From 98f9d442b44dbe2e3e4b3c8296be7e78d5d05450 Mon Sep 17 00:00:00 2001
From: Harald Welte <laforge@gnumonks.org>
Date: Sun, 24 Jul 2011 09:39:28 +0200
Subject: initial import of the usb ccid example for the sam7s

---
 at91lib/usb/device/ccid/cciddriver.c               | 1503 +++++++++++++++++
 at91lib/usb/device/ccid/cciddriver.h               |  378 +++++
 at91lib/usb/device/ccid/cciddriverdescriptors.h    |  152 ++
 at91lib/usb/device/core/USBD.h                     |  187 +++
 at91lib/usb/device/core/USBDCallbacks.h            |   65 +
 .../usb/device/core/USBDCallbacks_Initialized.c    |   62 +
 at91lib/usb/device/core/USBDCallbacks_Reset.c      |   47 +
 at91lib/usb/device/core/USBDDriver.c               |  682 ++++++++
 at91lib/usb/device/core/USBDDriver.h               |   93 ++
 at91lib/usb/device/core/USBDDriverCallbacks.h      |   61 +
 at91lib/usb/device/core/USBDDriverCb_CfgChanged.c  |   49 +
 .../device/core/USBDDriverCb_IfSettingChanged.c    |   52 +
 at91lib/usb/device/core/USBDDriverDescriptors.h    |   86 +
 at91lib/usb/device/core/USBD_OTGHS.c               | 1677 +++++++++++++++++++
 at91lib/usb/device/core/USBD_UDP.c                 | 1224 ++++++++++++++
 at91lib/usb/device/core/USBD_UDPHS.c               | 1680 ++++++++++++++++++++
 16 files changed, 7998 insertions(+)
 create mode 100644 at91lib/usb/device/ccid/cciddriver.c
 create mode 100644 at91lib/usb/device/ccid/cciddriver.h
 create mode 100644 at91lib/usb/device/ccid/cciddriverdescriptors.h
 create mode 100644 at91lib/usb/device/core/USBD.h
 create mode 100644 at91lib/usb/device/core/USBDCallbacks.h
 create mode 100644 at91lib/usb/device/core/USBDCallbacks_Initialized.c
 create mode 100644 at91lib/usb/device/core/USBDCallbacks_Reset.c
 create mode 100644 at91lib/usb/device/core/USBDDriver.c
 create mode 100644 at91lib/usb/device/core/USBDDriver.h
 create mode 100644 at91lib/usb/device/core/USBDDriverCallbacks.h
 create mode 100644 at91lib/usb/device/core/USBDDriverCb_CfgChanged.c
 create mode 100644 at91lib/usb/device/core/USBDDriverCb_IfSettingChanged.c
 create mode 100644 at91lib/usb/device/core/USBDDriverDescriptors.h
 create mode 100644 at91lib/usb/device/core/USBD_OTGHS.c
 create mode 100644 at91lib/usb/device/core/USBD_UDP.c
 create mode 100644 at91lib/usb/device/core/USBD_UDPHS.c

(limited to 'at91lib/usb/device')

diff --git a/at91lib/usb/device/ccid/cciddriver.c b/at91lib/usb/device/ccid/cciddriver.c
new file mode 100644
index 0000000..a23fc21
--- /dev/null
+++ b/at91lib/usb/device/ccid/cciddriver.c
@@ -0,0 +1,1503 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+/// 
+/// CCID driver
+/// 
+/// !Usage
+/// 
+/// Explanation on the usage of the code made available through the header file.
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//       Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <utility/trace.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/device/ccid/cciddriver.h>
+#include <usb/device/ccid/cciddriverdescriptors.h>
+#include <iso7816/iso7816_4.h>
+#include <string.h>
+
+//------------------------------------------------------------------------------
+//         Local definition
+//------------------------------------------------------------------------------
+
+/// Constants: IDs: Device product ID.
+#define CCIDDriverDescriptors_PRODUCTID       0x6129
+/// Constants: IDs: Device vendor ID.
+#define CCIDDriverDescriptors_VENDORID        0x03EB
+/// Constants: IDs: Device release number.
+#define CCIDDriverDescriptors_RELEASE         0x0100
+
+/// Returns the minimum between two values.
+#define MIN(a, b)       ((a < b) ? a : b)
+
+//------------------------------------------------------------------------------
+//         Types
+//------------------------------------------------------------------------------
+
+/// CCIDDriverConfiguration Descriptors
+/// List of descriptors that make up the configuration descriptors of a
+/// device using the CCID driver.
+typedef struct {
+
+    /// Configuration descriptor
+    USBConfigurationDescriptor configuration;
+    /// Interface descriptor
+    USBInterfaceDescriptor     interface;
+    /// CCID descriptor
+    CCIDDescriptor             ccid;
+    /// Bulk OUT endpoint descriptor
+    USBEndpointDescriptor      bulkOut;
+    /// Bulk IN endpoint descriptor
+    USBEndpointDescriptor      bulkIn;
+    /// Interrupt OUT endpoint descriptor
+    USBEndpointDescriptor      interruptIn;
+
+} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+//         Types
+//------------------------------------------------------------------------------
+
+/// Driver structure for an CCID device
+typedef struct {
+
+    /// Standard USB device driver instance
+    USBDDriver             usbdDriver;
+    /// CCID message
+    S_ccid_bulk_in_header  sCcidMessage;
+    /// CCID command
+    S_ccid_bulk_out_header sCcidCommand;
+    /// Interrupt message answer
+    unsigned char          BufferINT[4];
+    /// Buffer data of message
+    unsigned char          ProtocolDataStructure[10];
+    /// Protocol used
+    unsigned char          bProtocol;
+    /// SlotStatus
+    /// Bit 0 = Slot 0 current state
+    /// Bit 1 = Slot 0 changed status
+    /// Bit 2 = Slot 1 current state
+    /// Bit 3 = Slot 1 changed status
+    /// Bit 4 = Slot 2 current state
+    /// Bit 5 = Slot 2 changed status
+    unsigned char          SlotStatus;
+
+} CCIDDriver;
+
+//------------------------------------------------------------------------------
+//         Local variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the CCID device driver.
+static CCIDDriver ccidDriver;
+
+/// Standard USB device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+    sizeof(USBDeviceDescriptor),
+    USBGenericDescriptor_DEVICE,
+    USBDeviceDescriptor_USB2_00,
+    0,
+    0,
+    0,
+    BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+    CCIDDriverDescriptors_VENDORID,
+    CCIDDriverDescriptors_PRODUCTID,
+    CCIDDriverDescriptors_RELEASE,
+    1, // Index of manufacturer description
+    2, // Index of product description
+    3, // Index of serial number description
+    1  // One possible configuration
+};
+
+
+/// List of configuration descriptors.
+static const CCIDDriverConfigurationDescriptors configurationDescriptorsFS = {
+
+    // Standard USB configuration descriptor
+    {
+        sizeof(USBConfigurationDescriptor),
+        USBGenericDescriptor_CONFIGURATION,
+        sizeof(CCIDDriverConfigurationDescriptors),
+        1, // One interface in this configuration
+        1, // This is configuration #1
+        0, // No associated string descriptor
+        BOARD_USB_BMATTRIBUTES,
+        USBConfigurationDescriptor_POWER(100)
+    },
+    // CCID interface descriptor
+    // Table 4.3-1 Interface Descriptor
+    // Interface descriptor
+    {
+        sizeof(USBInterfaceDescriptor),
+        USBGenericDescriptor_INTERFACE,
+        0,                       // Interface 0
+        0,                       // No alternate settings
+        3,                       // uses bulk-IN, bulk-OUT and interrupt�IN
+        SMART_CARD_DEVICE_CLASS,
+        0,                       // Subclass code
+        0,                       // bulk transfers optional interrupt-IN
+        0                        // No associated string descriptor
+    },
+    {
+        sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+        CCID_DECRIPTOR_TYPE,    // bDescriptorType:Functional descriptor type
+        CCID1_10,               // bcdCCID: CCID version
+        0,               // bMaxSlotIndex: Value 0 indicates that one slot is supported
+        VOLTS_5_0,       // bVoltageSupport
+        PROTOCOL_TO,     // dwProtocols
+        3580,            // dwDefaultClock
+        3580,            // dwMaxClock
+        0,               // bNumClockSupported
+        9600,            // dwDataRate : 9600 bauds
+        9600,            // dwMaxDataRate : 9600 bauds
+        0,               // bNumDataRatesSupported
+        0xfe,            // dwMaxIFSD
+        0,               // dwSynchProtocols
+        0,               // dwMechanical
+        //0x00010042,      // dwFeatures: Short APDU level exchanges
+        CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+        0x0000010F,      // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+        0xFF,            // bClassGetResponse: Echoes the class of the APDU
+        0xFF,            // bClassEnvelope: Echoes the class of the APDU
+        0,               // wLcdLayout: no LCD
+        0,               // bPINSupport: No PIN
+        1                // bMaxCCIDBusySlot
+    },
+    // Bulk-OUT endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+            USBEndpointDescriptor_MAXBULKSIZE_FS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Bulk-IN endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+            USBEndpointDescriptor_MAXBULKSIZE_FS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Notification endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+        USBEndpointDescriptor_INTERRUPT,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+            USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+        0x10                              
+    }
+};
+
+#ifdef BOARD_USB_UDPHS
+static const CCIDDriverConfigurationDescriptors configurationDescriptorsHS = {
+
+    // Standard USB configuration descriptor
+    {
+        sizeof(USBConfigurationDescriptor),
+        USBGenericDescriptor_CONFIGURATION,
+        sizeof(CCIDDriverConfigurationDescriptors),
+        1, // One interface in this configuration
+        1, // This is configuration #1
+        0, // No associated string descriptor
+        BOARD_USB_BMATTRIBUTES,
+        USBConfigurationDescriptor_POWER(100)
+    },
+    // CCID interface descriptor
+    // Table 4.3-1 Interface Descriptor
+    // Interface descriptor
+    {
+        sizeof(USBInterfaceDescriptor),
+        USBGenericDescriptor_INTERFACE,
+        0,                       // Interface 0
+        0,                       // No alternate settings
+        3,                       // uses bulk-IN, bulk-OUT and interrupt�IN
+        SMART_CARD_DEVICE_CLASS,
+        0,                       // Subclass code
+        0,                       // bulk transfers optional interrupt-IN
+        0                        // No associated string descriptor
+    },
+    {
+        sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+        CCID_DECRIPTOR_TYPE,    // bDescriptorType:Functional descriptor type
+        CCID1_10,               // bcdCCID: CCID version
+        0,               // bMaxSlotIndex: Value 0 indicates that one slot is supported
+        VOLTS_5_0,       // bVoltageSupport
+        PROTOCOL_TO,     // dwProtocols
+        3580,            // dwDefaultClock
+        3580,            // dwMaxClock
+        0,               // bNumClockSupported
+        9600,            // dwDataRate : 9600 bauds
+        9600,            // dwMaxDataRate : 9600 bauds
+        0,               // bNumDataRatesSupported
+        0xfe,            // dwMaxIFSD
+        0,               // dwSynchProtocols
+        0,               // dwMechanical
+        //0x00010042,      // dwFeatures: Short APDU level exchanges
+        CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+        0x0000010F,      // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+        0xFF,            // bClassGetResponse: Echoes the class of the APDU
+        0xFF,            // bClassEnvelope: Echoes the class of the APDU
+        0,               // wLcdLayout: no LCD
+        0,               // bPINSupport: No PIN
+        1                // bMaxCCIDBusySlot
+    },
+    // Bulk-OUT endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+            USBEndpointDescriptor_MAXBULKSIZE_HS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Bulk-IN endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+            USBEndpointDescriptor_MAXBULKSIZE_HS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Notification endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+        USBEndpointDescriptor_INTERRUPT,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+            USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
+        0x10                              
+    }
+};
+
+/// Qualifier descriptor
+const USBDeviceQualifierDescriptor deviceQualifierDescriptor = {
+
+    sizeof(USBDeviceQualifierDescriptor),  // Size of this descriptor in bytes
+    USBGenericDescriptor_DEVICEQUALIFIER,  // Qualifier Descriptor Type
+    USBDeviceDescriptor_USB2_00,           // USB specification 2.00
+    0x00,                                  // Class is specified in interface
+    0x00,                                  // Subclass is specified in interface
+    0x00,                                  // Protocol is specified in interface
+    BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),    
+    0x01,                                  // One possible configuration
+    0x00                                   // Reserved for future use, must be zero
+};
+
+/// OtherSpeed configuration descriptor in Full Speed mode
+static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationFS = {
+
+    // Standard USB configuration descriptor
+    {
+        sizeof(USBConfigurationDescriptor),
+        USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+        sizeof(CCIDDriverConfigurationDescriptors),
+        1, // One interface in this configuration
+        1, // This is configuration #1
+        0, // No associated string descriptor
+        BOARD_USB_BMATTRIBUTES,
+        USBConfigurationDescriptor_POWER(100)
+    },
+    // CCID interface descriptor
+    // Table 4.3-1 Interface Descriptor
+    // Interface descriptor
+    {
+        sizeof(USBInterfaceDescriptor),
+        USBGenericDescriptor_INTERFACE,
+        0,                       // Interface 0
+        0,                       // No alternate settings
+        3,                       // uses bulk-IN, bulk-OUT and interrupt�IN
+        SMART_CARD_DEVICE_CLASS,
+        0,                       // Subclass code
+        0,                       // bulk transfers optional interrupt-IN
+        0                        // No associated string descriptor
+    },
+    {
+        sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+        CCID_DECRIPTOR_TYPE,    // bDescriptorType:Functional descriptor type
+        CCID1_10,               // bcdCCID: CCID version
+        0,               // bMaxSlotIndex: Value 0 indicates that one slot is supported
+        VOLTS_5_0,       // bVoltageSupport
+        PROTOCOL_TO,     // dwProtocols
+        3580,            // dwDefaultClock
+        3580,            // dwMaxClock
+        0,               // bNumClockSupported
+        9600,            // dwDataRate : 9600 bauds
+        9600,            // dwMaxDataRate : 9600 bauds
+        0,               // bNumDataRatesSupported
+        0xfe,            // dwMaxIFSD
+        0,               // dwSynchProtocols
+        0,               // dwMechanical
+        //0x00010042,      // dwFeatures: Short APDU level exchanges
+        CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+        0x0000010F,      // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+        0xFF,            // bClassGetResponse: Echoes the class of the APDU
+        0xFF,            // bClassEnvelope: Echoes the class of the APDU
+        0,               // wLcdLayout: no LCD
+        0,               // bPINSupport: No PIN
+        1                // bMaxCCIDBusySlot
+    },
+    // Bulk-OUT endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+            USBEndpointDescriptor_MAXBULKSIZE_FS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Bulk-IN endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+            USBEndpointDescriptor_MAXBULKSIZE_FS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Notification endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+        USBEndpointDescriptor_INTERRUPT,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+            USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+        0x10                              
+    }
+};
+
+/// OtherSpeed configuration descriptor in High Speed mode
+static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationHS = {
+
+    // Standard USB configuration descriptor
+    {
+        sizeof(USBConfigurationDescriptor),
+        USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+        sizeof(CCIDDriverConfigurationDescriptors),
+        1, // One interface in this configuration
+        1, // This is configuration #1
+        0, // No associated string descriptor
+        BOARD_USB_BMATTRIBUTES,
+        USBConfigurationDescriptor_POWER(100)
+    },
+    // CCID interface descriptor
+    // Table 4.3-1 Interface Descriptor
+    // Interface descriptor
+    {
+        sizeof(USBInterfaceDescriptor),
+        USBGenericDescriptor_INTERFACE,
+        0,                       // Interface 0
+        0,                       // No alternate settings
+        3,                       // uses bulk-IN, bulk-OUT and interrupt�IN
+        SMART_CARD_DEVICE_CLASS,
+        0,                       // Subclass code
+        0,                       // bulk transfers optional interrupt-IN
+        0                        // No associated string descriptor
+    },
+    {
+        sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+        CCID_DECRIPTOR_TYPE,    // bDescriptorType:Functional descriptor type
+        CCID1_10,               // bcdCCID: CCID version
+        0,               // bMaxSlotIndex: Value 0 indicates that one slot is supported
+        VOLTS_5_0,       // bVoltageSupport
+        PROTOCOL_TO,     // dwProtocols
+        3580,            // dwDefaultClock
+        3580,            // dwMaxClock
+        0,               // bNumClockSupported
+        9600,            // dwDataRate : 9600 bauds
+        9600,            // dwMaxDataRate : 9600 bauds
+        0,               // bNumDataRatesSupported
+        0xfe,            // dwMaxIFSD
+        0,               // dwSynchProtocols
+        0,               // dwMechanical
+        //0x00010042,      // dwFeatures: Short APDU level exchanges
+        CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+        0x0000010F,      // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+        0xFF,            // bClassGetResponse: Echoes the class of the APDU
+        0xFF,            // bClassEnvelope: Echoes the class of the APDU
+        0,               // wLcdLayout: no LCD
+        0,               // bPINSupport: No PIN
+        1                // bMaxCCIDBusySlot
+    },
+    // Bulk-OUT endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+            USBEndpointDescriptor_MAXBULKSIZE_HS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Bulk-IN endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+        USBEndpointDescriptor_BULK,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+            USBEndpointDescriptor_MAXBULKSIZE_HS),
+        0x00                               // Does not apply to Bulk endpoints
+    },
+    // Notification endpoint descriptor
+    {
+        sizeof(USBEndpointDescriptor),
+        USBGenericDescriptor_ENDPOINT,
+        USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+        USBEndpointDescriptor_INTERRUPT,
+        MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+            USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
+        0x10                              
+    }
+};
+#endif
+
+/// Language ID string descriptor.
+static const unsigned char languageIdDescriptor[] = {
+
+    USBStringDescriptor_LENGTH(1),
+    USBGenericDescriptor_STRING,
+    USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static const unsigned char manufacturerDescriptor[] = {
+
+    USBStringDescriptor_LENGTH(5),
+    USBGenericDescriptor_STRING,
+    USBStringDescriptor_UNICODE('A'),
+    USBStringDescriptor_UNICODE('T'),
+    USBStringDescriptor_UNICODE('M'),
+    USBStringDescriptor_UNICODE('E'),
+    USBStringDescriptor_UNICODE('L')
+};
+
+/// Product name.
+static const unsigned char productDescriptor[] = {
+
+    USBStringDescriptor_LENGTH(23),
+    USBGenericDescriptor_STRING,
+    USBStringDescriptor_UNICODE('A'),
+    USBStringDescriptor_UNICODE('T'),
+    USBStringDescriptor_UNICODE('M'),
+    USBStringDescriptor_UNICODE('E'),
+    USBStringDescriptor_UNICODE('L'),
+    USBStringDescriptor_UNICODE(' '),
+    USBStringDescriptor_UNICODE('A'),
+    USBStringDescriptor_UNICODE('T'),
+    USBStringDescriptor_UNICODE('9'),
+    USBStringDescriptor_UNICODE('1'),
+    USBStringDescriptor_UNICODE(' '),
+    USBStringDescriptor_UNICODE('C'),
+    USBStringDescriptor_UNICODE('C'),
+    USBStringDescriptor_UNICODE('I'),
+    USBStringDescriptor_UNICODE('D'),
+    USBStringDescriptor_UNICODE(' '),
+    USBStringDescriptor_UNICODE('D'),
+    USBStringDescriptor_UNICODE('R'),
+    USBStringDescriptor_UNICODE('I'),
+    USBStringDescriptor_UNICODE('V'),
+    USBStringDescriptor_UNICODE('E'),
+    USBStringDescriptor_UNICODE('R'),
+    USBStringDescriptor_UNICODE(' ')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+    USBStringDescriptor_LENGTH(12),
+    USBGenericDescriptor_STRING,
+    USBStringDescriptor_UNICODE('0'),
+    USBStringDescriptor_UNICODE('1'),
+    USBStringDescriptor_UNICODE('2'),
+    USBStringDescriptor_UNICODE('3'),
+    USBStringDescriptor_UNICODE('4'),
+    USBStringDescriptor_UNICODE('5'),
+    USBStringDescriptor_UNICODE('6'),
+    USBStringDescriptor_UNICODE('7'),
+    USBStringDescriptor_UNICODE('8'),
+    USBStringDescriptor_UNICODE('9'),
+    USBStringDescriptor_UNICODE('A'),
+    USBStringDescriptor_UNICODE('F')
+};
+
+/// Array of pointers to string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+    languageIdDescriptor,
+    manufacturerDescriptor,
+    productDescriptor,
+    serialNumberDescriptor
+};
+
+
+/// List of standard descriptors for the serial driver.
+const USBDDriverDescriptors ccidDriverDescriptors = {
+
+    &deviceDescriptor, // FS
+    (USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#ifdef BOARD_USB_UDPHS
+    (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // FS
+    (USBConfigurationDescriptor *) &sOtherSpeedConfigurationFS,
+    &deviceDescriptor, // HS
+    (USBConfigurationDescriptor *) &configurationDescriptorsHS,
+    (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // HS
+    (USBConfigurationDescriptor *) &sOtherSpeedConfigurationHS,
+#else
+    0, // No qualifier descriptor FS
+    0, // No other-speed configuration FS
+    0, // No device descriptor HS
+    0, // No configuration HS
+    0, // No qualifier descriptor HS
+    0, // No other-speed configuration HS
+#endif
+    stringDescriptors,
+    4 // Four string descriptors in array
+};
+
+//------------------------------------------------------------------------------
+//      Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Return the Slot Status to the host
+/// Answer to:
+///   PC_to_RDR_IccPowerOff
+///   PC_to_RDR_GetSlotStatus
+///   PC_to_RDR_IccClock
+///   PC_to_RDR_T0APDU
+///   PC_to_RDR_Mechanical
+///   PC_to_RDR_Abort and Class specific ABORT request
+//------------------------------------------------------------------------------
+static void RDRtoPCSlotStatus( void )
+{
+    TRACE_DEBUG("RDRtoPCSlotStatus\n\r");
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
+    ccidDriver.sCcidMessage.wLength   = 0;
+    ccidDriver.sCcidMessage.bStatus   = ccidDriver.SlotStatus;
+    ccidDriver.sCcidMessage.bError    = 0;
+    // 00h Clock running
+    // 01h Clock stopped in state L
+    // 02h Clock stopped in state H
+    // 03h Clock stopped in an unknown state
+    // All other values are Reserved for Future Use.
+    ccidDriver.sCcidMessage.bSpecific = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to PC_to_RDR_IccPowerOn
+//------------------------------------------------------------------------------
+static void RDRtoPCDatablock_ATR( void )
+{
+    unsigned char i;
+    unsigned char Atr[ATR_SIZE_MAX];
+    unsigned char length;
+
+    //TRACE_DEBUG("RDRtoPCDatablock\n\r");
+
+    ISO7816_Datablock_ATR( Atr, &length );
+
+    if( length > 5 ) {
+        ccidDriver.ProtocolDataStructure[1] = Atr[5]&0x0F; // TD(1)
+        ccidDriver.bProtocol = Atr[5]&0x0F;           // TD(1)
+    }
+
+    // S_ccid_protocol_t0
+    // bmFindexDindex
+    ccidDriver.ProtocolDataStructure[0] = Atr[2];     // TA(1)
+
+    // bmTCCKST0
+    // For T=0 ,B0 � 0b, B7-2 � 000000b
+    // B1 � Convention used (b1=0 for direct, b1=1 for inverse)
+
+    // bGuardTimeT0
+    // Extra Guardtime between two characters. Add 0 to 254 etu to the normal 
+    // guardtime of 12etu. FFh is the same as 00h.
+    ccidDriver.ProtocolDataStructure[2] = Atr[4];     // TC(1)
+    // AT91C_BASE_US0->US_TTGR = 0;  // TC1
+
+    // bWaitingIntegerT0
+    // WI for T=0 used to define WWT
+    ccidDriver.ProtocolDataStructure[3] = Atr[7];     // TC(2)
+
+    // bClockStop
+    // ICC Clock Stop Support
+    // 00 = Stopping the Clock is not allowed
+    // 01 = Stop with Clock signal Low
+    // 02 = Stop with Clock signal High
+    // 03 = Stop with Clock either High or Low
+    ccidDriver.ProtocolDataStructure[4] = 0x00;       // 0 to 3
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
+    ccidDriver.sCcidMessage.wLength      = length;  // Size of ATR
+    ccidDriver.sCcidMessage.bSizeToSend += length;  // Size of ATR
+    // bChainParameter: 00 the response APDU begins and ends in this command
+    ccidDriver.sCcidMessage.bSpecific    = 0;
+
+    for( i=0; i<length; i++ ) {
+
+        ccidDriver.sCcidMessage.abData[i]  = Atr[i];
+    }
+
+    // Set the slot to an active status
+    ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// In other cases, the response message has the following format: 
+/// The response data will contain the optional data returned by the ICC, 
+/// followed by the 2 byte-size status words SW1-SW2.
+///
+/// Answer to:
+///   PC_to_RDR_XfrBlock
+///   PC_to_RDR_Secure
+//------------------------------------------------------------------------------
+static void RDRtoPCDatablock( void )
+{
+    //TRACE_DEBUG("RDRtoPCDatablock\n\r");
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
+    ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
+    // bChainParameter: 00 the response APDU begins and ends in this command
+    ccidDriver.sCcidMessage.bSpecific = 0;
+
+    // Set the slot to an active status
+    ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to:
+///   PC_to_RDR_GetParameters
+///   PC_to_RDR_ResetParameters
+///   PC_to_RDR_SetParameters
+//------------------------------------------------------------------------------
+static void RDRtoPCParameters( void )
+{
+    unsigned int i;
+
+    TRACE_DEBUG("RDRtoPCParameters\n\r");
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_PARAMETERS;
+
+    //ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError  = 0;
+
+    if( ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO ) {
+
+        // T=0
+        ccidDriver.sCcidMessage.wLength   = sizeof(S_ccid_protocol_t0);
+        ccidDriver.sCcidMessage.bSpecific = PROTOCOL_TO;
+    }
+    else {
+
+        // T=1
+        ccidDriver.sCcidMessage.wLength   = sizeof(S_ccid_protocol_t1);
+        ccidDriver.sCcidMessage.bSpecific = PROTOCOL_T1;
+    }
+
+    ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
+
+    for( i=0; i<ccidDriver.sCcidMessage.wLength; i++ ) {
+        ccidDriver.sCcidMessage.abData[i] = ccidDriver.ProtocolDataStructure[i];
+    }
+
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to:
+///   PC_to_RDR_Escape
+//------------------------------------------------------------------------------
+static void RDRtoPCEscape( unsigned char length, unsigned char *data_send_from_CCID )
+{
+    unsigned int i;
+
+    TRACE_DEBUG("RDRtoPCEscape\n\r");
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_ESCAPE;
+
+    ccidDriver.sCcidMessage.wLength   = length;
+
+    ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError  = 0;
+
+    ccidDriver.sCcidMessage.bSpecific = 0;  // bRFU
+
+    for( i=0; i<length; i++ ) {
+        ccidDriver.sCcidMessage.abData[i] = data_send_from_CCID[i];
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to: 
+///   PC_to_RDR_SetDataRateAndClockFrequency
+//------------------------------------------------------------------------------
+static void RDRtoPCDataRateAndClockFrequency( unsigned int dwClockFrequency, 
+                                       unsigned int dwDataRate )
+{
+    TRACE_DEBUG("RDRtoPCDataRateAndClockFrequency\n\r");
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATARATEANDCLOCKFREQUENCY;
+
+    ccidDriver.sCcidMessage.wLength   = 8;
+
+    ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError  = 0;
+
+    ccidDriver.sCcidMessage.bSpecific = 0;  // bRFU
+
+    ccidDriver.sCcidMessage.abData[0] = dwClockFrequency;
+    
+    ccidDriver.sCcidMessage.abData[4] = dwDataRate;
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// Power On Command - Cold Reset & Warm Reset 
+/// Return the ATR to the host
+//------------------------------------------------------------------------------
+static void PCtoRDRIccPowerOn( void )
+{
+    TRACE_DEBUG("PCtoRDRIccPowerOn\n\r");
+
+    if( CCID_FEATURES_AUTO_VOLT == (configurationDescriptorsFS.ccid.dwFeatures & CCID_FEATURES_AUTO_VOLT) ) {
+
+        // bPowerSelect = ccidDriver.sCcidCommand.bSpecific_0;
+        ccidDriver.sCcidCommand.bSpecific_0 = VOLTS_AUTO;
+    }
+
+    ISO7816_cold_reset();
+
+    // for emulation only //JCB 
+    if ( ccidDriver.sCcidCommand.bSpecific_0 != VOLTS_5_0 ) {
+
+        TRACE_ERROR("POWER_NOT_SUPPORTED\n\r");
+    }
+
+    else {
+
+        RDRtoPCDatablock_ATR();
+
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// Power Off Command - Set the ICC in an inactive state
+/// Return the slot status to the host
+//------------------------------------------------------------------------------
+static void PCtoRDRIccPowerOff( void )
+{
+    unsigned char bStatus;
+
+    TRACE_DEBUG("PCtoRDRIccPowerOff\n\r");
+
+    ISO7816_IccPowerOff();
+
+    //JCB stub
+    bStatus = ICC_BS_PRESENT_NOTACTIVATED;
+
+    // Set the slot to an inactive status
+    ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError = 0;
+
+    // if error, see Table 6.1-2 errors
+
+    // Return the slot status to the host
+    RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// Get slot status
+//------------------------------------------------------------------------------
+static void PCtoRDRGetSlotStatus( void )
+{
+    TRACE_DEBUG("PCtoRDRGetSlotStatus\n\r");
+
+    ccidDriver.sCcidMessage.bStatus = 0;
+    ccidDriver.sCcidMessage.bError = 0;
+
+    // Return the slot status to the host
+    RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// If the command header is valid, an APDU command is received and can be read
+/// by the application
+//------------------------------------------------------------------------------
+static void PCtoRDRXfrBlock( void )
+{
+    unsigned char indexMessage = 0;
+    unsigned char i;
+
+    //TRACE_DEBUG("PCtoRDRXfrBlock\n\r");
+
+    i = 0;
+
+    // Check the block length
+    if ( ccidDriver.sCcidCommand.wLength > (configurationDescriptorsFS.ccid.dwMaxCCIDMessageLength-10) ) {
+
+        ccidDriver.sCcidMessage.bStatus = 1;
+        ccidDriver.sCcidMessage.bError  = 0;
+    }
+    // check bBWI
+    else if ( 0 != ccidDriver.sCcidCommand.bSpecific_0 ) {
+
+         TRACE_ERROR("Bad bBWI\n\r");
+    }
+    else {
+
+        // APDU or TPDU
+        switch(configurationDescriptorsFS.ccid.dwFeatures 
+              & (CCID_FEATURES_EXC_TPDU|CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU)) {
+
+            case CCID_FEATURES_EXC_TPDU:
+                if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO) {
+
+                    // Send commande APDU
+                    indexMessage = ISO7816_XfrBlockTPDU_T0( ccidDriver.sCcidCommand.APDU , 
+                                            ccidDriver.sCcidMessage.abData, 
+                                            ccidDriver.sCcidCommand.wLength );
+                }
+                else {
+                    if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_T1) {
+                        TRACE_INFO("Not supported T=1\n\r");
+                    }
+                    else {
+                        TRACE_INFO("Not supported\n\r");
+                    }
+                }
+                break;
+
+            case CCID_FEATURES_EXC_APDU:
+                TRACE_INFO("Not supported\n\r");
+                break;
+
+            default:
+                break;
+        }
+
+    }
+
+    ccidDriver.sCcidMessage.wLength = indexMessage;
+    TRACE_DEBUG("USB: 0x%X, 0x%X, 0x%X, 0x%X, 0x%X\n\r", ccidDriver.sCcidMessage.abData[0], 
+                                                                    ccidDriver.sCcidMessage.abData[1], 
+                                                                    ccidDriver.sCcidMessage.abData[2], 
+                                                                    ccidDriver.sCcidMessage.abData[3],
+                                                                    ccidDriver.sCcidMessage.abData[4] );
+     RDRtoPCDatablock();
+
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// return parameters by the command: RDR_to_PC_Parameters
+//------------------------------------------------------------------------------
+static void PCtoRDRGetParameters( void )
+{
+    TRACE_DEBUG("PCtoRDRGetParameters\n\r");
+
+    // We support only one slot
+
+    // bmIccStatus
+    if( ISO7816_StatusReset() ) {
+        // 0: An ICC is present and active (power is on and stable, RST is inactive
+        ccidDriver.sCcidMessage.bStatus = 0;
+    }
+    else {
+        // 1: An ICC is present and inactive (not activated or shut down by hardware error)
+        ccidDriver.sCcidMessage.bStatus = 1;
+    }
+
+    RDRtoPCParameters();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command resets the slot parameters to their default values
+//------------------------------------------------------------------------------
+static void PCtoRDRResetParameters( void )
+{
+    TRACE_DEBUG("PCtoRDRResetParameters\n\r");
+
+    ccidDriver.SlotStatus = ICC_NOT_PRESENT;
+    ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
+
+    RDRtoPCParameters();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used to change the parameters for a given slot.
+//------------------------------------------------------------------------------
+static void PCtoRDRSetParameters( void )
+{
+    TRACE_DEBUG("PCtoRDRSetParameters\n\r");
+
+    ccidDriver.SlotStatus = ccidDriver.sCcidCommand.bSlot;
+    ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
+    // Not all feature supported
+
+    RDRtoPCParameters();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command allows the CCID manufacturer to define and access extended 
+/// features. 
+/// Information sent via this command is processed by the CCID control logic.
+//------------------------------------------------------------------------------
+static void PCtoRDREscape( void )
+{
+    TRACE_DEBUG("PCtoRDREscape\n\r");
+
+    // If needed by the user
+    ISO7816_Escape();
+
+    // stub, return all value send
+    RDRtoPCEscape( ccidDriver.sCcidCommand.wLength, ccidDriver.sCcidCommand.APDU);    
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command stops or restarts the clock.
+//------------------------------------------------------------------------------
+static void PCtoRDRICCClock( void )
+{
+    TRACE_DEBUG("PCtoRDRICCClock\n\r");
+
+    if( 0 == ccidDriver.sCcidCommand.bSpecific_0 ) {
+        // restarts the clock
+        ISO7816_RestartClock();
+    }
+    else {
+        // stop clock in the state shown in the bClockStop field
+        ISO7816_StopClock();
+    }
+
+    RDRtoPCSlotStatus( );    
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command changes the parameters used to perform the transportation of 
+/// APDU messages by the T=0 protocol. 
+//------------------------------------------------------------------------------
+static void PCtoRDRtoAPDU( void )
+{
+    unsigned char bmChanges;
+    unsigned char bClassGetResponse;
+    unsigned char bClassEnvelope;
+
+    TRACE_DEBUG("PCtoRDRtoAPDU\n\r");
+
+    if( configurationDescriptorsFS.ccid.dwFeatures == (CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU) ) {
+
+        bmChanges = ccidDriver.sCcidCommand.bSpecific_0;
+        bClassGetResponse = ccidDriver.sCcidCommand.bSpecific_1;
+        bClassEnvelope = ccidDriver.sCcidCommand.bSpecific_2;
+
+        ISO7816_toAPDU();
+    }
+
+    RDRtoPCSlotStatus();    
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This is a command message to allow entering the PIN for verification or
+/// modification.
+//------------------------------------------------------------------------------
+static void PCtoRDRSecure( void )
+{
+    TRACE_DEBUG("PCtoRDRSecure\n\r");
+
+    TRACE_DEBUG("For user\n\r");
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used to manage motorized type CCID functionality. 
+/// The Lock Card function is used to hold the ICC. 
+/// This prevents an ICC from being easily removed from the CCID. 
+/// The Unlock Card function is used to remove the hold initiated by the Lock 
+/// Card function
+//------------------------------------------------------------------------------
+static void PCtoRDRMechanical( void )
+{
+    TRACE_DEBUG("PCtoRDRMechanical\n\r");
+    TRACE_DEBUG("Not implemented\n\r");
+
+    RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used with the Control pipe Abort request to tell the CCID 
+/// to stop any current transfer at the specified slot and return to a state 
+/// where the slot is ready to accept a new command pipe Bulk-OUT message.
+//------------------------------------------------------------------------------
+static void PCtoRDRAbort( void )
+{
+    TRACE_DEBUG("PCtoRDRAbort\n\r");
+
+    RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used to manually set the data rate and clock frequency of 
+/// a specific slot.
+//------------------------------------------------------------------------------
+static void PCtoRDRSetDataRateAndClockFrequency( void )
+{
+    unsigned int dwClockFrequency;
+    unsigned int dwDataRate;
+
+    TRACE_DEBUG("PCtoRDRSetDatarateandClockFrequency\n\r");
+
+    dwClockFrequency = ccidDriver.sCcidCommand.APDU[0]
+                     + (ccidDriver.sCcidCommand.APDU[1]<<8)
+                     + (ccidDriver.sCcidCommand.APDU[2]<<16)
+                     + (ccidDriver.sCcidCommand.APDU[3]<<24);
+
+    dwDataRate = ccidDriver.sCcidCommand.APDU[4]
+               + (ccidDriver.sCcidCommand.APDU[5]<<8)
+               + (ccidDriver.sCcidCommand.APDU[6]<<16)
+               + (ccidDriver.sCcidCommand.APDU[7]<<24);
+
+    ISO7816_SetDataRateandClockFrequency( dwClockFrequency, dwDataRate );
+
+    RDRtoPCDataRateAndClockFrequency( dwClockFrequency, dwDataRate );
+
+}
+
+//------------------------------------------------------------------------------
+/// Report the CMD_NOT_SUPPORTED error to the host
+//------------------------------------------------------------------------------
+static void vCCIDCommandNotSupported( void )
+{
+    // Command not supported
+    // vCCIDReportError(CMD_NOT_SUPPORTED);
+
+    TRACE_DEBUG("CMD_NOT_SUPPORTED\n\r");
+
+    // Header fields settings
+    ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
+    ccidDriver.sCcidMessage.wLength      = 0;
+    ccidDriver.sCcidMessage.bSpecific    = 0;
+
+    ccidDriver.sCcidMessage.bStatus |= ICC_CS_FAILED;
+
+    // Send the response to the host
+    //vCCIDSendResponse();
+}
+
+//------------------------------------------------------------------------------
+/// Sent CCID response on USB
+//------------------------------------------------------------------------------
+static void vCCIDSendResponse( void )
+{
+    unsigned char bStatus;
+
+    do {
+        bStatus = USBD_Write( CCID_EPT_DATA_IN, (void*)&ccidDriver.sCcidMessage, 
+                              ccidDriver.sCcidMessage.bSizeToSend, 0, 0 );
+    }
+    while (bStatus != USBD_STATUS_SUCCESS);
+}
+
+
+//------------------------------------------------------------------------------
+///  Description: CCID Command dispatcher
+//------------------------------------------------------------------------------
+static void CCIDCommandDispatcher( void )
+{
+    unsigned char MessageToSend = 0;
+
+    //TRACE_DEBUG("Command: 0x%X 0x%x 0x%X 0x%X 0x%X 0x%X 0x%X\n\r\n\r",
+    //               (unsigned int)ccidDriver.sCcidCommand.bMessageType,
+    //               (unsigned int)ccidDriver.sCcidCommand.wLength,
+    //               (unsigned int)ccidDriver.sCcidCommand.bSlot,
+    //               (unsigned int)ccidDriver.sCcidCommand.bSeq,
+    //               (unsigned int)ccidDriver.sCcidCommand.bSpecific_0,
+    //               (unsigned int)ccidDriver.sCcidCommand.bSpecific_1,
+    //               (unsigned int)ccidDriver.sCcidCommand.bSpecific_2);
+
+    // Check the slot number
+    if ( ccidDriver.sCcidCommand.bSlot > 0 ) {
+
+        TRACE_ERROR("BAD_SLOT_NUMBER\n\r");
+    }
+
+    TRACE_DEBUG("typ=0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
+
+    ccidDriver.sCcidMessage.bStatus = 0;
+
+    ccidDriver.sCcidMessage.bSeq  = ccidDriver.sCcidCommand.bSeq;
+    ccidDriver.sCcidMessage.bSlot = ccidDriver.sCcidCommand.bSlot;
+
+    ccidDriver.sCcidMessage.bSizeToSend = sizeof(S_ccid_bulk_in_header)-(ABDATA_SIZE+1);
+
+
+    // Command dispatcher
+    switch ( ccidDriver.sCcidCommand.bMessageType ) {
+
+        case PC_TO_RDR_ICCPOWERON:
+            PCtoRDRIccPowerOn();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_ICCPOWEROFF:
+            PCtoRDRIccPowerOff();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_GETSLOTSTATUS:
+            PCtoRDRGetSlotStatus();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_XFRBLOCK:
+            PCtoRDRXfrBlock();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_GETPARAMETERS:
+            PCtoRDRGetParameters();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_RESETPARAMETERS:
+            PCtoRDRResetParameters();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_SETPARAMETERS:
+            PCtoRDRSetParameters();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_ESCAPE:
+            PCtoRDREscape();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_ICCCLOCK:
+            PCtoRDRICCClock();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_T0APDU:
+            // Only CCIDs reporting a short or extended APDU level in the dwFeatures 
+            // field of the CCID class descriptor may take this command into account.
+            if( (CCID_FEATURES_EXC_SAPDU == (CCID_FEATURES_EXC_SAPDU&configurationDescriptorsFS.ccid.dwFeatures))
+            || (CCID_FEATURES_EXC_APDU  == (CCID_FEATURES_EXC_APDU &configurationDescriptorsFS.ccid.dwFeatures)) ) {
+
+                // command supported
+                PCtoRDRtoAPDU();
+            }
+            else {
+                // command not supported
+                TRACE_DEBUG("PC_TO_RDR_T0APDU\n\r");
+                vCCIDCommandNotSupported();
+            }
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_SECURE:
+            PCtoRDRSecure();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_MECHANICAL:
+            PCtoRDRMechanical();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_ABORT:
+            PCtoRDRAbort();
+            MessageToSend = 1;
+            break;
+
+        case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
+            PCtoRDRSetDataRateAndClockFrequency();
+            MessageToSend = 1;
+            break;
+
+        default:
+            TRACE_DEBUG("default: 0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
+            vCCIDCommandNotSupported();
+            MessageToSend = 1;
+            break;
+
+    }
+
+    if( MessageToSend == 1 ) {
+        vCCIDSendResponse();
+    }
+}
+
+
+//------------------------------------------------------------------------------
+/// SETUP request handler for a CCID device
+/// \param pRequest Pointer to a USBGenericRequest instance
+//------------------------------------------------------------------------------
+static void CCID_RequestHandler(const USBGenericRequest *pRequest)
+{
+    TRACE_DEBUG("CCID_RHl\n\r");
+
+    // Check if this is a class request
+    if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_CLASS) {
+
+        // Check if the request is supported
+        switch (USBGenericRequest_GetRequest(pRequest)) {
+
+            case CCIDGenericRequest_ABORT:
+                TRACE_DEBUG("CCIDGenericRequest_ABORT\n\r");
+                break;
+
+            case CCIDGenericRequest_GET_CLOCK_FREQUENCIES:
+                TRACE_DEBUG("Not supported\n\r");
+                // A CCID with bNumClockSupported equal to 00h does not have 
+                // to support this request
+                break;
+
+            case CCIDGenericRequest_GET_DATA_RATES:
+                TRACE_DEBUG("Not supported\n\r");
+                // A CCID with bNumDataRatesSupported equal to 00h does not have 
+                // to support this request.
+                break;
+
+            default:
+                TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request (%d)\n\r",
+                                                    USBGenericRequest_GetRequest(pRequest));
+                USBD_Stall(0);
+        }
+    }
+
+    else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) {
+
+        // Forward request to the standard handler
+        USBDDriver_RequestHandler(&(ccidDriver.usbdDriver), pRequest);
+    }
+    else {
+
+        // Unsupported request type
+        TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request type (%d)\n\r",
+                                                    USBGenericRequest_GetType(pRequest));
+        USBD_Stall(0);
+    }
+}
+
+
+//------------------------------------------------------------------------------
+//      Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Optional callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+// not static function
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+    CCID_RequestHandler(request);
+}
+#endif
+
+
+//------------------------------------------------------------------------------
+/// Handles SmartCart request
+//------------------------------------------------------------------------------
+void CCID_SmartCardRequest( void )
+{
+    unsigned char bStatus;
+
+    do {
+
+        bStatus = CCID_Read( (void*)&ccidDriver.sCcidCommand,
+                             sizeof(S_ccid_bulk_out_header),
+                             (TransferCallback)&CCIDCommandDispatcher,
+                             (void*)0 );
+    } 
+    while (bStatus != USBD_STATUS_SUCCESS);
+
+}
+
+//------------------------------------------------------------------------------
+/// Initializes the CCID device driver.
+//------------------------------------------------------------------------------
+void CCIDDriver_Initialize( void )
+{
+    TRACE_DEBUG("CCID_Init\n\r");
+    USBDDriver_Initialize(&(ccidDriver.usbdDriver),
+                          &ccidDriverDescriptors,
+                          0); // Multiple interface settings not supported
+    USBD_Init();
+}
+
+//------------------------------------------------------------------------------
+/// Reads data from the Data OUT endpoint
+/// \param pBuffer   Buffer to store the received data
+/// \param dLength   data buffer length
+/// \param fCallback Optional callback function
+/// \param pArgument Optional parameter for the callback function
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Read(void *pBuffer,
+                        unsigned int dLength,
+                        TransferCallback fCallback,
+                        void *pArgument)
+{
+    return USBD_Read(CCID_EPT_DATA_OUT, pBuffer, dLength, fCallback, pArgument);
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through the Data IN endpoint
+/// \param pBuffer   Buffer holding the data to transmit
+/// \param dLength   Length of data buffer
+/// \param fCallback Optional callback function
+/// \param pArgument Optional parameter for the callback function
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Write(void *pBuffer,
+                         unsigned int dLength,
+                         TransferCallback fCallback,
+                         void *pArgument)
+{
+    return USBD_Write(CCID_EPT_DATA_IN, pBuffer, dLength, fCallback, pArgument);
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through the interrupt endpoint, ICC insertion event
+/// RDR_to_PC_NotifySlotChange
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Insertion( void )
+{
+    TRACE_DEBUG("CCID_Insertion\n\r");
+
+    // Build the Interrupt-IN message
+    ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
+    ccidDriver.BufferINT[1] = ICC_INSERTED_EVENT;
+    ccidDriver.SlotStatus   = ICC_INSERTED_EVENT;
+
+    // Notify the host that a ICC is inserted
+    return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 );
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through the interrupt endpoint, ICC removal event
+/// RDR_to_PC_NotifySlotChange
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Removal( void )
+{
+    TRACE_DEBUG("CCID_Removal\n\r");
+
+    // Build the Interrupt-IN message
+    ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
+    ccidDriver.BufferINT[1] = ICC_NOT_PRESENT;
+    ccidDriver.SlotStatus   = ICC_NOT_PRESENT;
+
+    // Notify the host that a ICC is inserted
+    return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 );
+}
+
+//------------------------------------------------------------------------------
+/// Interrupt-IN Messages
+/// This message is sent when any bit in the bHardwareErrorCode field is set. 
+/// If this message is sent when there is no �outstanding� command, the bSeq 
+/// field will be undefined.
+/// \param bSlot ICC slot number
+/// \param bSeq  Sequence number of the bulk OUT command when the hardware error
+/// occured
+/// \param bHardwareErrorCode Hardware error code
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char RDRtoPCHardwareError( unsigned char bSlot, 
+                                    unsigned char bSeq, 
+                                    unsigned char bHardwareErrorCode )
+{
+    TRACE_DEBUG("RDRtoPCHardwareError\n\r");
+
+    // Build the Interrupt-IN message
+    ccidDriver.BufferINT[0] = RDR_TO_PC_HARDWAREERROR;
+    ccidDriver.BufferINT[1] = bSlot;
+    ccidDriver.BufferINT[2] = bSeq;
+    ccidDriver.BufferINT[3] = bHardwareErrorCode;
+
+    // Notify the host that a ICC is inserted
+    return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 4, 0, 0 );
+}
+
+
diff --git a/at91lib/usb/device/ccid/cciddriver.h b/at91lib/usb/device/ccid/cciddriver.h
new file mode 100644
index 0000000..8bac286
--- /dev/null
+++ b/at91lib/usb/device/ccid/cciddriver.h
@@ -0,0 +1,378 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definition of methods for using a CCID device driver.
+/// 
+/// !Usage
+/// 
+/// -# CCIDDriver_Initialize
+/// -# CCID_Read
+/// -# CCID_Write
+/// -# CCID_SmartCardRequest
+/// -# CCID_Insertion
+/// -# CCID_Removal
+/// -# RDRtoPCHardwareError
+//------------------------------------------------------------------------------
+
+#ifndef CCID_DRIVER_H
+#define CCID_DRIVER_H
+
+/// For reference, the absolute maximum block size 
+/// for a TPDU T=0 block is 260 bytes (5 bytes command; 255 bytes data), or 
+/// for a TPDU T=1 block is 259 bytes, or 
+/// for a short APDU T=1 block is 261 bytes, or 
+/// for an extended APDU T=1 block is 65544 bytes.
+#define ABDATA_SIZE 260
+
+/// define protocol T=0
+#define PROTOCOL_TO 0
+/// define protocol T=1
+#define PROTOCOL_T1 1
+
+/// define for dwFeatures see Table 5.1-1 Smart Card Device Class Descriptors
+/// No special characteristics
+#define CCID_FEATURES_NADA       0x00000000
+/// Automatic parameter configuration based on ATR data
+#define CCID_FEATURES_AUTO_PCONF 0x00000002
+/// Automatic activation of ICC on inserting
+#define CCID_FEATURES_AUTO_ACTIV 0x00000004 
+/// Automatic ICC voltage selection
+#define CCID_FEATURES_AUTO_VOLT  0x00000008 
+/// Automatic ICC clock frequency change according to active parameters provided 
+/// by the Host or self determined
+#define CCID_FEATURES_AUTO_CLOCK 0x00000010 
+/// Automatic baud rate change according to active parameters provided by the 
+/// Host or self determined
+#define CCID_FEATURES_AUTO_BAUD  0x00000020 
+/// Automatic parameters negotiation made by the CCID (use of warm or cold 
+/// resets or PPS according to a manufacturer proprietary algorithm to select 
+/// the communication parameters with the ICC)
+#define CCID_FEATURES_AUTO_PNEGO 0x00000040 
+/// Automatic PPS made by the CCID according to the active parameters
+#define CCID_FEATURES_AUTO_PPS   0x00000080 
+/// CCID can set ICC in clock stop mode
+#define CCID_FEATURES_ICCSTOP    0x00000100 
+/// NAD value other than 00 accepted (T=1 protocol in use)
+#define CCID_FEATURES_NAD        0x00000200 
+/// Automatic IFSD exchange as first exchange (T=1 protocol in use)
+#define CCID_FEATURES_AUTO_IFSD  0x00000400 
+/// TPDU level exchanges with CCID
+#define CCID_FEATURES_EXC_TPDU   0x00010000 
+/// Short APDU level exchange with CCID
+#define CCID_FEATURES_EXC_SAPDU  0x00020000 
+/// Short and Extended APDU level exchange with CCID
+#define CCID_FEATURES_EXC_APDU   0x00040000 
+/// USB Wake up signaling supported on card insertion and removal
+#define CCID_FEATURES_WAKEUP     0x00100000 
+
+//------------------------------------------------------------------------------
+//         Types
+//------------------------------------------------------------------------------
+
+/// Bulk CCID Message header structure
+typedef struct
+{
+   unsigned char bMessageType;
+   /// Message-specific data length
+   unsigned long wLength;
+   /// Identifies the slot number for this command
+   unsigned char bSlot;
+   /// Sequence number for command.
+   unsigned char bSeq;
+   /// Slot status register
+   unsigned char bStatus;
+   /// Slot error
+   unsigned char bError;
+   /// specific register
+   unsigned char bSpecific;
+   /// Data block sent to the CCID.
+   unsigned char abData[ABDATA_SIZE];
+   unsigned char bSizeToSend;
+} __attribute__ ((packed)) S_ccid_bulk_in_header;
+
+/// 6.1 Bulk Transfers
+typedef struct
+{
+   unsigned char bMessageType;
+   /// Message-specific data length
+   unsigned long wLength;
+   /// Identifies the slot number for this command
+   unsigned char bSlot;
+   /// Sequence number for command.
+   unsigned char bSeq;
+   /// specific register
+   unsigned char bSpecific_0;
+   unsigned char bSpecific_1;
+   unsigned char bSpecific_2;
+   /// Application Protocol Data Unit
+   unsigned char APDU[ABDATA_SIZE];
+} __attribute__ ((packed)) S_ccid_bulk_out_header;
+
+
+/// 6.1.11.2 PIN Verification Data Structure
+typedef struct
+{
+    /// Number of seconds.
+    unsigned char bTimerOut;
+    /// Several parameters for the PIN format options
+    unsigned char bmFormatString;
+    /// Define the length of the PIN to present in the APDU command
+    unsigned char bmPINBlockString;
+    /// Allows the length PIN insertion in the APDU command
+    unsigned char bmPINLengthFormat;
+    /// Minimum PIN size in digit and Maximum PIN size in digit
+    unsigned char wPINMaxExtraDigit;
+    /// The value is a bit wise OR operation.
+    unsigned char bEntryValidationCondition;
+    /// Number of messages to display for the PIN modify command
+    unsigned char bNumberMessage;
+    /// Language used to display the messages.
+    unsigned char wLangId;
+    /// Message index in the Reader message table
+    unsigned char bMsgIndex;
+    /// T=1 I-block prologue field to use
+    unsigned char bTeoPrologue[3];
+    /// APDU to send to the ICC
+    unsigned char abPINApdu[255];
+}__attribute__ ((packed)) S_ccid_PIN_Verification;
+
+
+/// 6.1.11.7 PIN Modification Data Structure
+typedef struct
+{
+    /// Number of seconds. If 00h then CCID default value is used.
+    unsigned char bTimeOut;
+    /// Several parameters for the PIN format options (defined in � 6.1.11.4)
+    unsigned char bmFormatString4;
+    /// Define the length of the PIN to present in the APDU command
+    unsigned char bmPINBlockString;
+    /// Allows the length PIN insertion in the APDU command (defined in � 6.1.11.6)
+    unsigned char bmPinLengthFormat;
+    /// Insertion position offset in byte for the current PIN
+    unsigned char bInsertionOffsetOld;
+    /// Insertion position offset in byte for the new PIN
+    unsigned char bInsertionOffsetNew;
+    /// XXYYh
+    /// XX: Minimum PIN size in digit
+    /// YY: Maximum PIN size in digit
+    unsigned char wPINMaxExtraDigit;
+    /// 00h,01h,02h,03h
+    /// Indicates if a confirmation is requested before acceptance of a new PIN (meaning that the user has to enter this new PIN twice before it is accepted)
+    /// Indicates if the current PIN must be entered and set in the same APDU field of not.
+    unsigned char bConfirmPIN;
+    /// The value is a bit wise OR operation.
+    /// 01h Max size reached
+    /// 02h Validation key pressed
+    /// 04h Timeout occurred
+    unsigned char bEntryValidationCondition;
+    /// 00h,01h,02h,03h,or FFh
+    /// Number of messages to display for the PIN modify command.
+    unsigned char bNumberMessage;
+    /// Language used to display the messages. The 16 bit
+    unsigned char wLangId;
+    /// Message index in the Reader message table (should be 00h or 01h).
+    unsigned char bMsgIndex1;
+    /// Message index in the Reader message table (should be 01h or 02h).
+    unsigned char bMsgIndex2;
+    /// Message index in the Reader message table (should be 02h).
+    unsigned char bMsgIndex3;
+    /// T=1 I-block prologue field to use. Significant only if protocol in use is T=1.
+    unsigned char bTeoPrologue[3];
+    /// Byte array APDU to send to the ICC
+    unsigned char abPINApdu[255];
+}__attribute__ ((packed)) S_ccid_PIN_Modification;
+
+/// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h)
+typedef struct
+{
+    /// B7-4 � FI � Index into the table 7 in ISO/IEC 7816-3:1997 selecting a 
+    /// clock rate conversion factor
+    /// B3-0 � DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a 
+    /// baud rate conversion factor
+    unsigned char bmFindexDindex;
+    /// For T=0 ,B0 � 0b, B7-2 � 000000b
+    /// B1 � Convention used (b1=0 for direct, b1=1 for inverse)
+    unsigned char bmTCCKST0;         // 0 to 2
+    /// Extra Guardtime between two characters. Add 0 to 254 etu to the normal 
+    /// guardtime of 12etu. FFh is the same as 00h.
+    unsigned char bGuardTimeT0;      // 0 to FF
+    /// WI for T=0 used to define WWT
+    unsigned char bWaitingIntegerT0; // 0 to FF
+    /// ICC Clock Stop Support
+    /// 00 = Stopping the Clock is not allowed
+    /// 01 = Stop with Clock signal Low
+    /// 02 = Stop with Clock signal High
+    /// 03 = Stop with Clock either High or Low
+    unsigned char bClockStop;        // 0 to 3
+} __attribute__ ((packed)) S_ccid_protocol_t0;
+
+
+/// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h)
+typedef struct
+{
+    /// B7-4 � FI � Index into the table 7 in ISO/IEC 7816-3:1997 selecting a 
+    /// clock rate conversion factor
+    /// B3-0 � DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a 
+    /// baud rate conversion factor
+    unsigned char bmFindexDindex;
+    /// For T=1, B7-2 � 000100b
+    /// B0 � Checksum type (b0=0 for LRC, b0=1 for CRC
+    /// B1 � Convention used (b1=0 for direct, b1=1 for inverse)
+    unsigned char bmTCCKST1;           // 10h, 11h, 12h, 13h
+    /// Extra Guardtime (0 to 254 etu between two characters). 
+    /// If value is FFh, then guardtime is reduced by 1.
+    unsigned char bGuardTimeT1;        // 0 to FF
+    /// B7-4 = BWI
+    /// B3-0 = CWI
+    unsigned char bmWaitingIntegersT1; // 0 to 9
+    /// ICC Clock Stop Support
+    /// 00 = Stopping the Clock is not allowed
+    /// 01 = Stop with Clock signal Low
+    /// 02 = Stop with Clock signal High
+    /// 03 = Stop with Clock either High or Low
+    unsigned char bClockStop;          // 0 to 3
+    /// Size of negotiated IFSC
+    unsigned char bIFSC;               // 0 to FE
+    /// Nad value used by CCID
+    unsigned char bNadValue;           // 0 to FF
+} __attribute__ ((packed)) S_ccid_protocol_t1;
+
+
+/// Identifies the length of type of subordinate descriptors of a CCID device
+/// Table 5.1-1 Smart Card Device Class descriptors
+typedef struct
+{
+   /// Size of this descriptor, in bytes.
+   unsigned char  bLength;
+   /// Functional Descriptor type
+   unsigned char  bDescriptorType;
+   /// Integrated Circuit(s) Cards Interface Devices (CCID) Specification 
+   /// Release Number
+   unsigned short bcdCCID;
+   /// Index of the highest available slot. An USB-ICC is regarded as a single
+   /// slot CCID.
+   unsigned char  bMaxSlotIndex;
+   /// This value indicates what voltages the CCID can supply to its slots.
+   /// It is a bitwise OR operation performed on the following values:
+   /// - 01h 5.0V
+   /// - 02h 3.0V
+   /// - 04h 1.8V
+   /// Other bits are RFU.
+   unsigned char  bVoltageSupport;
+   /// RRRR �Upper Word- is RFU = 0000h
+   /// PPPP �Lower Word- Encodes the supported protocol types. A �1� in a given
+   /// bit position indicates support for the associated ISO protocol.
+   /// 0001h = Protocol T=0
+   /// 0002h = Protocol T=1
+   /// All other bits are reserved and must be set to zero. The field is 
+   /// intended to correspond to the PCSC specification definitions. 
+   unsigned long  dwProtocols;
+   /// Default ICC clock frequency in KHz. This is an integer value.
+   unsigned long  dwDefaultClock;
+   /// Maximum supported ICC clock frequency in KHz. This is an integer value.
+   unsigned long  dwMaximumClock;
+   /// The number of clock frequencies that are supported by the CCID. If the 
+   /// value is 00h, the supported clock frequencies are assumed to be the 
+   /// default clock frequency defined by dwDefaultClock and the maximum clock 
+   /// frequency defined by dwMaximumClock.
+   unsigned char  bNumClockSupported;
+   /// Default ICC I/O data rate in bps. This is an integer value
+   unsigned long  dwDataRate;
+   /// Maximum supported ICC I/O data rate in bps
+   unsigned long  dwMaxDataRate;
+   /// The number of data rates that are supported by the CCID.
+   unsigned char  bNumDataRatesSupported;
+   /// Indicates the maximum IFSD supported by CCID for protocol T=1.
+   unsigned long  dwMaxIFSD;
+   /// - RRRR-Upper Word- is RFU = 0000h
+   /// - PPPP-Lower Word- encodes the supported protocol types. A �1� in a given
+   ///   bit position indicates support for the associated protocol.
+   ///   0001h indicates support for the 2-wire protocol 1
+   ///   0002h indicates support for the 3-wire protocol 1
+   ///   0004h indicates support for the I2C protocol 1
+   /// All other values are outside of this specification, and must be handled 
+   /// by vendor-supplied drivers.
+   unsigned long  dwSynchProtocols;
+   /// The value is a bitwise OR operation performed on the following values:
+   /// - 00000000h No special characteristics
+   /// - 00000001h Card accept mechanism 2
+   /// - 00000002h Card ejection mechanism 2
+   /// - 00000004h Card capture mechanism 2
+   /// - 00000008h Card lock/unlock mechanism
+   unsigned long  dwMechanical;
+   /// This value indicates what intelligent features the CCID has.
+   unsigned long  dwFeatures;
+   /// For extended APDU level the value shall be between 261 + 10 (header) and 
+   /// 65544 +10, otherwise the minimum value is the wMaxPacketSize of the 
+   /// Bulk-OUT endpoint.
+   unsigned long  dwMaxCCIDMessageLength;
+   /// Significant only for CCID that offers an APDU level for exchanges.
+   unsigned char  bClassGetResponse;
+   /// Significant only for CCID that offers an extended APDU level for exchanges.
+   unsigned char  bClassEnvelope;
+   /// Number of lines and characters for the LCD display used to send messages for PIN entry.
+   unsigned short wLcdLayout;
+   /// This value indicates what PIN support features the CCID has.
+   unsigned char  bPINSupport;
+   /// Maximum number of slots which can be simultaneously busy.
+   unsigned char  bMaxCCIDBusySlots;
+
+} __attribute__ ((packed)) CCIDDescriptor;
+
+//------------------------------------------------------------------------------
+//         Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char RDRtoPCHardwareError( unsigned char bSlot, 
+                                           unsigned char bSeq, 
+                                           unsigned char bHardwareErrorCode );
+
+#if !defined(NOAUTOCALLBACK)
+extern void USBDCallbacks_RequestReceived(const USBGenericRequest *pRequest);
+#endif
+extern void CCID_SmartCardRequest( void );
+extern void CCIDDriver_Initialize( void );
+extern unsigned char CCID_Read(void *pBuffer,
+                               unsigned int dLength,
+                               TransferCallback fCallback,
+                               void *pArgument);
+extern unsigned char CCID_Write(void *pBuffer,
+                                unsigned int dLength,
+                                TransferCallback fCallback,
+                                void *pArgument);
+extern unsigned char CCID_Insertion( void );
+extern unsigned char CCID_Removal( void );
+
+#endif //#ifndef CCID_DRIVER_H
+
diff --git a/at91lib/usb/device/ccid/cciddriverdescriptors.h b/at91lib/usb/device/ccid/cciddriverdescriptors.h
new file mode 100644
index 0000000..2daea67
--- /dev/null
+++ b/at91lib/usb/device/ccid/cciddriverdescriptors.h
@@ -0,0 +1,152 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//  Title: cciddriverdescriptors.h
+//
+//  About: Purpose
+//      Definitions of the descriptors required by the ccid device driver.
+//      DWG_Smart-Card_CCID_Rev110.pdf
+//------------------------------------------------------------------------------
+
+#ifndef CCID_DRIVER_DESCRIPTORS_H
+#define CCID_DRIVER_DESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+//         Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Constants: Endpoints
+//   CCID_EPT_DATA_OUT endpoint data out bulk     1
+//   CCID_EPT_DATA_IN endpoint data in bulk       2
+//   CCID_EPT_NOTIFICATION endpoint data interupt 3
+//------------------------------------------------------------------------------
+#define CCID_EPT_DATA_OUT       1  
+#define CCID_EPT_DATA_IN        2
+#define CCID_EPT_NOTIFICATION   3
+
+//------------------------------------------------------------------------------
+// USB-ICC protocol
+//------------------------------------------------------------------------------
+// CCID specification version 1.10
+#define CCID1_10                               0x0110
+
+#define SMART_CARD_DEVICE_CLASS                0x0B
+// Smart Card Device Class Descriptor Type
+#define CCID_DECRIPTOR_TYPE                    0x21
+
+// Table 5.3-1 Summary of CCID Class Specific Request
+#define CCIDGenericRequest_ABORT                 0x01
+#define CCIDGenericRequest_GET_CLOCK_FREQUENCIES 0x02
+#define CCIDGenericRequest_GET_DATA_RATES        0x03
+
+// 6.1 Command Pipe, Bulk-OUT Messages
+#define PC_TO_RDR_ICCPOWERON                   0x62
+#define PC_TO_RDR_ICCPOWEROFF                  0x63
+#define PC_TO_RDR_GETSLOTSTATUS                0x65
+#define PC_TO_RDR_XFRBLOCK                     0x6F
+#define PC_TO_RDR_GETPARAMETERS                0x6C
+#define PC_TO_RDR_RESETPARAMETERS              0x6D
+#define PC_TO_RDR_SETPARAMETERS                0x61
+#define PC_TO_RDR_ESCAPE                       0x6B
+#define PC_TO_RDR_ICCCLOCK                     0x6E
+#define PC_TO_RDR_T0APDU                       0x6A
+#define PC_TO_RDR_SECURE                       0x69
+#define PC_TO_RDR_MECHANICAL                   0x71
+#define PC_TO_RDR_ABORT                        0x72
+#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73
+
+// 6.2 Response Pipe, Bulk-IN Messages
+#define RDR_TO_PC_DATABLOCK                    0x80
+#define RDR_TO_PC_SLOTSTATUS                   0x81
+#define RDR_TO_PC_PARAMETERS                   0x82
+#define RDR_TO_PC_ESCAPE                       0x83
+#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY    0x84
+
+// 6.3 Interrupt-IN Messages
+#define RDR_TO_PC_NOTIFYSLOTCHANGE             0x50
+#define RDR_TO_PC_HARDWAREERROR                0x51
+
+// Table 6.2-2 Slot error register when bmCommandStatus = 1
+#define CMD_ABORTED                                   0xFF
+#define ICC_MUTE                                      0xFE
+#define XFR_PARITY_ERROR                              0xFD
+#define XFR_OVERRUN                                   0xFC
+#define HW_ERROR                                      0xFB
+#define BAD_ATR_TS                                    0xF8
+#define BAD_ATR_TCK                                   0xF7
+#define ICC_PROTOCOL_NOT_SUPPORTED                    0xF6
+#define ICC_CLASS_NOT_SUPPORTED                       0xF5
+#define PROCEDURE_BYTE_CONFLICT                       0xF4
+#define DEACTIVATED_PROTOCOL                          0xF3
+#define BUSY_WITH_AUTO_SEQUENCE                       0xF2
+#define PIN_TIMEOUT                                   0xF0
+#define PIN_CANCELLED                                 0xEF
+#define CMD_SLOT_BUSY                                 0xE0
+//      User defined                              0xC0 to 0x81
+//      Reserved for futur use                        0x80
+//      not supported incorrect message parameter 0x7F to 0x01
+//      Command not supported                         0x00
+
+// CCID rev 1.1, p.27
+#define VOLTS_AUTO                            0x00
+#define VOLTS_5_0                             0x01
+#define VOLTS_3_0                             0x02
+#define VOLTS_1_8                             0x03
+
+// 6.3.1 RDR_to_PC_NotifySlotChange
+#define ICC_NOT_PRESENT                       0x00
+#define ICC_PRESENT                           0x01
+#define ICC_CHANGE                            0x02
+#define ICC_INSERTED_EVENT                    ICC_PRESENT+ICC_CHANGE
+
+// ICCD: Table 6.1-8 Bitmap for bStatus field
+#define ICC_BS_PRESENT_ACTIVATED     0x00 // USB-ICC is present and activated
+#define ICC_BS_PRESENT_NOTACTIVATED  0x01 // USB-ICC is present but not activated
+#define ICC_BS_NOTPRESENT            0x02 // USB-ICC is virtually not present
+#define ICC_BS_RFU                   0x03 // RFU
+#define ICC_CS_NO_ERROR           (0x00<<6) // Processed without error
+#define ICC_CS_FAILED             (0x01<<6) // Failed, error condition given by bError
+#define ICC_CS_TIME_EXT           (0x02<<6) // Time extension is requested
+#define ICC_CS_RFU                (0x03<<6) // RFU
+
+/*
+#define NO_ERROR                               0x00
+#define NO_EXTRA_BYTES                         0x00
+#define CCID_FLAG_INITIAL_VALUE                0x05
+#define CCID_EVENT_SIZE                        0x02
+#define STATUS_MASK                            0x41
+*/
+//------------------------------------------------------------------------------
+//      Structures
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CCID_DRIVER_DESCRIPTORS_H
+
diff --git a/at91lib/usb/device/core/USBD.h b/at91lib/usb/device/core/USBD.h
new file mode 100644
index 0000000..6680e27
--- /dev/null
+++ b/at91lib/usb/device/core/USBD.h
@@ -0,0 +1,187 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+/// 
+/// Collection of methods for using the USB device controller on AT91
+/// microcontrollers.
+/// 
+/// !!!Usage
+/// 
+/// Please refer to the corresponding application note.
+/// - "AT91 USB device framework"
+/// - "USBD API" . "USBD API Methods"
+//------------------------------------------------------------------------------
+
+#ifndef USBD_H
+#define USBD_H
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+//      Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB device API return values"
+///
+/// This page lists the return values of the USB %device driver API
+///
+/// !Return codes
+/// - USBD_STATUS_SUCCESS
+/// - USBD_STATUS_LOCKED
+/// - USBD_STATUS_ABORTED
+/// - USBD_STATUS_RESET
+           
+/// Indicates the operation was successful.
+#define USBD_STATUS_SUCCESS             0
+/// Endpoint/device is already busy.
+#define USBD_STATUS_LOCKED              1
+/// Operation has been aborted.
+#define USBD_STATUS_ABORTED             2
+/// Operation has been aborted because the device has been reset.
+#define USBD_STATUS_RESET               3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB device states"
+///
+/// This page lists the %device states of the USB %device driver.
+///
+/// !States
+/// - USBD_STATE_SUSPENDED
+/// - USBD_STATE_ATTACHED
+/// - USBD_STATE_POWERED
+/// - USBD_STATE_DEFAULT
+/// - USBD_STATE_ADDRESS
+/// - USBD_STATE_CONFIGURED
+
+/// The device is currently suspended.
+#define USBD_STATE_SUSPENDED            0
+/// USB cable is plugged into the device.
+#define USBD_STATE_ATTACHED             1
+/// Host is providing +5V through the USB cable.
+#define USBD_STATE_POWERED              2
+/// Device has been reset.
+#define USBD_STATE_DEFAULT              3
+/// The device has been given an address on the bus.
+#define USBD_STATE_ADDRESS              4
+/// A valid configuration has been selected.
+#define USBD_STATE_CONFIGURED           5
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB device LEDs"
+///
+/// This page lists the LEDs used in the USB %device driver.
+///
+/// !LEDs
+/// - USBD_LEDPOWER
+/// - USBD_LEDUSB
+/// - USBD_LEDOTHER
+
+/// LED for indicating that the device is powered.
+#define USBD_LEDPOWER                   0
+/// LED for indicating USB activity.
+#define USBD_LEDUSB                     1
+/// LED for custom usage.
+#define USBD_LEDOTHER                   2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//         Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback used by transfer functions (USBD_Read & USBD_Write) to notify
+/// that a transaction is complete.
+//------------------------------------------------------------------------------
+typedef void (*TransferCallback)(void *pArg,
+                                 unsigned char status,
+                                 unsigned int transferred,
+                                 unsigned int remaining);
+
+//------------------------------------------------------------------------------
+//         Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBD_InterruptHandler(void);
+
+extern void USBD_Init(void);
+
+extern void USBD_Connect(void);
+
+extern void USBD_Disconnect(void);
+
+extern char USBD_Write(
+    unsigned char bEndpoint,
+    const void *pData,
+    unsigned int size,
+    TransferCallback callback,
+    void *pArg);
+
+extern char USBD_Read(
+    unsigned char bEndpoint,
+    void *pData,
+    unsigned int dLength,
+    TransferCallback fCallback,
+    void *pArg);
+
+extern unsigned char USBD_Stall(unsigned char bEndpoint);
+
+extern void USBD_Halt(unsigned char bEndpoint);
+
+extern void USBD_Unhalt(unsigned char bEndpoint);
+
+extern void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor);
+
+extern unsigned char USBD_IsHalted(unsigned char bEndpoint);
+
+extern void USBD_RemoteWakeUp(void);
+
+extern void USBD_SetAddress(unsigned char address);
+
+extern void USBD_SetConfiguration(unsigned char cfgnum);
+
+extern unsigned char USBD_GetState(void);
+
+extern unsigned char USBD_IsHighSpeed(void);
+
+extern void USBD_Test(unsigned char bIndex);
+
+#endif //#ifndef USBD_H
+
diff --git a/at91lib/usb/device/core/USBDCallbacks.h b/at91lib/usb/device/core/USBDCallbacks.h
new file mode 100644
index 0000000..d4d5c7e
--- /dev/null
+++ b/at91lib/usb/device/core/USBDCallbacks.h
@@ -0,0 +1,65 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+    Definitions of callbacks used by the USBD API to notify the user
+    application of incoming events. These functions are declared as 'weak',
+    so they can be re-implemented elsewhere in the application in a
+    transparent way.
+*/
+
+#ifndef USBDCALLBACKS_H
+#define USBDCALLBACKS_H
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+//         Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBDCallbacks_Initialized(void);
+
+extern void USBDCallbacks_Reset(void);
+
+extern void USBDCallbacks_Suspended(void);
+
+extern void USBDCallbacks_Resumed(void);
+
+extern void USBDCallbacks_RequestReceived(const USBGenericRequest *request);
+
+#endif //#ifndef USBDCALLBACKS_H
+
diff --git a/at91lib/usb/device/core/USBDCallbacks_Initialized.c b/at91lib/usb/device/core/USBDCallbacks_Initialized.c
new file mode 100644
index 0000000..9c84773
--- /dev/null
+++ b/at91lib/usb/device/core/USBDCallbacks_Initialized.c
@@ -0,0 +1,62 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include "USBDCallbacks.h"
+#include "USBD.h"
+#include <board.h>
+#include <aic/aic.h>
+
+//------------------------------------------------------------------------------
+//         Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Invoked after the USB driver has been initialized. By default, configures
+/// the UDP/UDPHS interrupt.
+//------------------------------------------------------------------------------
+void USBDCallbacks_Initialized(void)
+{
+#if defined(BOARD_USB_UDP)
+    // Configure and enable the UDP interrupt
+    AIC_ConfigureIT(AT91C_ID_UDP, 0, USBD_InterruptHandler);
+    AIC_EnableIT(AT91C_ID_UDP);
+
+#elif defined(BOARD_USB_UDPHS)
+    // Configure and enable the UDPHS interrupt
+    AIC_ConfigureIT(AT91C_ID_UDPHS, 0, USBD_InterruptHandler);
+    AIC_EnableIT(AT91C_ID_UDPHS);
+#else
+    #error Unsupported controller.
+#endif
+}
+
diff --git a/at91lib/usb/device/core/USBDCallbacks_Reset.c b/at91lib/usb/device/core/USBDCallbacks_Reset.c
new file mode 100644
index 0000000..64d9aaa
--- /dev/null
+++ b/at91lib/usb/device/core/USBDCallbacks_Reset.c
@@ -0,0 +1,47 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include "USBDCallbacks.h"
+
+//------------------------------------------------------------------------------
+//         Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Invoked when the USB driver is reset. Does nothing by default.
+//------------------------------------------------------------------------------
+void USBDCallbacks_Reset(void)
+{
+    // Does nothing
+}
+
diff --git a/at91lib/usb/device/core/USBDDriver.c b/at91lib/usb/device/core/USBDDriver.c
new file mode 100644
index 0000000..c2a8abd
--- /dev/null
+++ b/at91lib/usb/device/core/USBDDriver.c
@@ -0,0 +1,682 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//      Headers
+//------------------------------------------------------------------------------
+
+#include "USBDDriver.h"
+#include "USBDDriverCallbacks.h"
+#include "USBD.h"
+#include <board.h>
+#include <utility/trace.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBDeviceQualifierDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/common/core/USBSetAddressRequest.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/common/core/USBSetConfigurationRequest.h>
+#include <usb/common/core/USBInterfaceRequest.h>
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+//      Local functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Configures the device by setting it into the Configured state and
+/// initializing all endpoints.
+/// \param pDriver  Pointer to a USBDDriver instance.
+/// \param cfgnum  Configuration number to set.
+//------------------------------------------------------------------------------
+static void SetConfiguration(USBDDriver *pDriver, unsigned char cfgnum)
+{
+    USBEndpointDescriptor *pEndpoints[BOARD_USB_NUMENDPOINTS+1];
+    const USBConfigurationDescriptor *pConfiguration;
+
+    // Use different descriptor depending on device speed
+    if (USBD_IsHighSpeed()) {
+
+        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
+    }
+    else {
+
+        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
+    }
+
+    // Set & save the desired configuration
+    USBD_SetConfiguration(cfgnum);
+    pDriver->cfgnum = cfgnum;
+
+    // If the configuration is not 0, configure endpoints
+    if (cfgnum != 0) {
+    
+        // Parse configuration to get endpoint descriptors
+        USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);
+    
+        // Configure endpoints
+        int i = 0;
+        while (pEndpoints[i] != 0) {
+    
+            USBD_ConfigureEndpoint(pEndpoints[i]);
+            i++;
+        }
+    }
+    // Should be done before send the ZLP
+    USBDDriverCallbacks_ConfigurationChanged(cfgnum);
+
+    // Acknowledge the request
+    USBD_Write(0, // Endpoint #0
+               0, // No data buffer
+               0, // No data buffer
+               (TransferCallback) 0,
+               (void *)  0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current configuration number to the host.
+/// \param pDriver  Pointer to a USBDDriver instance.
+//------------------------------------------------------------------------------
+static void GetConfiguration(const USBDDriver *pDriver)
+{
+    USBD_Write(0, &(pDriver->cfgnum), 1, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current status of the device to the host.
+/// \param pDriver  Pointer to a USBDDriver instance.
+//------------------------------------------------------------------------------
+static void GetDeviceStatus(const USBDDriver *pDriver)
+{
+    unsigned short data = 0;
+    const USBConfigurationDescriptor *pConfiguration;
+
+    // Use different configuration depending on device speed
+    if (USBD_IsHighSpeed()) {
+
+        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
+    }
+    else {
+
+        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
+    }
+
+    // Check current configuration for power mode (if device is configured)
+    if (pDriver->cfgnum != 0) {
+
+        if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) {
+
+            data |= 1;
+        }
+    }
+
+    // Check if remote wake-up is enabled
+    if (pDriver->isRemoteWakeUpEnabled) {
+
+        data |= 2;
+    }
+
+    // Send the device status
+    USBD_Write(0, &data, 2, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current status of an endpoints to the USB host.
+/// \param bEndpoint  Endpoint number.
+//------------------------------------------------------------------------------
+static void GetEndpointStatus(unsigned char bEndpoint)
+{
+    unsigned short data = 0;
+
+    // Check if the endpoint exists
+    if (bEndpoint > BOARD_USB_NUMENDPOINTS) {
+
+        USBD_Stall(0);
+    }
+    else {
+
+        // Check if the endpoint if currently halted
+        if (USBD_IsHalted(bEndpoint)) {
+
+            data = 1;
+        }
+        
+        // Send the endpoint status
+        USBD_Write(0, &data, 2, 0, 0);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Sends the requested USB descriptor to the host if available, or STALLs  the
+/// request.
+/// \param pDriver  Pointer to a USBDDriver instance.
+/// \param type  Type of the requested descriptor
+/// \param index  Index of the requested descriptor.
+/// \param length  Maximum number of bytes to return.
+//------------------------------------------------------------------------------
+static void GetDescriptor(
+    const USBDDriver *pDriver,
+    unsigned char type,
+    unsigned char index,
+    unsigned int length)
+{
+    const USBDeviceDescriptor *pDevice;
+    const USBConfigurationDescriptor *pConfiguration;
+    const USBDeviceQualifierDescriptor *pQualifier;
+    const USBConfigurationDescriptor *pOtherSpeed;
+    const USBGenericDescriptor **pStrings =
+        (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
+    unsigned char numStrings = pDriver->pDescriptors->numStrings;
+    const USBGenericDescriptor *pString;
+
+    // Use different set of descriptors depending on device speed
+    if (USBD_IsHighSpeed()) {
+
+        TRACE_DEBUG("HS ");
+        pDevice = pDriver->pDescriptors->pHsDevice;
+        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
+        pQualifier = pDriver->pDescriptors->pHsQualifier;
+        pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
+    }
+    else {
+
+        TRACE_DEBUG("FS ");
+        pDevice = pDriver->pDescriptors->pFsDevice;
+        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
+        pQualifier = pDriver->pDescriptors->pFsQualifier;
+        pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
+    }
+
+    // Check the descriptor type
+    switch (type) {
+        
+        case USBGenericDescriptor_DEVICE:
+            TRACE_INFO_WP("Dev ");
+
+            // Adjust length and send descriptor
+            if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {
+
+                length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
+            }
+            USBD_Write(0, pDevice, length, 0, 0);
+            break;
+
+        case USBGenericDescriptor_CONFIGURATION:
+            TRACE_INFO_WP("Cfg ");
+
+            // Adjust length and send descriptor
+            if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {
+
+                length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
+            }
+            USBD_Write(0, pConfiguration, length, 0, 0);
+            break;
+
+        case USBGenericDescriptor_DEVICEQUALIFIER:
+            TRACE_INFO_WP("Qua ");
+
+            // Check if descriptor exists
+            if (!pQualifier) {
+
+                USBD_Stall(0);
+            }
+            else {
+
+                // Adjust length and send descriptor
+                if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {
+
+                    length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
+                }
+                USBD_Write(0, pQualifier, length, 0, 0);
+            }
+            break;
+
+        case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
+            TRACE_INFO_WP("OSC ");
+
+            // Check if descriptor exists
+            if (!pOtherSpeed) {
+
+                USBD_Stall(0);
+            }
+            else {
+
+                // Adjust length and send descriptor
+                if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {
+
+                    length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
+                }
+                USBD_Write(0, pOtherSpeed, length, 0, 0);
+            }
+            break;
+
+        case USBGenericDescriptor_STRING:
+            TRACE_INFO_WP("Str%d ", index);
+
+            // Check if descriptor exists
+            if (index > numStrings) {
+
+                USBD_Stall(0);
+            }
+            else {
+
+                pString = pStrings[index];
+
+                // Adjust length and send descriptor
+                if (length > USBGenericDescriptor_GetLength(pString)) {
+
+                    length = USBGenericDescriptor_GetLength(pString);
+                }
+                USBD_Write(0, pString, length, 0, 0);
+            }
+            break;
+
+        default:
+            TRACE_WARNING(
+                      "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
+                      type);
+            USBD_Stall(0);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the active setting of the given interface if the configuration supports
+/// it; otherwise, the control pipe is STALLed. If the setting of an interface
+/// changes.
+/// \parma pDriver  Pointer to a USBDDriver instance.
+/// \parma infnum  Interface number.
+/// \parma setting  New active setting for the interface.
+//------------------------------------------------------------------------------
+static void SetInterface(
+    USBDDriver *pDriver,
+    unsigned char infnum,
+    unsigned char setting)
+{
+    // Make sure alternate settings are supported
+    if (!pDriver->pInterfaces) {
+
+        USBD_Stall(0);
+    }
+    else {
+
+        // Change the current setting of the interface and trigger the callback 
+        // if necessary
+        if (pDriver->pInterfaces[infnum] != setting) {
+
+            pDriver->pInterfaces[infnum] = setting;
+            USBDDriverCallbacks_InterfaceSettingChanged(infnum, setting);
+        }
+
+        // Acknowledge the request
+        USBD_Write(0, 0, 0, 0, 0);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Sends the currently active setting of the given interface to the USB
+/// host. If alternate settings are not supported, this function STALLs the
+/// control pipe.
+/// \param pDriver  Pointer to a USBDDriver instance.
+/// \param infnum  Interface number.
+//------------------------------------------------------------------------------
+static void GetInterface(
+    const USBDDriver *pDriver,
+    unsigned char infnum)
+{
+    // Make sure alternate settings are supported, or STALL the control pipe
+    if (!pDriver->pInterfaces) {
+
+        USBD_Stall(0);
+    }
+    else {
+
+        // Sends the current interface setting to the host
+        USBD_Write(0, &(pDriver->pInterfaces[infnum]), 1, 0, 0);
+    }
+}
+
+#ifdef BOARD_USB_UDPHS
+//------------------------------------------------------------------------------
+// Performs the selected test on the USB device (high-speed only).
+// \param test  Test selector value.
+//------------------------------------------------------------------------------
+static void USBDDriver_Test(unsigned char test)
+{
+    TRACE_DEBUG("UDPHS_Test\n\r");
+
+    // the lower byte of wIndex must be zero
+    // the most significant byte of wIndex is used to specify the specific test mode
+    switch (test) {
+        case USBFeatureRequest_TESTPACKET:
+            //Test mode Test_Packet: 
+            //Upon command, a port must repetitively transmit the following test packet until
+            //the exit action is taken. This enables the testing of rise and fall times, eye 
+            //patterns, jitter, and any other dynamic waveform specifications.
+            //The test packet is made up by concatenating the following strings. 
+            //(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one 
+            //transmitted. �S� indicates that a bit stuff occurs, which inserts an �extra� NRZI data bit. 
+            //�* N� is used to indicate N occurrences of a string of bits or symbols.)
+            //A port in Test_Packet mode must send this packet repetitively. The inter-packet timing 
+            //must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and 
+            //no greater than 125 us.
+            // Send ZLP
+            USBD_Test(USBFeatureRequest_TESTSENDZLP);
+            // Tst PACKET
+            USBD_Test(USBFeatureRequest_TESTPACKET);
+            while (1);
+            break;
+
+        case USBFeatureRequest_TESTJ:
+            //Test mode Test_J:
+            //Upon command, a port�s transceiver must enter the high-speed J state and remain in that
+            //state until the exit action is taken. This enables the testing of the high output drive
+            //level on the D+ line.
+            // Send ZLP
+            USBD_Test(USBFeatureRequest_TESTSENDZLP);
+            // Tst J
+            USBD_Test(USBFeatureRequest_TESTJ);
+            while (1);
+            break;
+
+        case USBFeatureRequest_TESTK:
+            //Test mode Test_K:
+            //Upon command, a port�s transceiver must enter the high-speed K state and remain in
+            //that state until the exit action is taken. This enables the testing of the high output drive
+            //level on the D- line.
+            // Send a ZLP
+            USBD_Test(USBFeatureRequest_TESTSENDZLP);
+            USBD_Test(USBFeatureRequest_TESTK);
+            while (1);
+            break;
+
+        case USBFeatureRequest_TESTSE0NAK:
+            //Test mode Test_SE0_NAK:
+            //Upon command, a port�s transceiver must enter the high-speed receive mode
+            //and remain in that mode until the exit action is taken. This enables the testing
+            //of output impedance, low level output voltage, and loading characteristics.
+            //In addition, while in this mode, upstream facing ports (and only upstream facing ports)
+            //must respond to any IN token packet with a NAK handshake (only if the packet CRC is
+            //determined to be correct) within the normal allowed device response time. This enables testing of
+            //the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
+            //test for basic functional testing.
+            USBD_Test(USBFeatureRequest_TESTSE0NAK);
+            // Send a ZLP
+            USBD_Test(USBFeatureRequest_TESTSENDZLP);
+            while (1);
+            break;
+
+        default:
+            USBD_Stall( 0 );
+            break;
+
+    }
+    // The exit action is to power cycle the device.
+    // The device must be disconnected from the host
+}
+#endif
+
+//------------------------------------------------------------------------------
+//      Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a USBDDriver instance with a list of descriptors. If
+/// interfaces can have multiple alternate settings, an array to store the
+/// current setting for each interface must be provided.
+/// \param pDriver  Pointer to a USBDDriver instance.
+/// \param pDescriptors  Pointer to a USBDDriverDescriptors instance.
+/// \param pInterfaces  Pointer to an array for storing the current alternate
+///                     setting of each interface (optional).
+//------------------------------------------------------------------------------
+void USBDDriver_Initialize(
+    USBDDriver *pDriver,
+    const USBDDriverDescriptors *pDescriptors,
+    unsigned char *pInterfaces)
+{
+
+    pDriver->cfgnum = 0;
+#if (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_SELFPOWERED_RWAKEUP) \
+    || (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_BUSPOWERED_RWAKEUP)
+    pDriver->isRemoteWakeUpEnabled = 1;
+#else
+    pDriver->isRemoteWakeUpEnabled = 0;
+#endif
+
+    pDriver->pDescriptors = pDescriptors;
+    pDriver->pInterfaces = pInterfaces;
+
+    // Initialize interfaces array if not null
+    if (pInterfaces != 0) {
+    
+        memset(pInterfaces, sizeof(pInterfaces), 0);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Handles the given request if it is standard, otherwise STALLs it.
+/// \param pDriver  Pointer to a USBDDriver instance.
+/// \param pRequest  Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+void USBDDriver_RequestHandler(
+    USBDDriver *pDriver,
+    const USBGenericRequest *pRequest)
+{
+    unsigned char cfgnum;
+    unsigned char infnum;
+    unsigned char eptnum;
+    unsigned char setting;
+    unsigned char type;
+    unsigned char index;
+    unsigned int length;
+    unsigned int address;
+
+    TRACE_INFO_WP("Std ");
+
+    // Check request code
+    switch (USBGenericRequest_GetRequest(pRequest)) {
+
+        case USBGenericRequest_GETDESCRIPTOR:
+            TRACE_INFO_WP("gDesc ");
+
+            // Send the requested descriptor
+            type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
+            index = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
+            length = USBGenericRequest_GetLength(pRequest);
+            GetDescriptor(pDriver, type, index, length);
+            break;
+
+        case USBGenericRequest_SETADDRESS:
+            TRACE_INFO_WP("sAddr ");
+
+            // Sends a zero-length packet and then set the device address
+            address = USBSetAddressRequest_GetAddress(pRequest);
+            USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
+            break;
+
+        case USBGenericRequest_SETCONFIGURATION:
+            TRACE_INFO_WP("sCfg ");
+
+            // Set the requested configuration
+            cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
+            SetConfiguration(pDriver, cfgnum);
+            break;
+
+        case USBGenericRequest_GETCONFIGURATION:
+            TRACE_INFO_WP("gCfg ");
+
+            // Send the current configuration number
+            GetConfiguration(pDriver);
+            break;
+
+        case USBGenericRequest_GETSTATUS:
+            TRACE_INFO_WP("gSta ");
+    
+            // Check who is the recipient
+            switch (USBGenericRequest_GetRecipient(pRequest)) {
+    
+                case USBGenericRequest_DEVICE:
+                    TRACE_INFO_WP("Dev ");
+    
+                    // Send the device status
+                    GetDeviceStatus(pDriver);
+                    break;
+    
+                case USBGenericRequest_ENDPOINT:
+                    TRACE_INFO_WP("Ept ");
+    
+                    // Send the endpoint status
+                    eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
+                    GetEndpointStatus(eptnum);
+                    break;
+    
+                default:
+                    TRACE_WARNING(
+                              "USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
+                              USBGenericRequest_GetRecipient(pRequest));
+                    USBD_Stall(0);
+            }
+            break;
+
+        case USBGenericRequest_CLEARFEATURE:
+            TRACE_INFO_WP("cFeat ");
+
+            // Check which is the requested feature
+            switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
+
+                case USBFeatureRequest_ENDPOINTHALT:
+                    TRACE_INFO_WP("Hlt ");
+
+                    // Unhalt endpoint and send a zero-length packet
+                    USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
+                    USBD_Write(0, 0, 0, 0, 0);
+                    break;
+
+                case USBFeatureRequest_DEVICEREMOTEWAKEUP:
+                    TRACE_INFO_WP("RmWU ");
+
+                    // Disable remote wake-up and send a zero-length packet
+                    pDriver->isRemoteWakeUpEnabled = 0;
+                    USBD_Write(0, 0, 0, 0, 0);
+                    break;
+
+                default:
+                    TRACE_WARNING(
+                              "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
+                              USBFeatureRequest_GetFeatureSelector(pRequest));
+                    USBD_Stall(0);
+            }
+            break;
+
+    case USBGenericRequest_SETFEATURE:
+        TRACE_INFO_WP("sFeat ");
+
+        // Check which is the selected feature
+        switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
+
+            case USBFeatureRequest_DEVICEREMOTEWAKEUP:
+                TRACE_INFO_WP("RmWU ");
+
+                // Enable remote wake-up and send a ZLP
+                pDriver->isRemoteWakeUpEnabled = 1;
+                USBD_Write(0, 0, 0, 0, 0);
+                break;
+
+            case USBFeatureRequest_ENDPOINTHALT:
+                TRACE_INFO_WP("Ept ");
+
+                // Halt endpoint
+                USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
+                USBD_Write(0, 0, 0, 0, 0);
+                break;
+
+#if defined(BOARD_USB_UDPHS)
+
+            case USBFeatureRequest_TESTMODE:
+                // 7.1.20 Test Mode Support
+                if ((USBGenericRequest_GetType(pRequest) == USBGenericRequest_DEVICE)
+                    && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {
+
+                    // Handle test request
+                    USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest));
+                }
+                else {
+
+                    USBD_Stall(0);
+                }
+                break;
+#endif
+
+            default:
+                TRACE_WARNING(
+                          "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
+                          USBFeatureRequest_GetFeatureSelector(pRequest));
+                USBD_Stall(0);
+        }
+        break;
+
+    case USBGenericRequest_SETINTERFACE:
+        TRACE_INFO_WP("sInterface ");
+
+        infnum = USBInterfaceRequest_GetInterface(pRequest);
+        setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
+        SetInterface(pDriver, infnum, setting);
+        break;
+
+    case USBGenericRequest_GETINTERFACE:
+        TRACE_INFO_WP("gInterface ");
+
+        infnum = USBInterfaceRequest_GetInterface(pRequest);
+        GetInterface(pDriver, infnum);
+        break;
+
+    default:
+        TRACE_WARNING(
+                  "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
+                  USBGenericRequest_GetRequest(pRequest));
+        USBD_Stall(0);
+    }
+}
+
+
+//------------------------------------------------------------------------------
+/// Test if RemoteWakeUP feature is enabled
+/// \param pDriver  Pointer to an USBDDriver instance.
+/// \return 1 if remote wake up has been enabled by the host; otherwise, returns
+/// 0
+//------------------------------------------------------------------------------
+unsigned char USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver)
+{
+    return pDriver->isRemoteWakeUpEnabled;
+}
+
+
diff --git a/at91lib/usb/device/core/USBDDriver.h b/at91lib/usb/device/core/USBDDriver.h
new file mode 100644
index 0000000..7b14b8e
--- /dev/null
+++ b/at91lib/usb/device/core/USBDDriver.h
@@ -0,0 +1,93 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+    USB Device Driver class definition.
+
+ !!!Usage
+
+    -# Instanciate a USBDDriver object and initialize it using
+       USBDDriver_Initialize.
+    -# When a USB SETUP request is received, forward it to the standard
+       driver using USBDDriver_RequestHandler.
+    -# Check the Remote Wakeup setting via USBDDriver_IsRemoteWakeUpEnabled.
+*/
+
+#ifndef USBDDRIVER_H
+#define USBDDRIVER_H
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include "USBDDriverDescriptors.h"
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+//         Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USB device driver structure, holding a list of descriptors identifying
+/// the device as well as the driver current state.
+//------------------------------------------------------------------------------
+typedef struct {
+
+    /// List of descriptors used by the device.
+    const USBDDriverDescriptors *pDescriptors;
+    /// Current setting for each interface.
+    unsigned char *pInterfaces;
+    /// Current configuration number (0 -> device is not configured).
+    unsigned char cfgnum;
+    /// Indicates if remote wake up has been enabled by the host.
+    unsigned char isRemoteWakeUpEnabled;
+
+} USBDDriver;
+
+//------------------------------------------------------------------------------
+//         Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBDDriver_Initialize(
+    USBDDriver *pDriver,
+    const USBDDriverDescriptors *pDescriptors,
+    unsigned char *pInterfaces);
+
+extern void USBDDriver_RequestHandler(
+    USBDDriver *pDriver,
+    const USBGenericRequest *pRequest);
+
+extern unsigned char USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver);
+
+#endif //#ifndef USBDDRIVER_H
+
diff --git a/at91lib/usb/device/core/USBDDriverCallbacks.h b/at91lib/usb/device/core/USBDDriverCallbacks.h
new file mode 100644
index 0000000..053e8ac
--- /dev/null
+++ b/at91lib/usb/device/core/USBDDriverCallbacks.h
@@ -0,0 +1,61 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+    Definition of several callbacks which are triggered by the USB software
+    driver after receiving specific requests.
+
+ !!!Usage
+
+    -# Re-implement the USBDDriverCallbacks_ConfigurationChanged
+        callback to know when the hosts changes the active configuration of
+        the device.
+    -# Re-implement the USBDDriverCallbacks_InterfaceSettingChanged
+        callback to get notified whenever the active setting of an interface
+        is changed by the host.
+*/
+
+#ifndef USBDDRIVERCALLBACKS_H
+#define USBDDRIVERCALLBACKS_H
+
+//------------------------------------------------------------------------------
+//         Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum);
+
+extern void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
+                                                        unsigned char setting);
+
+#endif //#ifndef USBDDRIVERCALLBACKS_H
+
diff --git a/at91lib/usb/device/core/USBDDriverCb_CfgChanged.c b/at91lib/usb/device/core/USBDDriverCb_CfgChanged.c
new file mode 100644
index 0000000..08e2b2f
--- /dev/null
+++ b/at91lib/usb/device/core/USBDDriverCb_CfgChanged.c
@@ -0,0 +1,49 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include "USBDDriverCallbacks.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+//         Global functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates that the current configuration of the device has changed.
+/// \param cfgnum  New device configuration index.
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+    TRACE_INFO_WP("ConfigurationChanged ");
+}
+
diff --git a/at91lib/usb/device/core/USBDDriverCb_IfSettingChanged.c b/at91lib/usb/device/core/USBDDriverCb_IfSettingChanged.c
new file mode 100644
index 0000000..c9049e6
--- /dev/null
+++ b/at91lib/usb/device/core/USBDDriverCb_IfSettingChanged.c
@@ -0,0 +1,52 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include "USBDDriverCallbacks.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+//         Global functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Notifies of a change in the currently active setting of an interface.
+/// \param interface  Number of the interface whose setting has changed.
+/// \param setting  New interface setting.
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_InterfaceSettingChanged(
+    unsigned char interface,
+    unsigned char setting)
+{
+    TRACE_INFO_WP("InterfaceSettingChanged ");
+}
+
diff --git a/at91lib/usb/device/core/USBDDriverDescriptors.h b/at91lib/usb/device/core/USBDDriverDescriptors.h
new file mode 100644
index 0000000..f1064e4
--- /dev/null
+++ b/at91lib/usb/device/core/USBDDriverDescriptors.h
@@ -0,0 +1,86 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+    Definition of a class for declaring USB descriptors required by the
+    device driver.
+*/
+
+#ifndef USBDDRIVERDESCRIPTORS_H
+#define USBDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBDeviceQualifierDescriptor.h>
+
+//------------------------------------------------------------------------------
+//         Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// List of all descriptors used by a USB device driver. Each descriptor can
+/// be provided in two versions: full-speed and high-speed. Devices which are
+/// not high-speed capable do not need to provided high-speed descriptors and
+/// the full-speed qualifier & other speed descriptors.
+//------------------------------------------------------------------------------
+typedef struct {
+
+    /// Pointer to the full-speed device descriptor.
+    const USBDeviceDescriptor *pFsDevice;
+    /// Pointer to the full-speed configuration descriptor.
+    const USBConfigurationDescriptor *pFsConfiguration;
+    /// Pointer to the full-speed qualifier descriptor.
+    const USBDeviceQualifierDescriptor *pFsQualifier;
+    /// Pointer to the full-speed other speed configuration descriptor.
+    const USBConfigurationDescriptor *pFsOtherSpeed;
+    /// Pointer to the high-speed device descriptor.
+    const USBDeviceDescriptor *pHsDevice;
+    /// Pointer to the high-speed configuration descriptor.
+    const USBConfigurationDescriptor *pHsConfiguration;
+    /// Pointer to the high-speed qualifier descriptor.
+    const USBDeviceQualifierDescriptor *pHsQualifier;
+    /// Pointer to the high-speed other speed configuration descriptor.
+    const USBConfigurationDescriptor *pHsOtherSpeed;
+    /// Pointer to the list of string descriptors.
+    const unsigned char **pStrings;
+    /// Number of string descriptors in list.
+    unsigned char numStrings;
+
+} USBDDriverDescriptors;
+
+#endif //#ifndef USBDDRIVERDESCRIPTORS_H
+
diff --git a/at91lib/usb/device/core/USBD_OTGHS.c b/at91lib/usb/device/core/USBD_OTGHS.c
new file mode 100644
index 0000000..0f87143
--- /dev/null
+++ b/at91lib/usb/device/core/USBD_OTGHS.c
@@ -0,0 +1,1677 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/*!
+    Functions for OTGHS peripheral usage.
+*/
+ 
+//------------------------------------------------------------------------------
+//      Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+
+#ifdef CHIP_OTGHS
+
+#include "common.h"
+#include "trace.h"
+#include "usb.h"
+
+//------------------------------------------------------------------------------
+//         Definitions
+//------------------------------------------------------------------------------
+
+#define NUM_IT_MAX       (AT91C_BASE_OTGHS->OTGHS_IPFEATURES & AT91C_OTGHS_EPT_NBR_MAX)
+#define NUM_IT_MAX_DMA   ((AT91C_BASE_OTGHS->OTGHS_IPFEATURES & AT91C_OTGHS_DMA_CHANNEL_NBR)>>4)
+
+#define SHIFT_DMA         24
+#define SHIFT_INTERUPT    12
+
+#define DMA
+
+//------------------------------------------------------------------------------
+//      Structures
+//------------------------------------------------------------------------------
+
+// \brief  Endpoint states
+typedef enum {
+
+    endpointStateDisabled,
+    endpointStateIdle,
+    endpointStateWrite,
+    endpointStateRead,
+    endpointStateHalted
+
+} EndpointState_t;
+
+//------------------------------------------------------------------------------
+//      Macros
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//      Internal Functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+// \brief  Returns a pointer to the OTGHS controller interface used by an USB
+//         driver
+//
+//         The pointer is cast to the correct type (AT91PS_OTGHS).
+// \param  pUsb Pointer to a S_usb instance
+// \return Pointer to the USB controller interface
+// \see    S_usb
+//------------------------------------------------------------------------------
+static AT91PS_OTGHS OTGHS_GetDriverInterface(const S_usb *pUsb)
+{
+    return (AT91PS_OTGHS) pUsb->pDriver->pInterface;
+}
+
+//------------------------------------------------------------------------------
+// \fn      OTGHS_GetInterfaceEPT
+// \brief   Returns OTGHS endpoint FIFO interface from S_usb structure
+//------------------------------------------------------------------------------
+static AT91PS_OTGHS_EPTFIFO OTGHS_GetInterfaceEPT(const S_usb *pUsb) 
+{
+    return (AT91PS_OTGHS_EPTFIFO) pUsb->pDriver->pEndpointFIFO;
+}
+
+
+//------------------------------------------------------------------------------
+// \brief  Enables the peripheral clock of the USB controller associated with
+//         the specified USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_EnableMCK(const S_usb *pUsb)
+{
+
+}
+
+//------------------------------------------------------------------------------
+// \brief  Disables the peripheral clock of the USB controller associated with
+//         the specified USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_DisableMCK(const S_usb *pUsb)
+{
+
+}
+
+//------------------------------------------------------------------------------
+// \brief  Enables the 48MHz clock of the USB controller associated with
+//         the specified USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_EnableOTGHSCK(const S_usb *pUsb)
+{
+
+}
+
+//------------------------------------------------------------------------------
+// \brief  Disables the 48MHz clock of the USB controller associated with
+//         the specified USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_DisableOTGHSCK(const S_usb *pUsb)
+{
+
+}
+
+//------------------------------------------------------------------------------
+// \brief  Enables the transceiver of the USB controller associated with
+//         the specified USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_EnableTransceiver(const S_usb *pUsb)
+{
+    SET(OTGHS_GetDriverInterface(pUsb)->OTGHS_CTRL, AT91C_OTGHS_OTGPADE);
+}
+
+//------------------------------------------------------------------------------
+// \brief  Disables the transceiver of the USB controller associated with
+//         the specified USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_DisableTransceiver(const S_usb *pUsb)
+{
+    CLEAR(OTGHS_GetDriverInterface(pUsb)->OTGHS_CTRL, AT91C_OTGHS_OTGPADE);
+}
+
+//------------------------------------------------------------------------------
+// \brief  Invokes the callback associated with a finished transfer on an
+//         endpoint
+// \param  pEndpoint Pointer to a S_usb_endpoint instance
+// \param  bStatus   Status code returned by the transfer operation
+// \see    Status codes
+// \see    S_usb_endpoint
+//------------------------------------------------------------------------------
+static void OTGHS_EndOfTransfer(S_usb_endpoint *pEndpoint,
+                                         char bStatus)
+{
+    if ((pEndpoint->dState == endpointStateWrite)
+        || (pEndpoint->dState == endpointStateRead)) {
+
+        TRACE_DEBUG_WP("E");
+
+        // Endpoint returns in Idle state
+        pEndpoint->dState = endpointStateIdle;
+
+        // Invoke callback is present
+        if (pEndpoint->fCallback != 0) {
+
+            pEndpoint->fCallback((unsigned int) pEndpoint->pArgument,
+                                 (unsigned int) bStatus,
+                                 pEndpoint->dBytesTransferred,
+                                 pEndpoint->dBytesRemaining
+                                 + pEndpoint->dBytesBuffered);
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Transfers a data payload from the current tranfer buffer to the
+//         endpoint FIFO.
+// \param  pUsb      Pointer to a S_usb instance
+// \param  bEndpoint Index of endpoint
+// \return Number of bytes transferred
+// \see    S_usb
+//------------------------------------------------------------------------------
+static unsigned int OTGHS_WritePayload(const S_usb *pUsb,
+                                       unsigned char bEndpoint)
+{
+    AT91PS_OTGHS_EPTFIFO pInterfaceEPT = OTGHS_GetInterfaceEPT(pUsb);
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+    char           *pfifo;
+    unsigned int   dBytes;
+    unsigned int   dCtr;
+
+    pfifo = (char*)&(pInterfaceEPT->OTGHS_READEPT0[bEndpoint*16384]);
+
+    // Get the number of bytes to send
+    dBytes = min(pEndpoint->wMaxPacketSize, pEndpoint->dBytesRemaining);
+
+    // Transfer one packet in the FIFO buffer
+    for (dCtr = 0; dCtr < dBytes; dCtr++) {
+
+        pfifo[dCtr] = *(pEndpoint->pData);
+        pEndpoint->pData++;
+    }
+
+    pEndpoint->dBytesBuffered += dBytes;
+    pEndpoint->dBytesRemaining -= dBytes;
+
+    return dBytes;
+}
+
+//----------------------------------------------------------------------------
+// \brief  Transfers a data payload from an endpoint FIFO to the current
+//         transfer buffer.
+// \param  pUsb        Pointer to a S_usb instance
+// \param  bEndpoint   Index of endpoint
+// \param  wPacketSize Size of received data packet
+// \return Number of bytes transferred
+// \see    S_usb
+//------------------------------------------------------------------------------
+static unsigned int OTGHS_GetPayload(const S_usb    *pUsb,
+                                     unsigned char  bEndpoint,
+                                     unsigned short wPacketSize)
+{
+    AT91PS_OTGHS_EPTFIFO pInterfaceEPT = OTGHS_GetInterfaceEPT(pUsb);
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+    char           *pfifo;
+    unsigned int   dBytes;
+    unsigned int   dCtr;
+
+    pfifo = (char*)&(pInterfaceEPT->OTGHS_READEPT0[bEndpoint*16384]);
+
+    // Get number of bytes to retrieve
+    dBytes = min(pEndpoint->dBytesRemaining, wPacketSize);
+
+    // Retrieve packet
+    for (dCtr = 0; dCtr < dBytes; dCtr++) {
+
+        *(pEndpoint->pData) = pfifo[dCtr];
+        pEndpoint->pData++;
+    }
+
+    pEndpoint->dBytesRemaining -= dBytes;
+    pEndpoint->dBytesTransferred += dBytes;
+    pEndpoint->dBytesBuffered += wPacketSize - dBytes;
+
+    return dBytes;
+}
+
+//------------------------------------------------------------------------------
+// \brief  Transfers a received SETUP packet from endpoint 0 FIFO to the
+//         S_usb_request structure of an USB driver
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_GetSetup(const S_usb *pUsb)
+{
+    unsigned int *pData = (unsigned int *) USB_GetSetup(pUsb);
+    AT91PS_OTGHS_EPTFIFO pInterfaceEPT = OTGHS_GetInterfaceEPT(pUsb);
+
+    pData[0] = pInterfaceEPT->OTGHS_READEPT0[0];
+    pData[1] = pInterfaceEPT->OTGHS_READEPT0[0];
+}
+
+//------------------------------------------------------------------------------
+// \brief  This function reset all endpoint transfer descriptors
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_ResetEndpoints(const S_usb *pUsb)
+{
+    S_usb_endpoint *pEndpoint;
+    unsigned char  bEndpoint;
+
+    // Reset the transfer descriptor of every endpoint
+    for (bEndpoint = 0; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {
+
+        pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+
+        // Reset endpoint transfer descriptor
+        pEndpoint->pData = 0;
+        pEndpoint->dBytesRemaining = 0;
+        pEndpoint->dBytesTransferred = 0;
+        pEndpoint->dBytesBuffered = 0;
+        pEndpoint->fCallback = 0;
+        pEndpoint->pArgument = 0;
+
+        // Configure endpoint characteristics
+        pEndpoint->dState = endpointStateDisabled;
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Disable all endpoints (except control endpoint 0), aborting current
+//         transfers if necessary.
+// \param  pUsb Pointer to a S_usb instance
+//------------------------------------------------------------------------------
+static void OTGHS_DisableEndpoints(const S_usb *pUsb)
+{
+    S_usb_endpoint *pEndpoint;
+    unsigned char  bEndpoint;
+
+    // Foreach endpoint, if it is enabled, disable it and invoke the callback
+    // Control endpoint 0 is not disabled
+    for (bEndpoint = 1; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {
+
+        pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
+
+        pEndpoint->dState = endpointStateDisabled;
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Endpoint interrupt handler.
+//
+//         Handle IN/OUT transfers, received SETUP packets and STALLing
+// \param  pUsb      Pointer to a S_usb instance
+// \param  bEndpoint Index of endpoint
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_EndpointHandler(const S_usb *pUsb, unsigned char bEndpoint)
+{
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+    unsigned int dStatus = pInterface->OTGHS_DEVEPTCSR[bEndpoint];
+    unsigned short wPacketSize;
+
+    TRACE_DEBUG_WP("Ept%d, 0x%X ", bEndpoint, dStatus);
+
+    // Handle interrupts
+    // IN packet sent
+    if((ISSET(pInterface->OTGHS_DEVEPTCMR[bEndpoint], AT91C_OTGHS_TXINI))
+    && (ISSET(dStatus, AT91C_OTGHS_TXINI ))) {
+
+        TRACE_DEBUG_WP("Wr ");
+
+        if (pEndpoint->dBytesBuffered > 0) {
+
+            TRACE_DEBUG_WP("%d ", pEndpoint->dBytesBuffered);
+
+            pEndpoint->dBytesTransferred += pEndpoint->dBytesBuffered;
+            pEndpoint->dBytesBuffered = 0;
+        }
+
+        if ((!pEndpoint->isDataSent) || (pEndpoint->dBytesRemaining > 0)) {
+            
+            OTGHS_WritePayload(pUsb, bEndpoint);
+            pEndpoint->isDataSent = true;
+
+            pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_TXINI;
+            // For a non-control endpoint, the FIFOCON bit must be cleared
+            // to start the transfer
+            if ((AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])
+                != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+
+                pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_FIFOCON;
+            }
+        }
+        else {
+            
+            pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_TXINI;
+
+            // Disable interrupt if this is not a control endpoint
+            if ((AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])
+                != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+
+                pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
+
+            }
+            OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
+        }
+    }
+
+    // OUT packet received
+    if(ISSET(dStatus, AT91C_OTGHS_RXOUT)) {
+
+        TRACE_DEBUG_WP("Rd ");
+
+        // Check that the endpoint is in Read state
+        if (pEndpoint->dState != endpointStateRead) {
+
+            // Endpoint is NOT in Read state
+            if (ISCLEARED(pInterface->OTGHS_DEVEPTCFG[bEndpoint], AT91C_OTGHS_EPT_TYPE)
+             && ISCLEARED(dStatus, (0x7FF<<20))) {  // byte count
+
+                // Control endpoint, 0 bytes received
+                // Acknowledge the data and finish the current transfer
+                TRACE_DEBUG_WP("Ack ");
+                pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
+
+                OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
+            }
+            else if (ISSET(dStatus, AT91C_OTGHS_STALL)) {
+
+                // Non-control endpoint
+                // Discard stalled data
+                TRACE_DEBUG_WP("Disc ");
+                pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
+            }
+            else {
+
+                // Non-control endpoint
+                // Nak data
+                TRACE_DEBUG_WP("Nak ");
+                pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
+            }
+        }
+        else {
+
+            // Endpoint is in Read state
+            // Retrieve data and store it into the current transfer buffer
+            wPacketSize = (unsigned short) ((dStatus >> 20) & 0x7FF);
+
+            TRACE_DEBUG_WP("%d ", wPacketSize);
+
+            OTGHS_GetPayload(pUsb, bEndpoint, wPacketSize);
+
+            pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
+            pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_FIFOCON;
+
+            if ((pEndpoint->dBytesRemaining == 0)
+                || (wPacketSize < pEndpoint->wMaxPacketSize)) {
+
+                pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_RXOUT;
+
+                // Disable interrupt if this is not a control endpoint
+                if ((AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])
+                    != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+
+                    pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
+                }
+
+                OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
+            }
+        }
+    }
+
+    // SETUP packet received
+    if(ISSET(dStatus, AT91C_OTGHS_RXSTP)) {
+
+        TRACE_DEBUG_WP("Stp ");
+
+        // If a transfer was pending, complete it
+        // Handle the case where during the status phase of a control write
+        // transfer, the host receives the device ZLP and ack it, but the ack
+        // is not received by the device
+        if ((pEndpoint->dState == endpointStateWrite)
+            || (pEndpoint->dState == endpointStateRead)) {
+
+            OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
+        }
+
+        // Copy the setup packet in S_usb
+        OTGHS_GetSetup(pUsb);
+
+        // Acknowledge setup packet
+        pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXSTP;
+
+        // Forward the request to the upper layer
+        USB_NewRequestCallback(pUsb);
+    }
+
+    // STALL sent
+    if (ISSET(dStatus, AT91C_OTGHS_STALL)) {
+
+        TRACE_WARNING("Sta 0x%X [%d] ", dStatus, bEndpoint);
+
+        // Acknowledge STALL interrupt and disable it
+        pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_STALL;
+        //pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALL;
+
+        // If the endpoint is not halted, clear the stall condition
+        if (pEndpoint->dState != endpointStateHalted) {
+
+            TRACE_WARNING("_ " );
+            // Acknowledge the stall RQ flag
+            pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
+        }
+
+    }
+
+}
+
+
+//------------------------------------------------------------------------------
+//      Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+// \brief  Configure an endpoint with the provided endpoint descriptor
+// \param  pUsb    Pointer to a S_usb instance
+// \param  pEpDesc Pointer to the endpoint descriptor
+// \return true if the endpoint is now configured, false otherwise
+// \see    S_usb_endpoint_descriptor
+// \see    S_usb
+//------------------------------------------------------------------------------
+static bool OTGHS_ConfigureEndpoint(const S_usb *pUsb,
+                             const S_usb_endpoint_descriptor *pEpDesc)
+{
+    AT91PS_OTGHS   pInterface = OTGHS_GetDriverInterface(pUsb);
+    S_usb_endpoint *pEndpoint;
+    unsigned char  bEndpoint;
+    unsigned char  bType;
+    unsigned char  endpointDir;
+    unsigned short sizeEpt = 0;
+
+    // Maximum packet size configuration value
+    if( pEpDesc->wMaxPacketSize == 8 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_8;
+    } else if ( pEpDesc->wMaxPacketSize == 16 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_16;
+    } else if ( pEpDesc->wMaxPacketSize == 32 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_32;
+    } else if ( pEpDesc->wMaxPacketSize == 64 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_64;
+    } else if ( pEpDesc->wMaxPacketSize == 128 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_128;
+    } else if ( pEpDesc->wMaxPacketSize == 256 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_256;
+    } else if ( pEpDesc->wMaxPacketSize == 512 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_512;
+    } else if ( pEpDesc->wMaxPacketSize == 1024 ) {
+        sizeEpt = AT91C_OTGHS_EPT_SIZE_1024;
+    } //else {
+    //  sizeEpt = 0; // control endpoint
+    //}
+
+    // if pEpDesc == 0 then initialize the control endpoint
+    if (pEpDesc == (S_usb_endpoint_descriptor const *) 0) {
+
+        bEndpoint = 0;
+        bType = 0;    // Control endpoint
+    }
+    else {
+        // The endpoint number
+        bEndpoint   = (unsigned char) (pEpDesc->bEndpointAddress & 0x7);
+        // Transfer type: Control, Isochronous, Bulk, Interrupt
+        bType = (unsigned char) (pEpDesc->bmAttributes     & 0x3);
+        // Direction, ignored for control endpoints
+        endpointDir  = (unsigned char) (pEpDesc->bEndpointAddress & (1<<7));
+    }
+
+    // Get pointer on endpoint
+    pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+    if (pEndpoint == 0) {
+
+        return false;
+    }
+
+    // Configure wMaxPacketSize
+    if (pEpDesc != 0) {
+
+        pEndpoint->wMaxPacketSize = pEpDesc->wMaxPacketSize;
+    }
+    else {
+
+        pEndpoint->wMaxPacketSize = USB_ENDPOINT0_MAXPACKETSIZE;
+    }
+
+    // Abort the current transfer is the endpoint was configured and in
+    // Write or Read state
+    if ((pEndpoint->dState == endpointStateRead)
+        || (pEndpoint->dState == endpointStateWrite)) {
+
+        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
+    }
+
+    // Enter in IDLE state
+    pEndpoint->dState = endpointStateIdle;
+
+    // Reset Endpoint Fifos
+    pInterface->OTGHS_DEVEPT |= (1<<bEndpoint<<16);
+    pInterface->OTGHS_DEVEPT &= ~(1<<bEndpoint<<16);
+
+    // Enable endpoint
+    pInterface->OTGHS_DEVEPT |= (1<<bEndpoint);
+
+    // Configure endpoint
+    switch (bType) {
+
+        //-------------------------
+        case ENDPOINT_TYPE_CONTROL:
+        //-------------------------
+            TRACE_INFO("Control[%d]\n\r",bEndpoint);
+
+            //! Configure endpoint
+            pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
+                            AT91C_OTGHS_EPT_SIZE_64 | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_CTL_EPT | AT91C_OTGHS_BK_NUMBER_1;
+
+            // Enable RXSTP interrupt
+            pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RXSTP;
+
+            // Enable endpoint IT
+            pInterface->OTGHS_DEVIER = 1<<SHIFT_INTERUPT<<bEndpoint;
+
+            break;
+
+        //-----------------------------
+        case ENDPOINT_TYPE_ISOCHRONOUS:
+        //-----------------------------
+            if (endpointDir) {
+                TRACE_INFO("Iso In[%d]\n\r",bEndpoint);
+
+                //! Configure endpoint
+#ifndef DMA
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
+                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#else
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
+                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#endif
+
+            }
+            else {
+                TRACE_INFO("Iso Out[%d]\n\r",bEndpoint);
+
+                //! Configure endpoint
+#ifndef DMA
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] =  AT91C_OTGHS_ALLOC |
+                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#else
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
+                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#endif
+
+            }
+            break;
+
+        //----------------------
+        case ENDPOINT_TYPE_BULK:
+        //----------------------
+            if (endpointDir) {
+                TRACE_INFO("Bulk In(%d)[%d] ",bEndpoint, pEpDesc->wMaxPacketSize);
+                //! Configure endpoint
+#ifndef DMA
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
+                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#else
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
+                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#endif
+
+            }
+            else {
+                TRACE_INFO("Bulk Out(%d)[%d]\n\r",bEndpoint, pEpDesc->wMaxPacketSize);
+                //! Configure endpoint
+#ifndef DMA
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] =  AT91C_OTGHS_ALLOC |
+                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#else
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
+                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#endif
+            }
+            break;
+
+        //---------------------------
+        case ENDPOINT_TYPE_INTERRUPT:
+        //---------------------------
+            if (endpointDir) {
+                TRACE_INFO("Interrupt In[%d]\n\r",bEndpoint);
+                //! Configure endpoint
+#ifndef DMA
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
+                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#else
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
+                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#endif
+
+            }
+            else {
+                TRACE_INFO("Interrupt Out[%d]\n\r",bEndpoint);
+                //! Configure endpoint
+#ifndef DMA
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] =  AT91C_OTGHS_ALLOC |
+                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#else
+                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
+                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
+#endif
+
+            }
+            break;
+
+        //------
+        default:
+        //------
+            TRACE_ERROR(" unknown endpoint type\n\r");
+            return false;
+    }
+
+    // Check if the configuration is ok
+    if (ISCLEARED(pInterface->OTGHS_DEVEPTCSR[bEndpoint], AT91C_OTGHS_CFGOK)) {
+
+        TRACE_FATAL("OTGHS_ConfigureEndpoint: Cannot configure endpoint\n\r");
+        return false;
+    }
+
+    return true;
+}
+
+
+//------------------------------------------------------------------------------
+//      Interrupt service routine
+//------------------------------------------------------------------------------
+#ifdef DMA
+//----------------------------------------------------------------------------
+//! \fn    OTGHS_DmaHandler
+//! \brief This function (ISR) handles DMA interrupts
+//----------------------------------------------------------------------------
+static void OTGHS_DmaHandler(const S_usb *pUsb, unsigned char endpoint)
+{
+    AT91PS_OTGHS   pInterface = OTGHS_GetDriverInterface(pUsb);
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, endpoint);
+    unsigned int   csr;
+
+    csr = pInterface->OTGHS_DEVDMA[endpoint].OTGHS_DEVDMASTATUS;
+    pInterface->OTGHS_DEVIDR = (1<<SHIFT_DMA<<endpoint);
+
+    if((csr & AT91C_OTGHS_END_BF_ST) || (csr & AT91C_OTGHS_END_TR_ST)) {
+        // READ
+        TRACE_DEBUG_M("END_BF_ST\n\r");
+        pEndpoint->dBytesTransferred = pEndpoint->dBytesBuffered;
+        pEndpoint->dBytesBuffered = 0;
+
+        TRACE_DEBUG_M("dBytesBuffered: 0x%x\n\r",pEndpoint->dBytesBuffered);
+        TRACE_DEBUG_M("dBytesRemaining: 0x%x\n\r",pEndpoint->dBytesRemaining);
+        TRACE_DEBUG_M("dBytesTransferred: 0x%x\n\r",pEndpoint->dBytesTransferred);
+
+        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
+        pEndpoint->dState = endpointStateIdle;
+    }
+    else {
+        TRACE_FATAL("Probleme IT DMA\n\r");
+    }
+}
+#endif
+
+
+//------------------------------------------------------------------------------
+// \brief  OTGHS interrupt handler
+//
+//         Manages device resume, suspend, end of bus reset. Forwards endpoint
+//         interrupts to the appropriate handler.
+// \param  pUsb Pointer to a S_usb instance
+//------------------------------------------------------------------------------
+static void OTGHS_Handler(const S_usb *pUsb)
+{
+    AT91PS_OTGHS  pInterface = OTGHS_GetDriverInterface(pUsb);
+    unsigned int  dStatus;
+    unsigned char numIT;
+
+    if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
+       && (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){
+
+        LED_TOGGLE(LED_USB);
+    }
+
+    TRACE_DEBUG_H("Hlr ");
+
+    // Get General interrupts status
+    dStatus = pInterface->OTGHS_SR & pInterface->OTGHS_CTRL & 0xFF;
+    while (dStatus != 0) {
+
+        if(ISSET(dStatus, AT91C_OTGHS_VBUSTI))
+        {
+            TRACE_DEBUG_M("__VBus\n\r");
+
+            USB_Attach(pUsb);
+
+            // Acknowledge the interrupt
+            pInterface->OTGHS_SCR = AT91C_OTGHS_VBUSTI;
+        }
+
+        // Don't treat others interrupt for this time
+        pInterface->OTGHS_SCR = AT91C_OTGHS_IDT    | AT91C_OTGHS_SRP 
+                              | AT91C_OTGHS_VBERR  | AT91C_OTGHS_BCERR
+                              | AT91C_OTGHS_ROLEEX | AT91C_OTGHS_HNPERR
+                              | AT91C_OTGHS_STO;
+
+        dStatus = pInterface->OTGHS_SR & pInterface->OTGHS_CTRL & 0xFF;
+    }
+
+
+    // Get OTG Device interrupts status
+    dStatus = pInterface->OTGHS_DEVISR & pInterface->OTGHS_DEVIMR;
+    TRACE_DEBUG_H("OTGHS_DEVISR:0x%X\n\r", pInterface->OTGHS_DEVISR);
+    while (dStatus != 0) {
+
+        // Start Of Frame (SOF)
+        if (ISSET(dStatus, AT91C_OTGHS_SOF)) {
+            TRACE_DEBUG_WP("SOF ");
+
+            // Invoke the SOF callback
+            USB_StartOfFrameCallback(pUsb);
+
+            // Acknowledge interrupt
+            SET(pInterface->OTGHS_DEVICR, AT91C_OTGHS_SOF);
+            CLEAR(dStatus, AT91C_OTGHS_SOF);
+        }
+
+        // Suspend
+        else if (dStatus & AT91C_OTGHS_SUSP) {
+
+            TRACE_DEBUG_M("S ");
+
+            if (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED)) {
+
+                // The device enters the Suspended state
+                //      MCK + UDPCK must be off
+                //      Pull-Up must be connected
+                //      Transceiver must be disabled
+
+                // Enable wakeup
+                SET(pInterface->OTGHS_DEVIER, AT91C_OTGHS_EORST | AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM);
+
+                // Acknowledge interrupt
+                pInterface->OTGHS_DEVICR = AT91C_OTGHS_SUSP;
+                SET(*(pUsb->pState), USB_STATE_SUSPENDED);
+                OTGHS_DisableTransceiver(pUsb);
+                OTGHS_DisableMCK(pUsb);
+                OTGHS_DisableOTGHSCK(pUsb);
+
+                // Invoke the Suspend callback
+
+                USB_SuspendCallback(pUsb);
+            }
+        }
+
+        // Resume
+        else if (ISSET(dStatus, AT91C_OTGHS_WAKEUP)
+              || ISSET(dStatus, AT91C_OTGHS_EORSM)) {
+
+            // Invoke the Resume callback
+            USB_ResumeCallback(pUsb);
+
+            TRACE_DEBUG_M("R ");
+
+            // The device enters Configured state
+            //      MCK + UDPCK must be on
+            //      Pull-Up must be connected
+            //      Transceiver must be enabled
+
+            if (ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED)) {
+
+                // Powered state
+                OTGHS_EnableMCK(pUsb);
+                OTGHS_EnableOTGHSCK(pUsb);
+
+                // Default state
+                if (ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {
+
+                    OTGHS_EnableTransceiver(pUsb);
+                }
+
+                CLEAR(*(pUsb->pState), USB_STATE_SUSPENDED);
+            }
+            pInterface->OTGHS_DEVICR = 
+                (AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM | AT91C_OTGHS_SUSP);
+
+            pInterface->OTGHS_DEVIER = (AT91C_OTGHS_EORST | AT91C_OTGHS_SUSP);
+            pInterface->OTGHS_DEVICR = (AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM);
+            pInterface->OTGHS_DEVIDR = AT91C_OTGHS_WAKEUP;
+
+        }
+
+        // End of bus reset
+        else if (dStatus & AT91C_OTGHS_EORST) {
+
+            TRACE_DEBUG_M("EoB ");
+            // The device enters the Default state
+            //      MCK + UDPCK are already enabled
+            //      Pull-Up is already connected
+            //      Transceiver must be enabled
+            //      Endpoint 0 must be enabled
+            SET(*(pUsb->pState), USB_STATE_DEFAULT);
+
+            OTGHS_EnableTransceiver(pUsb);
+
+            // The device leaves the Address & Configured states
+            CLEAR(*(pUsb->pState), USB_STATE_ADDRESS | USB_STATE_CONFIGURED);
+            OTGHS_ResetEndpoints(pUsb);
+            OTGHS_DisableEndpoints(pUsb);
+            OTGHS_ConfigureEndpoint(pUsb, 0);
+
+            // Flush and enable the Suspend interrupt
+            SET(pInterface->OTGHS_DEVICR, AT91C_OTGHS_WAKEUP | AT91C_OTGHS_SUSP);
+
+            // Enable the Start Of Frame (SOF) interrupt if needed
+            if (pUsb->pCallbacks->startOfFrame != 0) {
+
+                SET(pInterface->OTGHS_DEVIER, AT91C_OTGHS_SOF);
+            }
+
+            // Invoke the Reset callback
+            USB_ResetCallback(pUsb);
+
+            // Acknowledge end of bus reset interrupt
+            pInterface->OTGHS_DEVICR = AT91C_OTGHS_EORST;
+        }
+
+        // Handle upstream resume interrupt
+        else if (dStatus & AT91C_OTGHS_UPRSM) {
+
+            TRACE_DEBUG_WP("  External resume interrupt\n\r");
+
+            // - Acknowledge the IT
+            pInterface->OTGHS_DEVICR = AT91C_OTGHS_UPRSM;
+        }
+
+        // Endpoint interrupts
+        else {
+#ifndef DMA
+            // Handle endpoint interrupts
+            for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
+                if( dStatus & (1<<SHIFT_INTERUPT<<numIT) ) {
+                    OTGHS_EndpointHandler(pUsb, numIT);
+                }
+            }
+#else
+            // Handle endpoint control interrupt
+            if( dStatus & (1<<SHIFT_INTERUPT<<0) ) {
+                OTGHS_EndpointHandler(pUsb, 0);
+            }
+            // Handle DMA interrupts
+            for(numIT = 1; numIT <= NUM_IT_MAX_DMA; numIT++) {
+                if( dStatus & (1<<SHIFT_DMA<<numIT) ) {
+                    OTGHS_DmaHandler(pUsb, numIT);
+                }
+            }
+#endif
+        }
+
+        // Retrieve new interrupt status
+        dStatus = (pInterface->OTGHS_DEVISR) & (pInterface->OTGHS_DEVIMR);
+
+        // Mask unneeded interrupts
+        if (!ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {
+
+            dStatus &= AT91C_OTGHS_EORST | AT91C_OTGHS_SOF;
+        }
+
+        TRACE_DEBUG_H("\n\r");
+
+        if (dStatus != 0) {
+
+            TRACE_DEBUG_WP("  - ");
+        }
+    }
+
+    if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
+       && (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){
+
+        LED_TOGGLE(LED_USB);
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Sends data through an USB endpoint
+//
+//         Sets up the transfer descriptor, write one or two data payloads
+//         (depending on the number of FIFO banks for the endpoint) and then
+//         starts the actual transfer. The operation is complete when all
+//         the data has been sent.
+// \param  pUsb      Pointer to a S_usb instance
+// \param  bEndpoint Index of endpoint
+// \param  pData     Pointer to a buffer containing the data to send
+// \param  dLength   Length of the data buffer
+// \param  fCallback Optional function to invoke when the transfer finishes
+// \param  pArgument Optional argument for the callback function
+// \return Operation result code
+// \see    Operation result codes
+// \see    Callback_f
+// \see    S_usb
+//------------------------------------------------------------------------------
+static char OTGHS_Write(const S_usb   *pUsb,
+                        unsigned char bEndpoint,
+                        const void    *pData,
+                        unsigned int  dLength,
+                        Callback_f    fCallback,
+                        void          *pArgument)
+{
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+
+    // Check that the endpoint is in Idle state
+    if (pEndpoint->dState != endpointStateIdle) {
+
+        return USB_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
+
+    // Setup the transfer descriptor
+    pEndpoint->pData = (char *) pData;
+    pEndpoint->dBytesRemaining = dLength;
+    pEndpoint->dBytesBuffered = 0;
+    pEndpoint->dBytesTransferred = 0;
+    pEndpoint->fCallback = fCallback;
+    pEndpoint->pArgument = pArgument;
+    pEndpoint->isDataSent = false;
+    
+    // Send one packet
+    pEndpoint->dState = endpointStateWrite;
+
+#ifdef DMA
+    // Test if endpoint type control
+    if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])) {
+#endif
+        // Enable endpoint IT
+        pInterface->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
+        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_TXINI;
+
+#ifdef DMA
+    }
+    else {
+
+        // others endoint (not control)
+        pEndpoint->dBytesBuffered = pEndpoint->dBytesRemaining;
+        pEndpoint->dBytesRemaining = 0;
+
+        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int) pEndpoint->pData;
+
+        // Enable IT DMA
+        pInterface->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);
+
+        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = 
+             (((pEndpoint->dBytesBuffered<<16)&AT91C_OTGHS_BUFF_LENGTH)
+               | AT91C_OTGHS_END_B_EN
+               | AT91C_OTGHS_END_BUFFIT
+               | AT91C_OTGHS_CHANN_ENB);
+
+    }
+#endif
+
+    return USB_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+// \brief  Reads incoming data on an USB endpoint
+//
+//         This methods sets the transfer descriptor and activate the endpoint
+//         interrupt. The actual transfer is then carried out by the endpoint
+//         interrupt handler. The Read operation finishes either when the
+//         buffer is full, or a short packet (inferior to endpoint maximum
+//         packet size) is received.
+// \param  pUsb      Pointer to a S_usb instance
+// \param  bEndpoint Index of endpoint
+// \param  pData     Pointer to a buffer to store the received data
+// \param  dLength   Length of the receive buffer
+// \param  fCallback Optional callback function
+// \param  pArgument Optional callback argument
+// \return Operation result code
+// \see    Callback_f
+// \see    S_usb
+//------------------------------------------------------------------------------
+static char OTGHS_Read(const S_usb   *pUsb,
+                       unsigned char bEndpoint,
+                       void          *pData,
+                       unsigned int  dLength,
+                       Callback_f    fCallback,
+                       void          *pArgument)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+
+    //! Return if the endpoint is not in IDLE state
+    if (pEndpoint->dState != endpointStateIdle) {
+
+        return USB_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_M("Read%d(%d) ", bEndpoint, dLength);
+
+    // Endpoint enters Read state
+    pEndpoint->dState = endpointStateRead;
+
+    //! Set the transfer descriptor
+    pEndpoint->pData = (char *) pData;
+    pEndpoint->dBytesRemaining = dLength;
+    pEndpoint->dBytesBuffered = 0;
+    pEndpoint->dBytesTransferred = 0;
+    pEndpoint->fCallback = fCallback;
+    pEndpoint->pArgument = pArgument;
+
+#ifdef DMA
+    // Test if endpoint type control
+    if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])) {
+#endif
+        // Control endpoint
+        // Enable endpoint IT
+        pInterface->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
+        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RXOUT;
+#ifdef DMA
+    }
+    else {
+
+        // others endoint (not control)
+        pEndpoint->dBytesBuffered = pEndpoint->dBytesRemaining;
+        pEndpoint->dBytesRemaining = 0;
+
+        // Enable IT DMA
+        pInterface->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);
+
+        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int) pEndpoint->pData;
+
+        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = \
+                             ( (pEndpoint->dBytesBuffered<<16)
+                               | AT91C_OTGHS_END_TR_EN
+                               | AT91C_OTGHS_END_TR_IT
+                               | AT91C_OTGHS_END_B_EN
+                               | AT91C_OTGHS_END_BUFFIT
+                               | AT91C_OTGHS_CHANN_ENB);
+    }
+#endif
+
+  return USB_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+// \brief  Clears, sets or returns the Halt state on specified endpoint
+//
+//         When in Halt state, an endpoint acknowledges every received packet
+//         with a STALL handshake. This continues until the endpoint is
+//         manually put out of the Halt state by calling this function.
+// \param  pUsb Pointer to a S_usb instance
+// \param  bEndpoint Index of endpoint
+// \param  bRequest  Request to perform
+//                   -> USB_SET_FEATURE, USB_CLEAR_FEATURE, USB_GET_STATUS
+// \return true if the endpoint is currently Halted, false otherwise
+// \see    S_usb
+//------------------------------------------------------------------------------
+static bool OTGHS_Halt(const S_usb   *pUsb,
+                       unsigned char bEndpoint,
+                       unsigned char bRequest)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+
+    // Clear the Halt feature of the endpoint if it is enabled
+    if (bRequest == USB_CLEAR_FEATURE) {
+
+        TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
+
+        // Return endpoint to Idle state
+        pEndpoint->dState = endpointStateIdle;
+
+        // Clear FORCESTALL flag
+
+        // Disable stall on endpoint
+        pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
+        pEndpoint->dState = endpointStateIdle;
+
+        // Reset data-toggle
+        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RSTDT;
+    }
+    // Set the Halt feature on the endpoint if it is not already enabled
+    // and the endpoint is not disabled
+    else if ((bRequest == USB_SET_FEATURE)
+             && (pEndpoint->dState != endpointStateHalted)
+             && (pEndpoint->dState != endpointStateDisabled)) {
+
+        TRACE_DEBUG_WP("Halt%d ", bEndpoint);
+
+        // Abort the current transfer if necessary
+        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_ABORTED);
+
+        // Put endpoint into Halt state
+        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_STALLRQ;
+        pEndpoint->dState = endpointStateHalted;
+
+        // Enable the endpoint interrupt
+        pInterface->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
+    }
+
+    // Return the endpoint halt status
+    if (pEndpoint->dState == endpointStateHalted) {
+
+        return true;
+    }
+    else {
+
+        return false;
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Causes the endpoint to acknowledge the next received packet with
+//         a STALL handshake.
+//
+//         Further packets are then handled normally.
+// \param  pUsb      Pointer to a S_usb instance
+// \param  bEndpoint Index of endpoint
+// \return Operation result code
+// \see    S_usb
+//------------------------------------------------------------------------------
+static char OTGHS_Stall(const S_usb *pUsb,
+                        unsigned char bEndpoint)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
+
+    // Check that endpoint is in Idle state
+    if (pEndpoint->dState != endpointStateIdle) {
+
+        TRACE_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
+        return USB_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_WP("Stall%d ", bEndpoint);
+
+    pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_STALL;
+    pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_STALLRQ;
+
+    return USB_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+// \brief  Activates a remote wakeup procedure
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_RemoteWakeUp(const S_usb *pUsb)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+
+    OTGHS_EnableMCK(pUsb);
+    OTGHS_EnableOTGHSCK(pUsb);
+    OTGHS_EnableTransceiver(pUsb);
+
+    TRACE_DEBUG_WP("Remote WakeUp ");
+
+    //! Enable wakeup interrupt
+    //pInterface->OTGHS_DEVIER = AT91C_OTGHS_UPRSM;
+
+    // Activates a remote wakeup
+    pInterface->OTGHS_DEVCTRL |= AT91C_OTGHS_RMWKUP;
+}
+
+//------------------------------------------------------------------------------
+// \brief  Handles attachment or detachment from the USB when the VBus power
+//         line status changes.
+// \param  pUsb Pointer to a S_usb instance
+// \return true if VBus is present, false otherwise
+// \see    S_usb
+//------------------------------------------------------------------------------
+static bool OTGHS_Attach(const S_usb *pUsb)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+
+    TRACE_DEBUG_WP("Attach(");
+
+    // Check if VBus is present
+    if (!ISSET(USB_GetState(pUsb), USB_STATE_POWERED)
+        && BRD_IsVBusConnected(pInterface)) {
+
+        // Powered state:
+        //      MCK + UDPCK must be on
+        //      Pull-Up must be connected
+        //      Transceiver must be disabled
+
+        // Invoke the Resume callback
+        USB_ResumeCallback(pUsb);
+
+        OTGHS_EnableMCK(pUsb);
+        OTGHS_EnableOTGHSCK(pUsb);
+
+        // Enable the transceiver
+        OTGHS_EnableTransceiver(pUsb);
+
+        // Reconnect the pull-up if needed
+        if (ISSET(*(pUsb->pState), USB_STATE_SHOULD_RECONNECT)) {
+
+            USB_Connect(pUsb);
+            CLEAR(*(pUsb->pState), USB_STATE_SHOULD_RECONNECT);
+        }
+
+        // Clear the Suspend and Resume interrupts
+        pInterface->OTGHS_DEVICR = \
+             AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM | AT91C_OTGHS_SUSP;
+
+        // Enable interrupt
+        pInterface->OTGHS_DEVIER = AT91C_OTGHS_EORST | AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM;
+    
+        // The device is in Powered state
+        SET(*(pUsb->pState), USB_STATE_POWERED);
+
+    }
+    else if (ISSET(USB_GetState(pUsb), USB_STATE_POWERED)
+             && !BRD_IsVBusConnected(pInterface)) {
+
+        // Attached state:
+        //      MCK + UDPCK off
+        //      Pull-Up must be disconnected
+        //      Transceiver must be disabled
+
+        // Warning: MCK must be enabled to be able to write in UDP registers
+        // It may have been disabled by the Suspend interrupt, so re-enable it
+        OTGHS_EnableMCK(pUsb);
+
+        // Disable interrupts
+        pInterface->OTGHS_DEVIDR &= ~(AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM
+                                    | AT91C_OTGHS_SUSP   | AT91C_OTGHS_SOF);
+
+        OTGHS_DisableEndpoints(pUsb);
+
+        // Disconnect the pull-up if needed
+        if (ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {
+
+            USB_Disconnect(pUsb);
+            SET(*(pUsb->pState), USB_STATE_SHOULD_RECONNECT);
+        }
+
+        OTGHS_DisableTransceiver(pUsb);
+        OTGHS_DisableMCK(pUsb);
+        OTGHS_DisableOTGHSCK(pUsb);
+
+        // The device leaves the all states except Attached
+        CLEAR(*(pUsb->pState), USB_STATE_POWERED | USB_STATE_DEFAULT
+              | USB_STATE_ADDRESS | USB_STATE_CONFIGURED | USB_STATE_SUSPENDED);
+
+        // Invoke the Suspend callback
+        USB_SuspendCallback(pUsb);
+
+    }
+
+    TRACE_DEBUG_WP("%d) ", ISSET(USB_GetState(pUsb), USB_STATE_POWERED));
+
+    return ISSET(USB_GetState(pUsb), USB_STATE_POWERED);
+}
+
+//------------------------------------------------------------------------------
+// \brief  Sets the device address
+//
+//         This function directly accesses the S_usb_request instance located
+//         in the S_usb structure to extract its new address.
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_SetAddress(S_usb const *pUsb)
+{
+    unsigned short wAddress = USB_GetSetup(pUsb)->wValue;
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+
+    TRACE_DEBUG_WP("SetAddr(%d) ", wAddress);
+
+    // Set address
+    pInterface->OTGHS_DEVCTRL = wAddress & AT91C_OTGHS_UADD;
+    pInterface->OTGHS_DEVCTRL |= AT91C_OTGHS_ADDEN;
+
+}
+
+//------------------------------------------------------------------------------
+// \brief  Changes the device state from Address to Configured, or from
+//         Configured to Address.
+//
+//         This method directly access the last received SETUP packet to
+//         decide on what to do.
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_SetConfiguration(S_usb const *pUsb)
+{
+    unsigned short wValue = USB_GetSetup(pUsb)->wValue;
+
+    TRACE_DEBUG_WP("SetCfg() ");
+
+    // Check the request
+    if (wValue != 0) {
+        // Enter Configured state
+        SET(*(pUsb->pState), USB_STATE_CONFIGURED);
+
+    }
+    else {
+
+        // Go back to Address state
+        CLEAR(*(pUsb->pState), USB_STATE_CONFIGURED);
+
+        // Abort all transfers
+        OTGHS_DisableEndpoints(pUsb);
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Enables the pull-up on the D+ line to connect the device to the USB.
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_Connect(const S_usb *pUsb)
+{
+#if defined(INTERNAL_PULLUP)
+    CLEAR(OTGHS_GetDriverInterface(pUsb)->OTGHS_DEVCTRL, AT91C_OTGHS_DETACH);
+
+#elif defined(INTERNAL_PULLUP_MATRIX)
+    TRACE_DEBUG_WP("PUON 1\n\r");
+    AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
+
+#else
+    BRD_ConnectPullUp(UDP_GetDriverInterface(pUsb));
+
+#endif
+}
+
+//------------------------------------------------------------------------------
+// \brief  Disables the pull-up on the D+ line to disconnect the device from
+//         the bus.
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_Disconnect(const S_usb *pUsb)
+{
+#if defined(INTERNAL_PULLUP)
+    SET(OTGHS_GetDriverInterface(pUsb)->OTGHS_DEVCTRL, AT91C_OTGHS_DETACH);
+
+#elif defined(INTERNAL_PULLUP_MATRIX)
+    TRACE_DEBUG_WP("PUON 0\n\r");
+    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+
+#else
+    BRD_DisconnectPullUp(UDP_GetDriverInterface(pUsb));
+
+#endif
+    // Device leaves the Default state
+    CLEAR(*(pUsb->pState), USB_STATE_DEFAULT);
+}
+
+//------------------------------------------------------------------------------
+// \brief  Certification test for High Speed device.
+// \param  pUsb Pointer to a S_usb instance
+// \param  bIndex char for the test choice
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_Test(const S_usb *pUsb, unsigned char bIndex)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+
+    pInterface->OTGHS_DEVIDR &= ~AT91C_OTGHS_SUSP;
+    pInterface->OTGHS_DEVCTRL |= AT91C_OTGHS_SPDCONF_HS; // remove suspend ?
+
+    switch( bIndex ) {
+        case TEST_PACKET:
+            TRACE_DEBUG_M("TEST_PACKET ");
+            pInterface->OTGHS_DEVCTRL |= AT91C_OTGHS_TSTPCKT;
+            break;
+
+        case TEST_J:
+            TRACE_DEBUG_M("TEST_J ");
+            pInterface->OTGHS_DEVCTRL |= AT91C_OTGHS_TSTJ;
+            break;
+
+        case TEST_K:
+            TRACE_DEBUG_M("TEST_K ");
+            pInterface->OTGHS_DEVCTRL |= AT91C_OTGHS_TSTK;
+            break;
+
+        case TEST_SEO_NAK:
+            TRACE_DEBUG_M("TEST_SEO_NAK ");
+            pInterface->OTGHS_DEVIDR = 0xFFFFFFFF;
+            break;
+
+        case TEST_SEND_ZLP:
+            pInterface->OTGHS_DEVEPTCCR[0] = AT91C_OTGHS_TXINI;
+            TRACE_DEBUG_M("SEND_ZLP ");
+            break;
+
+        TRACE_DEBUG_M("\n\r");
+    }
+}
+
+//------------------------------------------------------------------------------
+// \brief  Certification test for High Speed device.
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static bool OTGHS_IsHighSpeed(const S_usb *pUsb)
+{
+    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
+    bool         status = false;
+
+    if(AT91C_OTGHS_SPEED_SR_HS == (pInterface->OTGHS_SR & (0x03<<12))) {
+        // High Speed
+        status = true;
+    }
+
+    return status;
+}
+
+//------------------------------------------------------------------------------
+// \brief  Initializes the specified USB driver
+//
+//         This function initializes the current FIFO bank of endpoints,
+//         configures the pull-up and VBus lines, disconnects the pull-up and
+//         then trigger the Init callback.
+// \param  pUsb Pointer to a S_usb instance
+// \see    S_usb
+//------------------------------------------------------------------------------
+static void OTGHS_Init(const S_usb *pUsb)
+{
+    AT91PS_OTGHS  pInterface = OTGHS_GetDriverInterface(pUsb);
+    unsigned char i;
+
+    TRACE_DEBUG_WP("Init()\n\r");
+
+    // Enable USB macro
+    SET(OTGHS_GetDriverInterface(pUsb)->OTGHS_CTRL, AT91C_OTGHS_USBECTRL);
+
+    pInterface->OTGHS_DEVCTRL &=~ AT91C_OTGHS_DETACH; // detach
+
+    //// Force FS (for debug or test)
+//    pDriver->OTGHS_DEVCTRL |= AT91C_OTGHS_SPDCONF_FS;
+    pInterface->OTGHS_DEVCTRL &= ~AT91C_OTGHS_SPDCONF_FS;   // Normal mode
+    pInterface->OTGHS_DEVCTRL &= ~(  AT91C_OTGHS_LS | AT91C_OTGHS_TSTJ
+                                | AT91C_OTGHS_TSTK | AT91C_OTGHS_TSTPCKT
+                                | AT91C_OTGHS_OPMODE2 ); // Normal mode
+
+
+    // With OR without DMA !!!
+    // Initialization of DMA
+    for( i=1; i<=((AT91C_BASE_OTGHS->OTGHS_IPFEATURES & AT91C_OTGHS_DMA_CHANNEL_NBR)>>4); i++ ) {
+
+        // RESET endpoint canal DMA:
+        // DMA stop channel command
+        AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMACONTROL = 0;  // STOP command
+
+        // Disable endpoint
+        AT91C_BASE_OTGHS->OTGHS_DEVEPTCDR[i] = 0XFFFFFFFF;
+
+        // Reset endpoint config
+        AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[i] = 0;
+
+        // Reset DMA channel (Buff count and Control field)
+        AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMACONTROL = 0x02;  // NON STOP command
+
+        // Reset DMA channel 0 (STOP)
+        AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMACONTROL = 0;  // STOP command
+
+        // Clear DMA channel status (read the register for clear it)
+        AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMASTATUS = AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMASTATUS;
+
+    }
+
+    // Enable clock OTG pad
+    pInterface->OTGHS_CTRL &= ~AT91C_OTGHS_FRZCLKCTRL;
+
+    // Clear General IT
+    pInterface->OTGHS_SCR = 0x01FF;
+
+    // Clear OTG Device IT
+    pInterface->OTGHS_DEVICR = 0xFF;
+
+    // Clear OTG Host IT
+    pInterface->OTGHS_HSTICR = 0x7F;
+
+    // Reset all Endpoints Fifos
+    pInterface->OTGHS_DEVEPT |= (0x7F<<16);
+    pInterface->OTGHS_DEVEPT &= ~(0x7F<<16);
+
+    // Disable all endpoints
+    pInterface->OTGHS_DEVEPT &= ~0x7F;
+
+    // Bypass UTMI problems // jcb to be removed with new version of UTMI
+    // pInterface->OTGHS_TSTA2 = (1<<6)|(1<<7)|(1<<8);
+    // pInterface->OTGHS_TSTA2 = (1<<8);
+    pInterface->OTGHS_TSTA2 = 0;
+
+    // External pull-up on D+
+    // Configure
+    BRD_ConfigurePullUp(pInterface);
+
+    // Detach
+    OTGHS_Disconnect(pUsb);
+
+    // Device is in the Attached state
+    *(pUsb->pState) = USB_STATE_ATTACHED;
+
+    // Disable the UDP transceiver and interrupts
+    OTGHS_EnableMCK(pUsb);
+    SET(pInterface->OTGHS_DEVIER, AT91C_OTGHS_EORSM);
+
+    OTGHS_DisableMCK(pUsb);
+    OTGHS_Disconnect(pUsb);
+
+    // Test ID
+    if( 0 != (pInterface->OTGHS_SR & AT91C_OTGHS_ID) ) {
+        TRACE_INFO("ID=1: PERIPHERAL\n\r");
+    }
+    else {
+        TRACE_INFO("ID=0: HOST\n\r");
+    }
+
+    // Test VBUS
+    if( 0 != (pInterface->OTGHS_SR & AT91C_OTGHS_VBUSSR) ) {
+        TRACE_INFO("VBUS = 1\n\r");
+    }
+    else {
+        TRACE_INFO("VBUS = 0\n\r");
+    }
+
+    // Test SPEED
+    if(AT91C_OTGHS_SPEED_SR_HS == (pInterface->OTGHS_SR & (0x03<<12))) {
+        TRACE_INFO("HIGH SPEED\n\r");
+    }
+    else if(AT91C_OTGHS_SPEED_SR_LS == (pInterface->OTGHS_SR & (0x03<<12))) {
+        TRACE_INFO("LOW SPEED\n\r");
+    }
+    else {
+        TRACE_INFO("FULL SPEED\n\r");
+    }
+
+    // Configure interrupts
+    USB_InitCallback(pUsb);
+
+    pInterface->OTGHS_CTRL |= AT91C_OTGHS_VBUSTI;
+}
+
+//------------------------------------------------------------------------------
+//      Global variables
+//------------------------------------------------------------------------------
+
+// \brief Low-level driver methods to use with the OTGHS USB controller
+// \see S_driver_methods
+const S_driver_methods sOTGHSMethods = {
+
+    OTGHS_Init,
+    OTGHS_Write,
+    OTGHS_Read,
+    OTGHS_Stall,
+    OTGHS_Halt,
+    OTGHS_RemoteWakeUp,
+    OTGHS_ConfigureEndpoint,
+    OTGHS_Attach,
+    OTGHS_SetAddress,
+    OTGHS_SetConfiguration,
+    OTGHS_Handler,
+    OTGHS_Connect,
+    OTGHS_Disconnect,
+    OTGHS_Test,
+    OTGHS_IsHighSpeed
+};
+
+// \brief  Default driver when an UDP controller is present on a chip
+const S_usb_driver sDefaultDriver = {
+
+    AT91C_BASE_OTGHS,
+    AT91C_BASE_OTGHS_EPTFIFO,
+    0,
+    AT91C_ID_OTGHS,
+    AT91C_PMC_OTG,
+    &sOTGHSMethods
+};
+
+#endif //#ifdef CHIP_OTGHS
+
diff --git a/at91lib/usb/device/core/USBD_UDP.c b/at91lib/usb/device/core/USBD_UDP.c
new file mode 100644
index 0000000..1438441
--- /dev/null
+++ b/at91lib/usb/device/core/USBD_UDP.c
@@ -0,0 +1,1224 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/** 
+ \unit
+
+ !!!Purpose
+
+    Implementation of USB device functions on a UDP controller.
+
+    See "USBD API Methods".
+*/
+
+//------------------------------------------------------------------------------
+//      Headers
+//------------------------------------------------------------------------------
+
+#include "USBD.h"
+#include "USBDCallbacks.h"
+#include <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <utility/led.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+
+#if defined(BOARD_USB_UDP)
+
+//------------------------------------------------------------------------------
+//         Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "UDP register field values"
+///
+/// This page lists the initialize values of UDP registers.
+///
+/// !Values
+/// - UDP_RXDATA
+
+/// Bit mask for both banks of the UDP_CSR register.
+#define UDP_RXDATA              (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Endpoint states"
+///
+/// This page lists the endpoint states.
+///
+/// !States
+//  - UDP_ENDPOINT_DISABLED
+//  - UDP_ENDPOINT_HALTED
+//  - UDP_ENDPOINT_IDLE
+//  - UDP_ENDPOINT_SENDING
+//  - UDP_ENDPOINT_RECEIVING
+
+/// Endpoint states: Endpoint is disabled
+#define UDP_ENDPOINT_DISABLED       0
+/// Endpoint states: Endpoint is halted (i.e. STALLs every request)
+#define UDP_ENDPOINT_HALTED         1
+/// Endpoint states: Endpoint is idle (i.e. ready for transmission)
+#define UDP_ENDPOINT_IDLE           2
+/// Endpoint states: Endpoint is sending data
+#define UDP_ENDPOINT_SENDING        3
+/// Endpoint states: Endpoint is receiving data
+#define UDP_ENDPOINT_RECEIVING      4
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "UDP_CSR register access"
+///
+/// This page lists the macroes to access UDP CSR register.
+///
+/// !Macros
+/// - CLEAR_CSR
+/// - SET_CSR
+
+/// Bitmap for all status bits in CSR.
+#define REG_NO_EFFECT_1_ALL      AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
+                                |AT91C_UDP_STALLSENT   | AT91C_UDP_RXSETUP \
+                                |AT91C_UDP_TXCOMP
+
+/// Clears the specified bit(s) in the UDP_CSR register.
+/// \param endpoint The endpoint number of the CSR to process.
+/// \param flags The bitmap to set to 1.
+#define SET_CSR(endpoint, flags) \
+    { \
+        volatile unsigned int reg; \
+        reg = AT91C_BASE_UDP->UDP_CSR[endpoint] ; \
+        reg |= REG_NO_EFFECT_1_ALL; \
+        reg |= (flags); \
+        AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
+        while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) != (flags)); \
+    }
+
+/// Sets the specified bit(s) in the UDP_CSR register.
+/// \param endpoint The endpoint number of the CSR to process.
+/// \param flags The bitmap to clear to 0.
+#define CLEAR_CSR(endpoint, flags) \
+    { \
+        volatile unsigned int reg; \
+        reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
+        reg |= REG_NO_EFFECT_1_ALL; \
+        reg &= ~(flags); \
+        AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
+        while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) == (flags)); \
+    }
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//      Types
+//------------------------------------------------------------------------------
+
+/// Describes an ongoing transfer on a UDP endpoint.
+typedef struct {
+
+    /// Pointer to a data buffer used for emission/reception.
+    char             *pData;
+    /// Number of bytes which have been written into the UDP internal FIFO
+    /// buffers.
+    volatile int     buffered;
+    /// Number of bytes which have been sent/received.
+    volatile int     transferred;
+    /// Number of bytes which have not been buffered/transferred yet.
+    volatile int     remaining;
+    /// Optional callback to invoke when the transfer completes.
+    volatile TransferCallback fCallback;
+    /// Optional argument to the callback function.
+    void             *pArgument;
+} Transfer;
+
+//------------------------------------------------------------------------------
+/// Describes the state of an endpoint of the UDP controller.
+//------------------------------------------------------------------------------
+typedef struct {
+
+    /// Current endpoint state.
+    volatile unsigned char  state;
+    /// Current reception bank (0 or 1).
+    volatile unsigned char  bank;
+    /// Maximum packet size for the endpoint.
+    volatile unsigned short size;
+    /// Describes an ongoing transfer (if current state is either
+    ///  <UDP_ENDPOINT_SENDING> or <UDP_ENDPOINT_RECEIVING>)
+    Transfer       transfer;
+} Endpoint;
+
+//------------------------------------------------------------------------------
+//         Internal variables
+//------------------------------------------------------------------------------
+
+/// Holds the internal state for each endpoint of the UDP.
+static Endpoint endpoints[BOARD_USB_NUMENDPOINTS];
+
+/// Device current state.
+static unsigned char deviceState;
+/// Indicates the previous device state
+static unsigned char previousDeviceState;
+
+//------------------------------------------------------------------------------
+//      Internal Functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Enables the clock of the UDP peripheral.
+//------------------------------------------------------------------------------
+static inline void UDP_EnablePeripheralClock(void)
+{
+    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the UDP peripheral clock.
+//------------------------------------------------------------------------------
+static inline void UDP_DisablePeripheralClock(void)
+{
+    AT91C_BASE_PMC->PMC_PCDR = 1 << AT91C_ID_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Enables the 48MHz USB clock.
+//------------------------------------------------------------------------------
+static inline void UDP_EnableUsbClock(void)
+{
+    AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
+}
+
+//------------------------------------------------------------------------------
+///  Disables the 48MHz USB clock.
+//------------------------------------------------------------------------------
+static inline void UDP_DisableUsbClock(void)
+{
+    AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Enables the UDP transceiver.
+//------------------------------------------------------------------------------
+static inline void UDP_EnableTransceiver(void)
+{
+    AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_TXVDIS;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the UDP transceiver.
+//------------------------------------------------------------------------------
+static inline void UDP_DisableTransceiver(void)
+{
+    AT91C_BASE_UDP->UDP_TXVC |= AT91C_UDP_TXVDIS;
+}
+
+//------------------------------------------------------------------------------
+/// Handles a completed transfer on the given endpoint, invoking the
+/// configured callback if any.
+/// \param bEndpoint Number of the endpoint for which the transfer has completed.
+/// \param bStatus   Status code returned by the transfer operation
+//------------------------------------------------------------------------------
+static void UDP_EndOfTransfer(unsigned char bEndpoint, char bStatus)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Check that endpoint was sending or receiving data
+    if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+        || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+        TRACE_DEBUG_WP("Eo");
+
+        // Endpoint returns in Idle state
+        pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+        // Invoke callback is present
+        if (pTransfer->fCallback != 0) {
+
+            ((TransferCallback) pTransfer->fCallback)
+                (pTransfer->pArgument,
+                 bStatus,
+                 pTransfer->transferred,
+                 pTransfer->remaining + pTransfer->buffered);
+        }
+        else {
+            TRACE_DEBUG_WP("No callBack\n\r");
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the correct reception flag (bank 0 or bank 1) of an endpoint
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDP_ClearRxFlag(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+    // Clear flag and change banks
+    if (pEndpoint->bank == 0) {
+
+        CLEAR_CSR(bEndpoint, AT91C_UDP_RX_DATA_BK0);
+        // Swap bank if in dual-fifo mode
+        if (BOARD_USB_ENDPOINTS_BANKS(bEndpoint) > 1) {
+
+            pEndpoint->bank = 1;
+        }
+    }
+    else {
+
+        CLEAR_CSR(bEndpoint, AT91C_UDP_RX_DATA_BK1);
+        pEndpoint->bank = 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static void UDP_WritePayload(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+    signed int size;
+
+    // Get the number of bytes to send
+    size = pEndpoint->size;
+    if (size > pTransfer->remaining) {
+
+        size = pTransfer->remaining;
+    }
+
+    // Update transfer descriptor information
+    pTransfer->buffered += size;
+    pTransfer->remaining -= size;
+
+    // Write packet in the FIFO buffer
+    while (size > 0) {
+
+        AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pTransfer->pData);
+        pTransfer->pData++;
+        size--;
+    }
+}
+
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from an endpoint FIFO to the current transfer buffer
+/// \param bEndpoint Endpoint number.
+/// \param wPacketSize Size of received data packet
+//------------------------------------------------------------------------------
+static void UDP_ReadPayload(unsigned char bEndpoint, int wPacketSize)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Check that the requested size is not bigger than the remaining transfer
+    if (wPacketSize > pTransfer->remaining) {
+
+        pTransfer->buffered += wPacketSize - pTransfer->remaining;
+        wPacketSize = pTransfer->remaining;
+    }
+
+    // Update transfer descriptor information
+    pTransfer->remaining -= wPacketSize;
+    pTransfer->transferred += wPacketSize;
+
+    // Retrieve packet
+    while (wPacketSize > 0) {
+
+        *(pTransfer->pData) = (char) AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+        pTransfer->pData++;
+        wPacketSize--;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Received SETUP packet from endpoint 0 FIFO
+/// \param pRequest Generic USB SETUP request sent over Control endpoints
+//------------------------------------------------------------------------------
+static void UDP_ReadRequest(USBGenericRequest *pRequest)
+{
+    unsigned char *pData = (unsigned char *)pRequest;
+    unsigned int i;
+
+    // Copy packet
+    for (i = 0; i < 8; i++) {
+
+        *pData = (unsigned char) AT91C_BASE_UDP->UDP_FDR[0];
+        pData++;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Reset all endpoint transfer descriptors
+//------------------------------------------------------------------------------
+static void UDP_ResetEndpoints( void )
+{
+    Endpoint *pEndpoint;
+    Transfer *pTransfer;
+    unsigned char bEndpoint;
+
+    // Reset the transfer descriptor of every endpoint
+    for (bEndpoint = 0; bEndpoint < BOARD_USB_NUMENDPOINTS; bEndpoint++) {
+
+        pEndpoint = &(endpoints[bEndpoint]);
+        pTransfer = &(pEndpoint->transfer);
+
+        // Reset endpoint transfer descriptor
+        pTransfer->pData = 0;
+        pTransfer->transferred = -1;
+        pTransfer->buffered = -1;
+        pTransfer->remaining = -1;
+        pTransfer->fCallback = 0;
+        pTransfer->pArgument = 0;
+
+        // Reset endpoint state
+        pEndpoint->bank = 0;
+        pEndpoint->state = UDP_ENDPOINT_DISABLED;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Disable all endpoints (except control endpoint 0), aborting current 
+/// transfers if necessary
+//------------------------------------------------------------------------------
+static void UDP_DisableEndpoints( void )
+
+{
+    unsigned char bEndpoint;
+
+    // Disable each endpoint, terminating any pending transfer
+    // Control endpoint 0 is not disabled
+    for (bEndpoint = 1; bEndpoint < BOARD_USB_NUMENDPOINTS; bEndpoint++) {
+
+        UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+        endpoints[bEndpoint].state = UDP_ENDPOINT_DISABLED;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Checks if an ongoing transfer on an endpoint has been completed.
+/// \param bEndpoint Endpoint number.
+/// \return 1 if the current transfer on the given endpoint is complete;
+///         otherwise 0.
+//------------------------------------------------------------------------------
+static unsigned char UDP_IsTransferFinished(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Check if it is a Control endpoint
+    //  -> Control endpoint must always finish their transfer with a zero-length
+    //     packet
+    if ((AT91C_BASE_UDP->UDP_CSR[bEndpoint] & AT91C_UDP_EPTYPE)
+        == AT91C_UDP_EPTYPE_CTRL) {
+
+        return (pTransfer->buffered < pEndpoint->size);
+    }
+    // Other endpoints only need to transfer all the data
+    else {
+
+        return (pTransfer->buffered <= pEndpoint->size)
+               && (pTransfer->remaining == 0);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Endpoint interrupt handler.
+/// Handle IN/OUT transfers, received SETUP packets and STALLing
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDP_EndpointHandler(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+    unsigned int status = AT91C_BASE_UDP->UDP_CSR[bEndpoint];
+    unsigned short wPacketSize;
+    USBGenericRequest request;
+
+    TRACE_DEBUG_WP("E%d ", bEndpoint);
+    TRACE_DEBUG_WP("st:0x%X ", status);
+
+    // Handle interrupts
+    // IN packet sent
+    if ((status & AT91C_UDP_TXCOMP) != 0) {
+
+        TRACE_DEBUG_WP("Wr ");
+
+        // Check that endpoint was in Sending state
+        if (pEndpoint->state == UDP_ENDPOINT_SENDING) {
+
+            // End of transfer ?
+            if (UDP_IsTransferFinished(bEndpoint)) {
+
+                pTransfer->transferred += pTransfer->buffered;
+                pTransfer->buffered = 0;
+
+                // Disable interrupt if this is not a control endpoint
+                if ((status & AT91C_UDP_EPTYPE) != AT91C_UDP_EPTYPE_CTRL) {
+
+                    AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+                }
+
+                UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+                CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+            }
+            else {
+
+                // Transfer remaining data
+                TRACE_DEBUG_WP(" %d ", pEndpoint->size);
+
+                pTransfer->transferred += pEndpoint->size;
+                pTransfer->buffered -= pEndpoint->size;
+
+                // Send next packet
+                if (BOARD_USB_ENDPOINTS_BANKS(bEndpoint) == 1) {
+
+                    // No double buffering
+                    UDP_WritePayload(bEndpoint);
+                    SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+                    CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+                }
+                else {
+                    // Double buffering
+                    SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+                    CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+                    UDP_WritePayload(bEndpoint);
+                }
+            }
+        }
+        else {
+            // Acknowledge interrupt
+            TRACE_ERROR("Error Wr");
+            CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+        }
+    }
+
+    // OUT packet received
+    if ((status & UDP_RXDATA) != 0) {
+
+        TRACE_DEBUG_WP("Rd ");
+
+        // Check that the endpoint is in Receiving state
+        if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {
+
+            // Check if an ACK has been received on a Control endpoint
+            if (((status & AT91C_UDP_EPTYPE) == AT91C_UDP_EPTYPE_CTRL)
+                && ((status & AT91C_UDP_RXBYTECNT) == 0)) {
+
+                // Acknowledge the data and finish the current transfer
+                UDP_ClearRxFlag(bEndpoint);
+                UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+            }
+            // Check if the data has been STALLed
+            else if ((status & AT91C_UDP_FORCESTALL) != 0) {
+
+                // Discard STALLed data
+                TRACE_DEBUG_WP("Discard ");
+                UDP_ClearRxFlag(bEndpoint);
+            }
+            // NAK the data
+            else {
+
+                TRACE_DEBUG_WP("Nak ");
+                AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+            }
+        }
+        // Endpoint is in Read state
+        else {
+
+            // Retrieve data and store it into the current transfer buffer
+            wPacketSize = (unsigned short) (status >> 16);
+            TRACE_DEBUG_WP("%d ", wPacketSize);
+            UDP_ReadPayload(bEndpoint, wPacketSize);
+            UDP_ClearRxFlag(bEndpoint);
+
+            // Check if the transfer is finished
+            if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {
+
+                // Disable interrupt if this is not a control endpoint
+                if ((status & AT91C_UDP_EPTYPE) != AT91C_UDP_EPTYPE_CTRL) {
+
+                    AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+                }
+                UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+            }
+        }
+    }
+
+    // STALL sent
+    if ((status & AT91C_UDP_STALLSENT) != 0) {
+
+        TRACE_WARNING( "Sta 0x%X [%d] ", status, bEndpoint);
+
+        // If the endpoint is not halted, clear the STALL condition
+        CLEAR_CSR(bEndpoint, AT91C_UDP_STALLSENT);
+        if (pEndpoint->state != UDP_ENDPOINT_HALTED) {
+
+            TRACE_WARNING( "_ " );
+            CLEAR_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+        }
+    }
+
+    // SETUP packet received
+    if ((status & AT91C_UDP_RXSETUP) != 0) {
+
+        TRACE_DEBUG_WP("Stp ");
+
+        // If a transfer was pending, complete it
+        // Handles the case where during the status phase of a control write
+        // transfer, the host receives the device ZLP and ack it, but the ack
+        // is not received by the device
+        if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+            || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+            UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+        }
+        // Copy the setup packet
+        UDP_ReadRequest(&request);
+
+        // Set the DIR bit before clearing RXSETUP in Control IN sequence
+        if (USBGenericRequest_GetDirection(&request) == USBGenericRequest_IN) {
+
+            SET_CSR(bEndpoint, AT91C_UDP_DIR);
+        }
+        // Acknowledge setup packet
+        CLEAR_CSR(bEndpoint, AT91C_UDP_RXSETUP);
+
+        // Forward the request to the upper layer
+        USBDCallbacks_RequestReceived(&request);
+    }
+
+}
+
+//------------------------------------------------------------------------------
+//      Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// USB interrupt handler
+/// Manages device resume, suspend, end of bus reset. 
+/// Forwards endpoint interrupts to the appropriate handler.
+//------------------------------------------------------------------------------
+void USBD_InterruptHandler(void)
+{
+    unsigned int status;
+    int eptnum = 0;
+    
+    // Get interrupt status
+    // Some interrupts may get masked depending on the device state
+    status = AT91C_BASE_UDP->UDP_ISR;
+    status &= AT91C_BASE_UDP->UDP_IMR;
+
+    if (deviceState < USBD_STATE_POWERED) {
+
+        status &= AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+        AT91C_BASE_UDP->UDP_ICR = ~status;
+    }
+
+    // Return immediately if there is no interrupt to service
+    if (status == 0) {
+
+        return;
+    }
+
+    // Toggle USB LED if the device is active
+    if (deviceState >= USBD_STATE_POWERED) {
+
+        LED_Set(USBD_LEDUSB);
+    }
+
+    // Service interrupts
+
+    //// Start Of Frame (SOF)
+    //if (ISSET(dStatus, AT91C_UDP_SOFINT)) {
+    //
+    //    TRACE_DEBUG("SOF");
+    //
+    //    // Invoke the SOF callback
+    //    USB_StartOfFrameCallback(pUsb);
+    //
+    //    // Acknowledge interrupt
+    //    AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_SOFINT;
+    //    dStatus &= ~AT91C_UDP_SOFINT;
+    //}
+
+    // Suspend
+    // This interrupt is always treated last (hence the '==')
+    if (status == AT91C_UDP_RXSUSP) {
+
+        TRACE_INFO_WP("Susp ");
+
+        // Don't do anything if the device is already suspended
+        if (deviceState != USBD_STATE_SUSPENDED) {
+
+            // The device enters the Suspended state
+            // Enable wakeup
+            AT91C_BASE_UDP->UDP_IER = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+
+            // Acknowledge interrupt
+            AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_RXSUSP;
+
+            // Switch to the Suspended state
+            previousDeviceState = deviceState;
+            deviceState = USBD_STATE_SUSPENDED;
+            // Invoke the Suspended callback
+            USBDCallbacks_Suspended();
+            UDP_DisableTransceiver();
+            UDP_DisablePeripheralClock();
+            UDP_DisableUsbClock();
+        }
+    }
+    // Resume
+    else if ((status & (AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM)) != 0) {
+
+        TRACE_INFO_WP("Res ");
+
+        // Don't do anything if the device was not suspended
+        if (deviceState == USBD_STATE_SUSPENDED) {
+
+            // The device enters its previous state
+            UDP_EnablePeripheralClock();
+            UDP_EnableUsbClock();
+
+            // Enable the transceiver if the device was past the Default
+            // state
+            deviceState = previousDeviceState;
+            if (deviceState >= USBD_STATE_DEFAULT) {
+
+                UDP_EnableTransceiver();
+
+                // Invoke the Resume callback
+                USBDCallbacks_Resumed();
+            }
+        }
+        
+        // Clear and disable resume interrupts
+        AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_WAKEUP 
+                                  | AT91C_UDP_RXRSM
+                                  | AT91C_UDP_RXSUSP;
+        AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+    }
+    // End of bus reset
+    else if ((status & AT91C_UDP_ENDBUSRES) != 0) {
+
+        TRACE_INFO_WP("EoBRes ");
+
+        // The device enters the Default state
+        deviceState = USBD_STATE_DEFAULT;
+        UDP_EnableTransceiver();
+        UDP_ResetEndpoints();
+        UDP_DisableEndpoints();
+        USBD_ConfigureEndpoint(0);
+
+        // Flush and enable the Suspend interrupt
+        AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_WAKEUP
+                                  | AT91C_UDP_RXRSM
+                                  | AT91C_UDP_RXSUSP;
+        AT91C_BASE_UDP->UDP_IER = AT91C_UDP_RXSUSP;
+
+        //// Enable the Start Of Frame (SOF) interrupt if needed
+        //if (pUsb->pCallbacks->startOfFrame != 0) {
+        //
+        //    AT91C_BASE_UDP->UDP_IER = AT91C_UDP_SOFINT;
+        //}
+
+        // Invoke the Reset callback
+        USBDCallbacks_Reset();
+
+        // Acknowledge end of bus reset interrupt
+        AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
+    }
+    // Endpoint interrupts
+    else {
+
+        while (status != 0) {
+
+            // Check if endpoint has a pending interrupt
+            if ((status & (1 << eptnum)) != 0) {
+            
+                UDP_EndpointHandler(eptnum);
+                status &= ~(1 << eptnum);
+                
+                if (status != 0) {
+                
+                    TRACE_INFO_WP("\n\r  - ");
+                }
+            }
+            eptnum++;
+        }
+    }
+
+    // Toggle LED back to its previous state
+    TRACE_INFO_WP("\n\r");
+    if (deviceState >= USBD_STATE_POWERED) {
+
+        LED_Clear(USBD_LEDUSB);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Configures an endpoint according to its Endpoint Descriptor.
+/// \param pDescriptor Pointer to an Endpoint descriptor.
+//------------------------------------------------------------------------------
+void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
+{
+    Endpoint *pEndpoint;
+    unsigned char bEndpoint;
+    unsigned char bType;
+    unsigned char bEndpointDir;
+
+    // NULL descriptor -> Control endpoint 0
+    if (pDescriptor == 0) {
+
+        bEndpoint = 0;
+        pEndpoint = &(endpoints[bEndpoint]);
+        bType= USBEndpointDescriptor_CONTROL;
+        bEndpointDir = 0;
+        pEndpoint->size = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0);
+    }
+    else {
+
+        bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
+        pEndpoint = &(endpoints[bEndpoint]);
+        bType = USBEndpointDescriptor_GetType(pDescriptor);
+        bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
+        pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
+    }
+
+    // Abort the current transfer is the endpoint was configured and in
+    // Write or Read state
+    if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+        || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+        UDP_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
+    }
+    pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+    // Reset Endpoint Fifos
+    AT91C_BASE_UDP->UDP_RSTEP |= (1 << bEndpoint);
+    AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << bEndpoint);
+
+    // Configure endpoint
+    SET_CSR(bEndpoint, (unsigned int)AT91C_UDP_EPEDS | (bType << 8) | (bEndpointDir << 10));
+    if (bType == USBEndpointDescriptor_CONTROL) {
+
+        AT91C_BASE_UDP->UDP_IER = (1 << bEndpoint);
+    }
+
+    TRACE_INFO_WP("CfgEpt%d ", bEndpoint);
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through a USB endpoint. Sets up the transfer descriptor,
+/// writes one or two data payloads (depending on the number of FIFO bank
+/// for the endpoint) and then starts the actual transfer. The operation is
+/// complete when all the data has been sent.
+///
+/// *If the size of the buffer is greater than the size of the endpoint
+///  (or twice the size if the endpoint has two FIFO banks), then the buffer
+///  must be kept allocated until the transfer is finished*. This means that
+///  it is not possible to declare it on the stack (i.e. as a local variable
+///  of a function which returns after starting a transfer).
+///
+/// \param bEndpoint Endpoint number.
+/// \param pData Pointer to a buffer with the data to send.
+/// \param dLength Size of the data buffer.
+/// \param fCallback Optional callback function to invoke when the transfer is
+///        complete.
+/// \param pArgument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer has been started;
+///         otherwise, the corresponding error status code.
+//------------------------------------------------------------------------------
+char USBD_Write( unsigned char    bEndpoint,
+                 const void       *pData,
+                 unsigned int     dLength,
+                 TransferCallback fCallback,
+                 void             *pArgument )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Check that the endpoint is in Idle state
+    if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+        return USBD_STATUS_LOCKED;
+    }
+    TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
+
+    // Setup the transfer descriptor
+    pTransfer->pData = (void *) pData;
+    pTransfer->remaining = dLength;
+    pTransfer->buffered = 0;
+    pTransfer->transferred = 0;
+    pTransfer->fCallback = fCallback;
+    pTransfer->pArgument = pArgument;
+
+    // Send the first packet
+    pEndpoint->state = UDP_ENDPOINT_SENDING;
+    while((AT91C_BASE_UDP->UDP_CSR[bEndpoint]&AT91C_UDP_TXPKTRDY)==AT91C_UDP_TXPKTRDY);
+    UDP_WritePayload(bEndpoint);
+    SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+
+    // If double buffering is enabled and there is data remaining,
+    // prepare another packet
+    if ((BOARD_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->remaining > 0)) {
+
+        UDP_WritePayload(bEndpoint);
+    }
+
+    // Enable interrupt on endpoint
+    AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+
+    return USBD_STATUS_SUCCESS;
+}
+
+
+//------------------------------------------------------------------------------
+/// Reads incoming data on an USB endpoint This methods sets the transfer
+/// descriptor and activate the endpoint interrupt. The actual transfer is
+/// then carried out by the endpoint interrupt handler. The Read operation
+/// finishes either when the buffer is full, or a short packet (inferior to
+/// endpoint maximum  size) is received.
+///
+/// *The buffer must be kept allocated until the transfer is finished*.
+/// \param bEndpoint Endpoint number.
+/// \param pData Pointer to a data buffer.
+/// \param dLength Size of the data buffer in bytes.
+/// \param fCallback Optional end-of-transfer callback function.
+/// \param pArgument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the read operation has been started;
+///         otherwise, the corresponding error code.
+//------------------------------------------------------------------------------
+char USBD_Read(unsigned char    bEndpoint,
+               void             *pData,
+               unsigned int     dLength,
+               TransferCallback fCallback,
+               void             *pArgument)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Return if the endpoint is not in IDLE state
+    if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+        return USBD_STATUS_LOCKED;
+    }
+
+    // Endpoint enters Receiving state
+    pEndpoint->state = UDP_ENDPOINT_RECEIVING;
+    TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+    // Set the transfer descriptor
+    pTransfer->pData = pData;
+    pTransfer->remaining = dLength;
+    pTransfer->buffered = 0;
+    pTransfer->transferred = 0;
+    pTransfer->fCallback = fCallback;
+    pTransfer->pArgument = pArgument;
+
+    // Enable interrupt on endpoint
+    AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+
+    return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the HALT feature on the given endpoint (if not already in this state).
+/// \param bEndpoint Endpoint number.
+//------------------------------------------------------------------------------
+void USBD_Halt(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    
+    // Check that endpoint is enabled and not already in Halt state
+    if ((pEndpoint->state != UDP_ENDPOINT_DISABLED)
+        && (pEndpoint->state != UDP_ENDPOINT_HALTED)) {
+
+        TRACE_DEBUG_WP("Halt%d ", bEndpoint);
+
+        // Abort the current transfer if necessary
+        UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+
+        // Put endpoint into Halt state
+        SET_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+        pEndpoint->state = UDP_ENDPOINT_HALTED;
+
+        // Enable the endpoint interrupt
+        AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the Halt feature on the given endpoint.
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Unhalt(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+    // Check if the endpoint is enabled
+    if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
+
+        TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
+
+        // Return endpoint to Idle state
+        pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+        // Clear FORCESTALL flag
+        CLEAR_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+
+        // Reset Endpoint Fifos, beware this is a 2 steps operation
+        AT91C_BASE_UDP->UDP_RSTEP |= 1 << bEndpoint;
+        AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << bEndpoint);
+    }
+}
+    
+//------------------------------------------------------------------------------
+/// Returns the current Halt status of an endpoint.
+/// \param bEndpoint Index of endpoint
+/// \return 1 if the endpoint is currently halted; otherwise 0
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHalted(unsigned char bEndpoint)
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    unsigned char status = 0;
+
+    if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+
+        status = 1;
+    }
+    return( status );
+}
+
+//------------------------------------------------------------------------------
+/// Indicates if the device is running in high or full-speed. Always returns 0
+/// since UDP does not support high-speed mode.
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHighSpeed(void)
+{
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+/// Causes the given endpoint to acknowledge the next packet it receives
+/// with a STALL handshake.
+/// \param bEndpoint Endpoint number.
+/// \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
+//------------------------------------------------------------------------------
+unsigned char USBD_Stall(unsigned char bEndpoint)
+
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+    // Check that endpoint is in Idle state
+    if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+        TRACE_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
+        return USBD_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_WP("Stall%d ", bEndpoint);
+    SET_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+
+    return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Starts a remote wake-up procedure.
+//------------------------------------------------------------------------------
+void USBD_RemoteWakeUp(void)
+{
+    UDP_EnablePeripheralClock();
+    UDP_EnableUsbClock();
+    UDP_EnableTransceiver();
+
+    TRACE_INFO_WP("RWUp ");
+
+    // Activates a remote wakeup (edge on ESR), then clear ESR
+    AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_ESR;
+    AT91C_BASE_UDP->UDP_GLBSTATE &= ~AT91C_UDP_ESR;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the device address to the given value.
+/// \param address New device address.
+//------------------------------------------------------------------------------
+void USBD_SetAddress(unsigned char address)
+{
+    TRACE_INFO_WP("SetAddr(%d) ", address);
+
+    // Set address
+    AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | address;
+
+    // If the address is 0, the device returns to the Default state
+    if (address == 0) {
+
+        AT91C_BASE_UDP->UDP_GLBSTATE = 0;
+        deviceState = USBD_STATE_DEFAULT;
+    }
+    // If the address is non-zero, the device enters the Address state
+    else {
+
+        AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+        deviceState = USBD_STATE_ADDRESS;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current device configuration.
+/// \param cfgnum - Configuration number to set.
+//------------------------------------------------------------------------------
+void USBD_SetConfiguration(unsigned char cfgnum)
+{
+    TRACE_INFO_WP("SetCfg(%d) ", cfgnum);
+
+    // If the configuration number if non-zero, the device enters the
+    // Configured state
+    if (cfgnum != 0) {
+
+        // Enter Configured state
+        deviceState = USBD_STATE_CONFIGURED;
+        AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_CONFG;
+    }
+    // If the configuration number is zero, the device goes back to the Address
+    // state
+    else {
+
+        deviceState = USBD_STATE_ADDRESS;
+        AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+
+        // Abort all transfers
+        UDP_DisableEndpoints();
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Connects the pull-up on the D+ line of the USB.
+//------------------------------------------------------------------------------
+void USBD_Connect(void)
+{
+    TRACE_DEBUG("Conn ");
+
+#if defined(BOARD_USB_PULLUP_EXTERNAL)
+    const Pin pinPullUp = PIN_USB_PULLUP;
+    if (pinPullUp.attribute == PIO_OUTPUT_0) {
+
+        PIO_Set(&pinPullUp);
+    }
+    else {
+
+        PIO_Clear(&pinPullUp);
+    }
+#elif defined(BOARD_USB_PULLUP_INTERNAL)
+    AT91C_BASE_UDP->UDP_TXVC |= AT91C_UDP_PUON;
+#elif defined(BOARD_USB_PULLUP_MATRIX)
+    AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
+#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
+    #error Unsupported pull-up type.
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disconnects the pull-up from the D+ line of the USB.
+//------------------------------------------------------------------------------
+void USBD_Disconnect(void)
+{
+    TRACE_DEBUG("Disc ");
+
+#if defined(BOARD_USB_PULLUP_EXTERNAL)
+    const Pin pinPullUp = PIN_USB_PULLUP;
+    if (pinPullUp.attribute == PIO_OUTPUT_0) {
+
+        PIO_Clear(&pinPullUp);
+    }
+    else {
+
+        PIO_Set(&pinPullUp);
+    }
+#elif defined(BOARD_USB_PULLUP_INTERNAL)
+    AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
+#elif defined(BOARD_USB_PULLUP_MATRIX)
+    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
+    #error Unsupported pull-up type.
+#endif
+
+    // Device returns to the Powered state
+    if (deviceState > USBD_STATE_POWERED) {
+    
+        deviceState = USBD_STATE_POWERED;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Initializes the USB driver.
+//------------------------------------------------------------------------------
+void USBD_Init(void)
+{
+    TRACE_INFO_WP("USBD_Init\n\r");
+
+    // Reset endpoint structures
+    UDP_ResetEndpoints();
+
+    // Configure the pull-up on D+ and disconnect it
+#if defined(BOARD_USB_PULLUP_EXTERNAL)
+    const Pin pinPullUp = PIN_USB_PULLUP;
+    PIO_Configure(&pinPullUp, 1);
+#elif defined(BOARD_USB_PULLUP_INTERNAL)
+    AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
+#elif defined(BOARD_USB_PULLUP_MATRIX)
+    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
+    #error Missing pull-up definition.
+#endif
+
+    // Device is in the Attached state
+    deviceState = USBD_STATE_SUSPENDED;
+    previousDeviceState = USBD_STATE_POWERED;
+    UDP_EnablePeripheralClock();
+    UDP_EnableUsbClock();
+
+    AT91C_BASE_UDP->UDP_IDR = 0xFE;
+
+    AT91C_BASE_UDP->UDP_IER = AT91C_UDP_WAKEUP;
+
+    // Configure interrupts
+    USBDCallbacks_Initialized();
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current state of the USB device.
+/// \return Device current state.
+//------------------------------------------------------------------------------
+unsigned char USBD_GetState(void)
+{
+    return deviceState;
+}
+
+#endif // BOARD_USB_UDP
+
diff --git a/at91lib/usb/device/core/USBD_UDPHS.c b/at91lib/usb/device/core/USBD_UDPHS.c
new file mode 100644
index 0000000..f7c0684
--- /dev/null
+++ b/at91lib/usb/device/core/USBD_UDPHS.c
@@ -0,0 +1,1680 @@
+/* ----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support 
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+//         Headers
+//------------------------------------------------------------------------------
+
+#include "USBD.h"
+#include "USBDCallbacks.h"
+#include "USBDDriver.h"
+#include <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <utility/led.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+
+#include <stdio.h>
+
+#ifdef BOARD_USB_UDPHS
+
+//------------------------------------------------------------------------------
+//         Definitions
+//------------------------------------------------------------------------------
+
+/// Maximum number of endpoints interrupts.
+#define NUM_IT_MAX       \
+    (AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_EPT_NBR_MAX)
+/// Maximum number of endpoint DMA interrupts
+#define NUM_IT_MAX_DMA   \
+    ((AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_DMA_CHANNEL_NBR)>>4)
+/// Bits that should be shifted to access DMA control bits.
+#define SHIFT_DMA        24
+/// Bits that should be shifted to access interrupt bits.
+#define SHIFT_INTERUPT    8
+
+/// Compile option, use DMA. Remove this define for not use DMA.
+#define DMA
+
+/// Max size of the FMA FIFO
+#define DMA_MAX_FIFO_SIZE 65536
+
+//------------------------------------------------------------------------------
+/// \page "Endpoint states"
+/// This page lists the endpoint states.
+/// !States
+//  - UDP_ENDPOINT_DISABLED
+//  - UDP_ENDPOINT_HALTED
+//  - UDP_ENDPOINT_IDLE
+//  - UDP_ENDPOINT_SENDING
+//  - UDP_ENDPOINT_RECEIVING
+
+/// Endpoint states: Endpoint is disabled
+#define UDP_ENDPOINT_DISABLED       0
+/// Endpoint states: Endpoint is halted (i.e. STALLs every request)
+#define UDP_ENDPOINT_HALTED         1
+/// Endpoint states: Endpoint is idle (i.e. ready for transmission)
+#define UDP_ENDPOINT_IDLE           2
+/// Endpoint states: Endpoint is sending data
+#define UDP_ENDPOINT_SENDING        3
+/// Endpoint states: Endpoint is receiving data
+#define UDP_ENDPOINT_RECEIVING      4
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//      Structures
+//------------------------------------------------------------------------------
+
+/// Describes an ongoing transfer on a UDP endpoint.
+typedef struct
+{
+    /// Pointer to a data buffer used for emission/reception.
+    char             *pData;
+    /// Number of bytes which have been written into the UDP internal FIFO
+    /// buffers.
+    volatile int     buffered;
+    /// Number of bytes which have been sent/received.
+    volatile int     transferred;
+    /// Number of bytes which have not been buffered/transferred yet.
+    volatile int     remaining;
+    /// Optional callback to invoke when the transfer completes.
+    volatile TransferCallback fCallback;
+    /// Optional argument to the callback function.
+    void             *pArgument;
+} Transfer;
+
+//------------------------------------------------------------------------------
+/// Describes the state of an endpoint of the UDP controller.
+//------------------------------------------------------------------------------
+typedef struct
+{
+    /// Current endpoint state.
+    volatile unsigned char  state;
+    /// Current reception bank (0 or 1).
+    unsigned char  bank;
+    /// Maximum packet size for the endpoint.
+    unsigned short size;
+    /// Describes an ongoing transfer (if current state is either
+    ///  <UDP_ENDPOINT_SENDING> or <UDP_ENDPOINT_RECEIVING>)
+    Transfer       transfer;
+} Endpoint;
+
+//------------------------------------------------------------------------------
+//         Internal variables
+//------------------------------------------------------------------------------
+
+/// Holds the internal state for each endpoint of the UDP.
+static Endpoint      endpoints[BOARD_USB_NUMENDPOINTS];
+/// Device current state.
+static unsigned char deviceState;
+/// Indicates the previous device state
+static unsigned char previousDeviceState;
+/// Special case for send a ZLP
+static unsigned char sendZLP = 0;
+
+/// 7.1.20 Test Mode Support
+/// Test codes for the USB HS test mode.
+static const char test_packet_buffer[] = {
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // JKJKJKJK * 9
+    0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,                     // JJKKJJKK * 8
+    0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,                     // JJJJKKKK * 8
+    0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
+    0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,                          // JJJJJJJK * 8
+    0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E                 // {JKKKKKKK * 10}, JK
+};
+
+//------------------------------------------------------------------------------
+//      Internal Functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Disables the BIAS of the USB controller
+//------------------------------------------------------------------------------
+static inline void UDPHS_DisableBIAS( void )
+{
+    // For CAP9, SAM9RL, HS
+#if !defined (BOARD_USB_NO_BIAS_COMMAND)
+    AT91C_BASE_PMC->PMC_UCKR &= ~AT91C_CKGR_BIASEN_ENABLED;
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Enables the BIAS of the USB controller
+//------------------------------------------------------------------------------
+static inline void UDPHS_EnableBIAS( void )
+{
+    // For CAP9, SAM9RL, HS
+#if !defined (BOARD_USB_NO_BIAS_COMMAND)
+    UDPHS_DisableBIAS();
+    AT91C_BASE_PMC->PMC_UCKR |= AT91C_CKGR_BIASEN_ENABLED;
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Enable UDPHS clock
+//------------------------------------------------------------------------------
+static inline void UDPHS_EnableUsbClock( void )
+{
+#if !defined (PMC_BY_HARD)
+    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDPHS);
+    // Enable 480MHZ
+    AT91C_BASE_CKGR->CKGR_UCKR |= (AT91C_CKGR_PLLCOUNT & (3 << 20)) | AT91C_CKGR_UPLLEN;
+    // Wait until UTMI PLL is locked
+    while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKU) == 0);
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disable UDPHS clock
+//------------------------------------------------------------------------------
+static inline void UDPHS_DisableUsbClock( void )
+{
+#if !defined (PMC_BY_HARD)
+    AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_UDPHS);
+    // 480MHZ
+    AT91C_BASE_CKGR->CKGR_UCKR &= ~AT91C_CKGR_UPLLEN;
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Handles a completed transfer on the given endpoint, invoking the
+/// configured callback if any.
+/// \param bEndpoint Number of the endpoint for which the transfer has completed.
+/// \param bStatus   Status code returned by the transfer operation
+//------------------------------------------------------------------------------
+static void UDPHS_EndOfTransfer( unsigned char bEndpoint, char bStatus )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Check that endpoint was sending or receiving data
+    if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+     || (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
+
+        TRACE_DEBUG_WP("Eo");
+
+        // Endpoint returns in Idle state
+        pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+        // Invoke callback is present
+        if (pTransfer->fCallback != 0) {
+
+            ((TransferCallback) pTransfer->fCallback)
+                (pTransfer->pArgument,
+                 bStatus,
+                 pTransfer->transferred,
+                 pTransfer->remaining + pTransfer->buffered);
+        }
+        else {
+            TRACE_DEBUG_WP("No callBack\n\r");
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the correct RX flag in endpoint status register
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDPHS_ClearRxFlag( unsigned char bEndpoint )
+{
+    AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_RX_BK_RDY;
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static void UDPHS_WritePayload( unsigned char bEndpoint )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+    char     *pFifo;
+    signed int   size;
+    unsigned int dCtr;
+
+    pFifo = (char*)((unsigned int *)AT91C_BASE_UDPHS_EPTFIFO + (16384 * bEndpoint));
+
+    // Get the number of bytes to send
+    size = pEndpoint->size;
+    if (size > pTransfer->remaining) {
+
+        size = pTransfer->remaining;
+    }
+
+    // Update transfer descriptor information
+    pTransfer->buffered += size;
+    pTransfer->remaining -= size;
+
+    // Write packet in the FIFO buffer
+    dCtr = 0;
+    while (size > 0) {
+
+        pFifo[dCtr] = *(pTransfer->pData);
+        pTransfer->pData++;
+        size--;
+        dCtr++;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from an endpoint FIFO to the current transfer buffer
+/// \param bEndpoint   Endpoint number.
+/// \param wPacketSize Size of received data packet
+//------------------------------------------------------------------------------
+static void UDPHS_ReadPayload( unsigned char bEndpoint, int wPacketSize )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+    char     *pFifo;
+    unsigned char dBytes=0;
+
+    pFifo = (char*)((unsigned int *)AT91C_BASE_UDPHS_EPTFIFO + (16384 * bEndpoint));
+
+    // Check that the requested size is not bigger than the remaining transfer
+    if (wPacketSize > pTransfer->remaining) {
+
+        pTransfer->buffered += wPacketSize - pTransfer->remaining;
+        wPacketSize = pTransfer->remaining;
+    }
+
+    // Update transfer descriptor information
+    pTransfer->remaining -= wPacketSize;
+    pTransfer->transferred += wPacketSize;
+
+    // Retrieve packet
+    while (wPacketSize > 0) {
+
+        *(pTransfer->pData) = pFifo[dBytes];
+        pTransfer->pData++;
+        wPacketSize--;
+        dBytes++;
+    }
+}
+
+
+//------------------------------------------------------------------------------
+/// Received SETUP packet from endpoint 0 FIFO
+/// \param pRequest Generic USB SETUP request sent over Control endpoints
+//------------------------------------------------------------------------------
+static void UDPHS_ReadRequest( USBGenericRequest *pRequest )
+{
+    unsigned int *pData = (unsigned int *)pRequest;
+    unsigned int fifo;
+
+    fifo = (AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[0]);
+    *pData = fifo;
+    fifo = (AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[0]);
+    pData++;
+    *pData = fifo;
+    //TRACE_ERROR("SETUP: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n\r", pData[0],pData[1],pData[2],pData[3],pData[4],pData[5],pData[6],pData[7]);
+}
+
+//------------------------------------------------------------------------------
+/// Reset all endpoint transfer descriptors
+//------------------------------------------------------------------------------
+static void UDPHS_ResetEndpoints( void )
+{
+    Endpoint *pEndpoint;
+    Transfer *pTransfer;
+    unsigned char bEndpoint;
+
+    // Reset the transfer descriptor of every endpoint
+    for( bEndpoint = 0; bEndpoint < BOARD_USB_NUMENDPOINTS; bEndpoint++ ) {
+
+        pEndpoint = &(endpoints[bEndpoint]);
+        pTransfer = &(pEndpoint->transfer);
+
+        // Reset endpoint transfer descriptor
+        pTransfer->pData = 0;
+        pTransfer->transferred = -1;
+        pTransfer->buffered = -1;
+        pTransfer->remaining = -1;
+        pTransfer->fCallback = 0;
+        pTransfer->pArgument = 0;
+
+        // Reset endpoint state
+        pEndpoint->bank = 0;
+        pEndpoint->state = UDP_ENDPOINT_DISABLED;
+    }
+}
+
+
+//------------------------------------------------------------------------------
+/// Disable all endpoints (except control endpoint 0), aborting current 
+/// transfers if necessary
+//------------------------------------------------------------------------------
+static void UDPHS_DisableEndpoints( void )
+{
+    unsigned char bEndpoint;
+
+    // Disable each endpoint, terminating any pending transfer
+    // Control endpoint 0 is not disabled
+    for( bEndpoint = 1; bEndpoint < BOARD_USB_NUMENDPOINTS; bEndpoint++ ) {
+
+        UDPHS_EndOfTransfer( bEndpoint, USBD_STATUS_ABORTED );
+        endpoints[bEndpoint].state = UDP_ENDPOINT_DISABLED;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Endpoint interrupt handler.
+/// Handle IN/OUT transfers, received SETUP packets and STALLing
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDPHS_EndpointHandler( unsigned char bEndpoint )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+    unsigned int   status = AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSTA;
+    unsigned short wPacketSize;
+    USBGenericRequest request;
+
+    TRACE_DEBUG_WP("E%d ", bEndpoint);
+    TRACE_DEBUG_WP("st:0x%X ", status);
+
+    // Handle interrupts
+    // IN packet sent
+    if( (AT91C_UDPHS_TX_PK_RDY == (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTL & AT91C_UDPHS_TX_PK_RDY))
+     && (0 == (status & AT91C_UDPHS_TX_PK_RDY )) ) {
+
+        TRACE_DEBUG_WP("Wr ");
+
+        // Check that endpoint was in Sending state
+        if( pEndpoint->state == UDP_ENDPOINT_SENDING ) {
+
+            if (pTransfer->buffered > 0) {
+                pTransfer->transferred += pTransfer->buffered;
+                pTransfer->buffered = 0;
+            }
+
+            if(  ((pTransfer->buffered)==0)
+               &&((pTransfer->transferred)==0)
+               &&((pTransfer->remaining)==0)
+               &&(sendZLP == 0)) {
+                sendZLP = 1;
+            }
+
+            // End of transfer ?
+            if( (pTransfer->remaining > 0)
+              ||(sendZLP == 1)) {
+                TRACE_DEBUG_WP("\n\r1pTransfer->buffered %d \n\r", pTransfer->buffered);
+                TRACE_DEBUG_WP("1pTransfer->transferred %d \n\r", pTransfer->transferred);
+                TRACE_DEBUG_WP("1pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+                // Transfer remaining data
+                TRACE_DEBUG_WP(" %d ", pEndpoint->size);
+
+                // Send next packet
+                UDPHS_WritePayload(bEndpoint);
+                AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+                sendZLP = 2;
+            }
+            else {
+                TRACE_DEBUG_WP("\n\r0pTransfer->buffered %d \n\r", pTransfer->buffered);
+                TRACE_DEBUG_WP("0pTransfer->transferred %d \n\r", pTransfer->transferred);
+                TRACE_DEBUG_WP("0pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+                TRACE_DEBUG_WP(" %d ", pTransfer->transferred);
+
+                // Disable interrupt if this is not a control endpoint
+                if( AT91C_UDPHS_EPT_TYPE_CTL_EPT != (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {
+
+                    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+                }
+                AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_TX_PK_RDY;
+
+                UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+                sendZLP = 0;
+            }
+        }
+        else {
+
+            TRACE_ERROR("Error Wr");
+        }
+    }
+
+    // OUT packet received
+    if( AT91C_UDPHS_RX_BK_RDY == (status & AT91C_UDPHS_RX_BK_RDY) ) {
+
+        TRACE_DEBUG_WP("Rd ");
+
+        // Check that the endpoint is in Receiving state
+        if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {
+
+            // Check if an ACK has been received on a Control endpoint
+            if( (0 == (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG & AT91C_UDPHS_EPT_TYPE))
+             && (0 == (status & AT91C_UDPHS_BYTE_COUNT)) ) {
+
+                // Control endpoint, 0 bytes received
+                // Acknowledge the data and finish the current transfer
+                TRACE_DEBUG_WP("Ack ");
+                UDPHS_ClearRxFlag(bEndpoint);
+                UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+            }
+            // Check if the data has been STALLed
+            else if( AT91C_UDPHS_FRCESTALL == (status & AT91C_UDPHS_FRCESTALL)) {
+
+                // Discard STALLed data
+                TRACE_DEBUG_WP("Discard ");
+                UDPHS_ClearRxFlag(bEndpoint);
+            }
+            // NAK the data
+            else {
+
+                TRACE_DEBUG_WP("Nak ");
+                AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+            }
+        }
+        else {
+
+            // Endpoint is in Read state
+            // Retrieve data and store it into the current transfer buffer
+            wPacketSize = (unsigned short)((status & AT91C_UDPHS_BYTE_COUNT)>>20);
+
+            TRACE_DEBUG_WP("%d ", wPacketSize);
+            UDPHS_ReadPayload(bEndpoint, wPacketSize);
+            UDPHS_ClearRxFlag(bEndpoint);
+
+            // Check if the transfer is finished
+            if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {
+
+                AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_RX_BK_RDY;
+
+                // Disable interrupt if this is not a control endpoint
+                if( AT91C_UDPHS_EPT_TYPE_CTL_EPT != (AT91C_UDPHS_EPT_TYPE & (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {
+
+                    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+                }
+                UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+            }
+        }
+    }
+
+
+    // STALL sent
+    if( AT91C_UDPHS_STALL_SNT == (status & AT91C_UDPHS_STALL_SNT) ) {
+
+        TRACE_WARNING( "Sta 0x%X [%d] ", status, bEndpoint);
+
+        // Acknowledge the stall flag
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_STALL_SNT;
+
+        // If the endpoint is not halted, clear the STALL condition
+        if (pEndpoint->state != UDP_ENDPOINT_HALTED) {
+
+            TRACE_WARNING( "_ " );
+            AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_FRCESTALL;
+        }
+    }
+
+    // SETUP packet received
+    if( AT91C_UDPHS_RX_SETUP == (status & AT91C_UDPHS_RX_SETUP) )  {
+
+        TRACE_DEBUG_WP("Stp ");
+
+        // If a transfer was pending, complete it
+        // Handles the case where during the status phase of a control write
+        // transfer, the host receives the device ZLP and ack it, but the ack
+        // is not received by the device
+        if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+            || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+            UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+        }
+        // Copy the setup packet
+        UDPHS_ReadRequest(&request);
+
+        // Acknowledge setup packet
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_RX_SETUP;
+
+        // Forward the request to the upper layer
+        USBDCallbacks_RequestReceived(&request);
+    }
+
+}
+
+//------------------------------------------------------------------------------
+//      Interrupt service routine
+//------------------------------------------------------------------------------
+#ifdef DMA
+//----------------------------------------------------------------------------
+/// Endpoint DMA interrupt handler.
+/// This function (ISR) handles dma interrupts
+/// \param bEndpoint Index of endpoint
+//----------------------------------------------------------------------------
+static void UDPHS_DmaHandler( unsigned char bEndpoint )
+{
+    Endpoint     *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer     *pTransfer = &(pEndpoint->transfer);
+    int           justTransferred;
+    unsigned int  status;
+    unsigned char result = USBD_STATUS_SUCCESS;
+
+    status = AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+    TRACE_DEBUG_WP("Dma Ept%d ", bEndpoint);
+
+    // Disable DMA interrupt to avoid receiving 2 interrupts (B_EN and TR_EN)
+    AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL &=
+        ~(AT91C_UDPHS_END_TR_EN | AT91C_UDPHS_END_B_EN);
+
+    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1 << SHIFT_DMA << bEndpoint);
+
+    if( AT91C_UDPHS_END_BF_ST == (status & AT91C_UDPHS_END_BF_ST) ) {
+
+        TRACE_DEBUG_WP("EndBuffer ");
+
+        // BUFF_COUNT holds the number of untransmitted bytes.
+        // BUFF_COUNT is equal to zero in case of good transfer
+        justTransferred = pTransfer->buffered
+                                 - ((status & AT91C_UDPHS_BUFF_COUNT) >> 16);
+        pTransfer->transferred += justTransferred;
+
+        pTransfer->buffered = ((status & AT91C_UDPHS_BUFF_COUNT) >> 16);
+
+        pTransfer->remaining -= justTransferred;
+
+        TRACE_DEBUG_WP("\n\r1pTransfer->buffered %d \n\r", pTransfer->buffered);
+        TRACE_DEBUG_WP("1pTransfer->transferred %d \n\r", pTransfer->transferred);
+        TRACE_DEBUG_WP("1pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+        if( (pTransfer->remaining + pTransfer->buffered) > 0 ) {
+
+            // Prepare an other transfer
+            if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+                pTransfer->buffered = DMA_MAX_FIFO_SIZE;    
+            }
+            else {
+                pTransfer->buffered = pTransfer->remaining;
+            }
+
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = 
+                (unsigned int)((pTransfer->pData) + (pTransfer->transferred));
+
+            // Clear unwanted interrupts
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+
+            // Enable DMA endpoint interrupt
+            AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+            // DMA config for receive the good size of buffer, or an error buffer
+
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
+                                     ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
+                                       | AT91C_UDPHS_END_TR_EN
+                                       | AT91C_UDPHS_END_TR_IT
+                                       | AT91C_UDPHS_END_B_EN
+                                       | AT91C_UDPHS_END_BUFFIT
+                                       | AT91C_UDPHS_CHANN_ENB );
+        }
+    }
+    else if( AT91C_UDPHS_END_TR_ST == (status & AT91C_UDPHS_END_TR_ST) ) {
+
+        TRACE_DEBUG_WP("EndTransf ");
+
+        pTransfer->transferred = pTransfer->buffered
+                                 - ((status & AT91C_UDPHS_BUFF_COUNT) >> 16);
+        pTransfer->remaining = 0;
+        TRACE_DEBUG_WP("\n\r0pTransfer->buffered %d \n\r", pTransfer->buffered);
+        TRACE_DEBUG_WP("0pTransfer->transferred %d \n\r", pTransfer->transferred);
+        TRACE_DEBUG_WP("0pTransfer->remaining %d \n\r", pTransfer->remaining);
+    }
+    else {
+
+        TRACE_ERROR("UDPHS_DmaHandler: Error (0x%08X)\n\r", status);
+        result = USBD_STATUS_ABORTED;
+    }
+
+    // Invoke callback
+    if( pTransfer->remaining == 0 ) {
+
+        TRACE_DEBUG_WP("EOT ");
+        UDPHS_EndOfTransfer(bEndpoint, result);
+    }
+}
+#endif
+
+
+//------------------------------------------------------------------------------
+//      Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USB interrupt handler
+/// Manages device resume, suspend, end of bus reset. 
+/// Forwards endpoint interrupts to the appropriate handler.
+//------------------------------------------------------------------------------
+void USBD_InterruptHandler(void)
+{
+    unsigned int  status;
+    unsigned char numIT;
+
+    if (deviceState >= USBD_STATE_POWERED) {
+
+        LED_Set(USBD_LEDUSB);
+    }
+
+    // Get interrupts status
+    status = AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_BASE_UDPHS->UDPHS_IEN;
+
+    // Handle all UDPHS interrupts
+    TRACE_DEBUG_WP("H");
+    while (status != 0) {
+
+        // Start Of Frame (SOF)
+        if ((status & AT91C_UDPHS_IEN_SOF) != 0) {
+
+            TRACE_DEBUG_WP("SOF ");
+
+            // Invoke the SOF callback
+            //USB_StartOfFrameCallback(pUsb);
+
+            // Acknowledge interrupt
+            AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_IEN_SOF;
+            status &= ~AT91C_UDPHS_IEN_SOF;
+        }
+        // Suspend
+        // This interrupt is always treated last (hence the '==')
+        else if (status == AT91C_UDPHS_DET_SUSPD) {
+
+            TRACE_DEBUG_WP("S");
+
+            // The device enters the Suspended state
+            // MCK + UDPCK must be off
+            // Pull-Up must be connected
+            // Transceiver must be disabled
+
+            LED_Clear(USBD_LEDUSB);
+
+            UDPHS_DisableBIAS();
+
+            // Enable wakeup
+            AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM;
+            AT91C_BASE_UDPHS->UDPHS_IEN &= ~AT91C_UDPHS_DET_SUSPD;
+
+            // Acknowledge interrupt
+            AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_DET_SUSPD | AT91C_UDPHS_WAKE_UP;
+            previousDeviceState = deviceState;
+            deviceState = USBD_STATE_SUSPENDED;
+            UDPHS_DisableUsbClock();
+
+            // Invoke the Suspend callback
+            USBDCallbacks_Suspended();
+        }
+        // Resume
+        else if( ((status & AT91C_UDPHS_WAKE_UP) != 0)      // line activity
+              || ((status & AT91C_UDPHS_ENDOFRSM) != 0))  { // pc wakeup
+
+//JCB
+#ifdef NOT_DEFINED
+#if !defined(PIN_USB_VBUS)
+            // Configure PIO
+            PIO_Configure(&pinVbus, 1);
+
+            // Check current level on VBus
+            if (PIO_Get(&pinVbus) == 1)    // Protection
+#endif
+#endif
+            {
+                // Invoke the Resume callback
+                USBDCallbacks_Resumed();
+
+                TRACE_DEBUG_WP("R");
+
+                UDPHS_EnableUsbClock();
+                UDPHS_EnableBIAS();
+
+                // The device enters Configured state
+                // MCK + UDPCK must be on
+                // Pull-Up must be connected
+                // Transceiver must be enabled
+
+                deviceState = previousDeviceState;
+
+                AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM | AT91C_UDPHS_DET_SUSPD;
+
+                AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_ENDOFRSM | AT91C_UDPHS_DET_SUSPD;
+                AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM;
+                AT91C_BASE_UDPHS->UDPHS_IEN &= ~AT91C_UDPHS_WAKE_UP;
+            }
+// jcb !!!
+#ifdef NOT_DEFINED
+#if !defined(PIN_USB_VBUS)
+            else {
+
+                // No VBUS
+                // Disconnect the pull-up
+                USBD_Disconnect();
+                AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP;
+            }
+#endif
+#endif
+        }
+        // End of bus reset
+        else if ((status & AT91C_UDPHS_ENDRESET) == AT91C_UDPHS_ENDRESET) {
+
+//            TRACE_DEBUG_WP("EoB ");
+
+            // The device enters the Default state
+            deviceState = USBD_STATE_DEFAULT;
+            //      MCK + UDPCK are already enabled
+            //      Pull-Up is already connected
+            //      Transceiver must be enabled
+            //      Endpoint 0 must be enabled
+
+            UDPHS_ResetEndpoints();
+            UDPHS_DisableEndpoints();
+            USBD_ConfigureEndpoint(0);
+
+            // Flush and enable the Suspend interrupt
+            AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_DET_SUSPD;
+
+            //// Enable the Start Of Frame (SOF) interrupt if needed
+            //if (pCallbacks->startOfFrame != 0)
+            //{
+            //    AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_IEN_SOF;
+            //}
+
+            // Invoke the Reset callback
+            USBDCallbacks_Reset();
+
+            // Acknowledge end of bus reset interrupt
+            AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_ENDRESET;
+
+            AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_DET_SUSPD;
+        }
+        // Handle upstream resume interrupt
+        else if (status & AT91C_UDPHS_UPSTR_RES) {
+
+            TRACE_DEBUG_WP("ExtRes ");
+
+            // - Acknowledge the IT
+            AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_UPSTR_RES;
+        }
+        // Endpoint interrupts
+        else {
+#ifndef DMA
+            // Handle endpoint interrupts
+            for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
+
+                if ((status & (1 << SHIFT_INTERUPT << numIT)) != 0) {
+
+                    UDPHS_EndpointHandler(numIT);
+                }
+            }
+#else
+            // Handle endpoint control interrupt
+            if ((status & (1 << SHIFT_INTERUPT << 0)) != 0) {
+
+                UDPHS_EndpointHandler( 0 );
+            }
+            else {
+
+                numIT = 1;
+                while((status&(0x7E<<SHIFT_DMA)) != 0) {
+
+                    // Check if endpoint has a pending interrupt
+                    if ((status & (1 << SHIFT_DMA << numIT)) != 0) {
+
+                        UDPHS_DmaHandler(numIT);
+                        status &= ~(1 << SHIFT_DMA << numIT);
+                        if (status != 0) {
+
+                            TRACE_INFO_WP("\n\r  - ");
+                        }
+                    }
+                    numIT++;
+                }
+            }
+#endif
+        }
+
+        // Retrieve new interrupt status
+        status = AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_BASE_UDPHS->UDPHS_IEN;
+
+        TRACE_DEBUG_WP("\n\r");
+        if (status != 0) {
+
+            TRACE_DEBUG_WP("  - ");
+        }
+    }
+
+    if (deviceState >= USBD_STATE_POWERED) {
+
+        LED_Clear(USBD_LEDUSB);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Configure an endpoint with the provided endpoint descriptor
+/// \param pDdescriptor Pointer to the endpoint descriptor
+//------------------------------------------------------------------------------
+void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
+{
+    Endpoint *pEndpoint;
+    unsigned char bEndpoint;
+    unsigned char bType;
+    unsigned char bEndpointDir;
+    unsigned char bSizeEpt = 0;
+
+    // NULL descriptor -> Control endpoint 0
+    if (pDescriptor == 0) {
+
+        bEndpoint = 0;
+        pEndpoint = &(endpoints[bEndpoint]);
+        bType = USBEndpointDescriptor_CONTROL;
+        bEndpointDir = 0;
+        pEndpoint->size = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0);
+        pEndpoint->bank = BOARD_USB_ENDPOINTS_BANKS(0);
+    }
+    else  {
+
+        // The endpoint number
+        bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
+        pEndpoint = &(endpoints[bEndpoint]);
+        // Transfer type: Control, Isochronous, Bulk, Interrupt
+        bType = USBEndpointDescriptor_GetType(pDescriptor);
+        // Direction, ignored for control endpoints
+        bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
+        pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
+        pEndpoint->bank = BOARD_USB_ENDPOINTS_BANKS(bEndpoint);
+    }
+
+    // Abort the current transfer is the endpoint was configured and in
+    // Write or Read state
+    if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+     || (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
+
+        UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
+    }
+    pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+    // Disable endpoint
+    AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_SHRT_PCKT
+                                                           | AT91C_UDPHS_BUSY_BANK
+                                                           | AT91C_UDPHS_NAK_OUT
+                                                           | AT91C_UDPHS_NAK_IN
+                                                           | AT91C_UDPHS_STALL_SNT
+                                                           | AT91C_UDPHS_RX_SETUP
+                                                           | AT91C_UDPHS_TX_PK_RDY
+                                                           | AT91C_UDPHS_TX_COMPLT
+                                                           | AT91C_UDPHS_RX_BK_RDY
+                                                           | AT91C_UDPHS_ERR_OVFLW
+                                                           | AT91C_UDPHS_MDATA_RX
+                                                           | AT91C_UDPHS_DATAX_RX
+                                                           | AT91C_UDPHS_NYET_DIS
+                                                           | AT91C_UDPHS_INTDIS_DMA
+                                                           | AT91C_UDPHS_AUTO_VALID
+                                                           | AT91C_UDPHS_EPT_DISABL;
+
+    // Reset Endpoint Fifos
+    AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ | AT91C_UDPHS_FRCESTALL;
+    AT91C_BASE_UDPHS->UDPHS_EPTRST = 1<<bEndpoint;
+
+    // Configure endpoint
+    if( pEndpoint->size <= 8 )  {
+        bSizeEpt = 0;
+    } 
+    else if ( pEndpoint->size <= 16 ) {
+        bSizeEpt = 1;
+    }
+    else if ( pEndpoint->size <= 32 ) {
+        bSizeEpt = 2;
+    }
+    else if ( pEndpoint->size <= 64 ) {
+        bSizeEpt = 3;
+    }
+    else if ( pEndpoint->size <= 128 ) {
+        bSizeEpt = 4;
+    }
+    else if ( pEndpoint->size <= 256 ) {
+        bSizeEpt = 5;
+    }
+    else if ( pEndpoint->size <= 512 )  {
+        bSizeEpt = 6;
+    }
+    else if ( pEndpoint->size <= 1024 ) {
+        bSizeEpt = 7;
+    } //else {
+    //  sizeEpt = 0; // control endpoint
+    //}
+
+    // Configure endpoint
+    if (bType == USBEndpointDescriptor_CONTROL) {
+
+        // Enable endpoint IT for control endpoint
+        AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<bEndpoint);
+    }
+
+
+    AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG = bSizeEpt 
+                                                        | (bEndpointDir << 3) 
+                                                        | (bType << 4) 
+                                                        | ((pEndpoint->bank) << 6);
+
+    while( (signed int)AT91C_UDPHS_EPT_MAPD != (signed int)((AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG) & AT91C_UDPHS_EPT_MAPD) ) {
+
+        // resolved by clearing the reset IT in good place
+        TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);
+        TRACE_ERROR("PB bSizeEpt: 0x%X\n\r", bSizeEpt);
+        TRACE_ERROR("PB bEndpointDir: 0x%X\n\r", bEndpointDir);
+        TRACE_ERROR("PB bType: 0x%X\n\r", bType);
+        TRACE_ERROR("PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);
+        TRACE_ERROR("PB UDPHS_EPTCFG: 0x%X\n\r", AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG);
+        for(;;);
+    }
+
+    if (bType == USBEndpointDescriptor_CONTROL) {
+
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_RX_BK_RDY 
+                                                               | AT91C_UDPHS_RX_SETUP
+                                                               | AT91C_UDPHS_EPT_ENABL;
+    }
+    else {
+#ifndef DMA
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_EPT_ENABL;
+#else
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_AUTO_VALID 
+                                                               | AT91C_UDPHS_EPT_ENABL;
+#endif
+    }
+
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through an USB endpoint (IN)
+/// Sets up the transfer descriptor, write one or two data payloads
+/// (depending on the number of FIFO banks for the endpoint) and then
+/// starts the actual transfer. The operation is complete when all
+/// the data has been sent.
+/// \param bEndpoint Index of endpoint
+/// \param *pData  Data to be written
+/// \param dLength Data length to be send
+/// \param fCallback  Callback to be call after the success command
+/// \param *pArgument Callback argument
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+char USBD_Write( unsigned char    bEndpoint,
+                 const void       *pData,
+                 unsigned int     dLength,
+                 TransferCallback fCallback,
+                 void             *pArgument )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+
+    // Return if the endpoint is not in IDLE state
+    if (pEndpoint->state != UDP_ENDPOINT_IDLE)  {
+
+        return USBD_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
+
+    // Setup the transfer descriptor
+    pTransfer->pData = (void *) pData;
+    pTransfer->remaining = dLength;
+    pTransfer->buffered = 0;
+    pTransfer->transferred = 0;
+    pTransfer->fCallback = fCallback;
+    pTransfer->pArgument = pArgument;
+
+    // Send one packet
+    pEndpoint->state = UDP_ENDPOINT_SENDING;
+
+#ifdef DMA
+    // Test if endpoint type control
+    if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)))  {
+#endif
+        // Enable endpoint IT
+        AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_TX_PK_RDY;
+
+#ifdef DMA
+    }
+    else {
+
+        if( pTransfer->remaining == 0 ) {
+            // DMA not handle ZLP
+            AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+            // Enable endpoint IT
+            AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+            AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_TX_PK_RDY;
+        }
+        else {
+            // Others endpoints (not control)
+            if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+                // Transfer the max
+                pTransfer->buffered = DMA_MAX_FIFO_SIZE;    
+            }
+            else {
+                // Transfer the good size
+                pTransfer->buffered = pTransfer->remaining;
+            }
+
+            TRACE_DEBUG_WP("\n\r_WR:%d ", pTransfer->remaining );
+            TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
+            TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );
+
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = (unsigned int)(pTransfer->pData);
+
+            // Clear unwanted interrupts
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+            // Enable DMA endpoint interrupt
+            AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+            // DMA config
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
+            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
+                                              ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
+                                                | AT91C_UDPHS_END_B_EN
+                                                | AT91C_UDPHS_END_BUFFIT
+                                                | AT91C_UDPHS_CHANN_ENB );
+        }
+    }
+#endif
+
+    return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Reads incoming data on an USB endpoint (OUT)
+/// \param bEndpoint Index of endpoint
+/// \param *pData  Data to be readen
+/// \param dLength Data length to be receive
+/// \param fCallback  Callback to be call after the success command
+/// \param *pArgument Callback argument
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+char USBD_Read( unsigned char    bEndpoint,
+                void             *pData,
+                unsigned int     dLength,
+                TransferCallback fCallback,
+                void             *pArgument )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    Transfer *pTransfer = &(pEndpoint->transfer);
+  
+    // Return if the endpoint is not in IDLE state
+    if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+        return USBD_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+    // Endpoint enters Receiving state
+    pEndpoint->state = UDP_ENDPOINT_RECEIVING;
+
+    // Set the transfer descriptor
+    pTransfer->pData = pData;
+    pTransfer->remaining = dLength;
+    pTransfer->buffered = 0;
+    pTransfer->transferred = 0;
+    pTransfer->fCallback = fCallback;
+    pTransfer->pArgument = pArgument;
+
+#ifdef DMA
+    // Test if endpoint type control
+    if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
+#endif
+        // Control endpoint
+        // Enable endpoint IT
+        AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_RX_BK_RDY;
+#ifdef DMA
+    }
+    else {
+
+        TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+        // Others endpoints (not control)
+        if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+            // Transfer the max
+            pTransfer->buffered = DMA_MAX_FIFO_SIZE;    
+        }
+        else {
+            // Transfer the good size
+            pTransfer->buffered = pTransfer->remaining;
+        }
+
+        AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = (unsigned int)(pTransfer->pData);
+
+        // Clear unwanted interrupts
+        AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+
+        // Enable DMA endpoint interrupt
+        AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+
+        TRACE_DEBUG_WP("\n\r_RR:%d ", pTransfer->remaining );
+        TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
+        TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );
+
+        // DMA config
+        AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
+        AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
+                                 ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
+                                   | AT91C_UDPHS_END_TR_EN
+                                   | AT91C_UDPHS_END_TR_IT
+                                   | AT91C_UDPHS_END_B_EN
+                                   | AT91C_UDPHS_END_BUFFIT
+                                   | AT91C_UDPHS_CHANN_ENB );
+    }
+#endif
+
+    return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Put endpoint into Halt state
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Halt( unsigned char bEndpoint )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+    // Check that endpoint is enabled and not already in Halt state
+    if( (pEndpoint->state != UDP_ENDPOINT_DISABLED)
+     && (pEndpoint->state != UDP_ENDPOINT_HALTED) ) {
+
+        TRACE_DEBUG_WP("Halt%d ", bEndpoint);
+
+        // Abort the current transfer if necessary
+        UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+
+        // Put endpoint into Halt state
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_FRCESTALL;
+        pEndpoint->state = UDP_ENDPOINT_HALTED;
+
+#ifdef DMA
+        // Test if endpoint type control
+        if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)))  {
+#endif
+            // Enable the endpoint interrupt
+            AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<bEndpoint);
+#ifdef DMA
+        }
+        else {
+            // Enable IT DMA
+            AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_DMA<<bEndpoint);
+        }
+#endif
+   }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the Halt feature on the given endpoint.
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Unhalt( unsigned char bEndpoint )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+    // Check if the endpoint is enabled
+    if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
+
+        TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
+
+        // Return endpoint to Idle state
+        pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+        // Clear FORCESTALL flag
+        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ | AT91C_UDPHS_FRCESTALL;
+
+        // Reset Endpoint Fifos
+        AT91C_BASE_UDPHS->UDPHS_EPTRST = (1<<bEndpoint);
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current Halt status of an endpoint.
+/// \param bEndpoint Index of endpoint
+/// \return 1 if the endpoint is currently halted; otherwise 0
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHalted( unsigned char bEndpoint )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+    unsigned char status = 0;
+
+    if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+        status = 1;
+    }
+    return( status );
+}
+
+//------------------------------------------------------------------------------
+/// IS High Speed device working in High Speed ?
+/// \return 1 if the device is in High Speed; otherwise 0 (Full Speed)
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHighSpeed( void )
+{
+    unsigned char status = 0;
+
+    if( AT91C_UDPHS_SPEED == (AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_UDPHS_SPEED) )
+    {
+        // High Speed
+        TRACE_DEBUG_WP("High Speed\n\r");
+        status = 1;
+    }
+    else {
+        TRACE_DEBUG_WP("Full Speed\n\r");
+    }
+    return( status );
+}
+ 
+
+//------------------------------------------------------------------------------
+/// Causes the endpoint to acknowledge the next received packet with a STALL
+/// handshake.
+/// Further packets are then handled normally.
+/// \param bEndpoint Index of endpoint
+/// \return Operation result code: USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char USBD_Stall( unsigned char bEndpoint )
+{
+    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+    // Check that endpoint is in Idle state
+    if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+        TRACE_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
+        return USBD_STATUS_LOCKED;
+    }
+
+    TRACE_DEBUG_WP("Stall%d ", bEndpoint);
+
+    AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_FRCESTALL;
+
+    return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Activates a remote wakeup procedure
+//------------------------------------------------------------------------------
+void USBD_RemoteWakeUp(void)
+{
+    TRACE_DEBUG_WP("Remote WakeUp\n\r");
+
+    // Device is currently suspended
+    if (deviceState == USBD_STATE_SUSPENDED) {
+
+        TRACE_DEBUG_WP("RW\n\r");
+        UDPHS_EnableUsbClock();
+
+        // Activates a remote wakeup
+        AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_REWAKEUP;
+
+        while ((AT91C_BASE_UDPHS->UDPHS_CTRL&AT91C_UDPHS_REWAKEUP) == AT91C_UDPHS_REWAKEUP) {
+
+            TRACE_DEBUG_WP("W");
+        }
+        UDPHS_EnableBIAS();
+    }
+    // Device is NOT suspended
+    else {
+
+        TRACE_WARNING("USBD_RemoteWakeUp: Device is not suspended\n\r");
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the device address
+/// \param address Adress to be set
+//------------------------------------------------------------------------------
+void USBD_SetAddress( unsigned char address )
+{
+    TRACE_DEBUG_WP("SetAddr(%d) ", address);
+
+    // Set address
+    AT91C_BASE_UDPHS->UDPHS_CTRL &= ~AT91C_UDPHS_DEV_ADDR; // RAZ Address
+    AT91C_BASE_UDPHS->UDPHS_CTRL |= address | AT91C_UDPHS_FADDR_EN;
+
+    // If the address is 0, the device returns to the Default state
+    if (address == 0) {
+        deviceState = USBD_STATE_DEFAULT;
+    }
+    // If the address is non-zero, the device enters the Address state
+    else {
+        deviceState = USBD_STATE_ADDRESS;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Changes the device state from Address to Configured, or from Configured 
+/// to Address.
+/// This method directly access the last received SETUP packet to decide on 
+/// what to do.
+/// \param cfgnum configuration number
+//------------------------------------------------------------------------------
+void USBD_SetConfiguration( unsigned char cfgnum )
+{
+    TRACE_DEBUG_WP("SetCfg(%d) ", cfgnum);
+
+    // Check the request
+    if( cfgnum != 0 ) {
+
+        // Enter Configured state
+        deviceState = USBD_STATE_CONFIGURED;
+    }
+    // If the configuration number is zero, the device goes back to the Address
+    // state
+    else  {
+
+        // Go back to Address state
+        deviceState = USBD_STATE_ADDRESS;
+
+        // Abort all transfers
+        UDPHS_DisableEndpoints();
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Enables the pull-up on the D+ line to connect the device to the USB.
+//------------------------------------------------------------------------------
+void USBD_Connect( void )
+{
+    TRACE_DEBUG_WP("Conn ");
+#if defined(BOARD_USB_PULLUP_INTERNAL)
+    AT91C_BASE_UDPHS->UDPHS_CTRL &= ~AT91C_UDPHS_DETACH;   // Pull Up on DP
+    AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_PULLD_DIS; // Disable Pull Down
+
+#elif defined(BOARD_USB_PULLUP_INTERNAL_BY_MATRIX)
+    TRACE_DEBUG_WP("PUON 1\n\r");
+    AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
+
+#elif defined(BOARD_USB_PULLUP_EXTERNAL)
+
+#ifdef PIN_USB_PULLUP
+    const Pin pinPullUp = PIN_USB_PULLUP;
+    if( pinPullUp.attribute == PIO_OUTPUT_0 ) {
+
+        PIO_Set(&pinPullUp);
+    }
+    else {
+
+        PIO_Clear(&pinPullUp);
+    }
+#else
+    #error unsupported now
+#endif
+
+#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
+    #error Unsupported pull-up type.
+
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disables the pull-up on the D+ line to disconnect the device from the bus.
+//------------------------------------------------------------------------------
+void USBD_Disconnect( void )
+{
+    TRACE_DEBUG_WP("Disc ");
+
+#if defined(BOARD_USB_PULLUP_INTERNAL)
+    AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_DETACH; // detach
+    AT91C_BASE_UDPHS->UDPHS_CTRL &= ~AT91C_UDPHS_PULLD_DIS; // Enable Pull Down
+
+#elif defined(BOARD_USB_PULLUP_INTERNAL_BY_MATRIX)
+    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+
+#elif defined(BOARD_USB_PULLUP_EXTERNAL)
+
+#ifdef PIN_USB_PULLUP
+    const Pin pinPullUp = PIN_USB_PULLUP;
+    if (pinPullUp.attribute == PIO_OUTPUT_0) {
+
+        PIO_Clear(&pinPullUp);
+    }
+    else {
+
+        PIO_Set(&pinPullUp);
+    }
+#else
+    #error unsupported now
+#endif
+
+#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
+    #error Unsupported pull-up type.
+
+#endif
+
+    // Device returns to the Powered state
+    if (deviceState > USBD_STATE_POWERED) {    
+
+        deviceState = USBD_STATE_POWERED;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// Certification test for High Speed device.
+/// \param bIndex Test to be done
+//------------------------------------------------------------------------------
+void USBD_Test( unsigned char bIndex )
+{
+    char          *pFifo;
+    unsigned char i;
+
+    AT91C_BASE_UDPHS->UDPHS_IEN &= ~AT91C_UDPHS_DET_SUSPD; // remove suspend for TEST
+    AT91C_BASE_UDPHS->UDPHS_TST |= AT91C_UDPHS_SPEED_CFG_HS; // force High Speed (remove suspend)
+
+    switch( bIndex ) {
+
+        case USBFeatureRequest_TESTPACKET:
+            TRACE_DEBUG_WP("TEST_PACKET ");
+
+            AT91C_BASE_UDPHS->UDPHS_DMA[1].UDPHS_DMACONTROL = 0;
+            AT91C_BASE_UDPHS->UDPHS_DMA[2].UDPHS_DMACONTROL = 0;
+
+            // Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank
+            AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTCFG = AT91C_UDPHS_EPT_SIZE_64 | AT91C_UDPHS_EPT_DIR_IN | AT91C_UDPHS_EPT_TYPE_BUL_EPT | AT91C_UDPHS_BK_NUMBER_1;
+            while( (signed int)(AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTCFG & AT91C_UDPHS_EPT_MAPD) != (signed int)AT91C_UDPHS_EPT_MAPD ) {}
+
+            AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTCTLENB =  AT91C_UDPHS_EPT_ENABL;
+
+            // Write FIFO
+            pFifo = (char*)((unsigned int *)(AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0) + (16384 * 2));
+            for( i=0; i<sizeof(test_packet_buffer); i++) {
+                pFifo[i] = test_packet_buffer[i];
+            }
+            // Tst PACKET
+            AT91C_BASE_UDPHS->UDPHS_TST |= AT91C_UDPHS_TST_PKT;
+            // Send packet
+            AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+            break;
+
+        case USBFeatureRequest_TESTJ:
+            TRACE_DEBUG_WP("TEST_J ");
+            AT91C_BASE_UDPHS->UDPHS_TST = AT91C_UDPHS_TST_J;
+            break;
+
+        case USBFeatureRequest_TESTK:
+            TRACE_DEBUG_WP("TEST_K ");
+            AT91C_BASE_UDPHS->UDPHS_TST = AT91C_UDPHS_TST_K;
+            break;
+
+        case USBFeatureRequest_TESTSE0NAK:
+            TRACE_DEBUG_WP("TEST_SEO_NAK ");
+            AT91C_BASE_UDPHS->UDPHS_IEN = 0;  // for test
+            break;
+
+        case USBFeatureRequest_TESTSENDZLP:
+            //while( 0 != (AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY ) ) {}
+            AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+            //while( 0 != (AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY ) ) {}
+            TRACE_DEBUG_WP("SEND_ZLP ");
+            break;
+    }
+    TRACE_DEBUG_WP("\n\r");
+}
+
+
+//------------------------------------------------------------------------------
+/// Initializes the specified USB driver
+/// This function initializes the current FIFO bank of endpoints,
+/// configures the pull-up and VBus lines, disconnects the pull-up and
+/// then trigger the Init callback.
+//------------------------------------------------------------------------------
+void USBD_Init( void )
+{
+    unsigned char i;
+
+    TRACE_DEBUG_WP("USBD Init()\n\r");
+
+    // Reset endpoint structures
+    UDPHS_ResetEndpoints();
+
+    // Enables the USB Clock
+    UDPHS_EnableUsbClock();
+
+    // Configure the pull-up on D+ and disconnect it
+#if defined(BOARD_USB_PULLUP_INTERNAL)
+    AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_DETACH; // detach
+    AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_PULLD_DIS; // Disable Pull Down
+
+#elif defined(BOARD_USB_PULLUP_INTERNAL_BY_MATRIX)
+    TRACE_DEBUG_WP("PUON 0\n\r");
+    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+
+#elif defined(BOARD_USB_PULLUP_EXTERNAL)
+#ifdef PIN_USB_PULLUP
+    const Pin pinPullUp = PIN_USB_PULLUP;
+    PIO_Configure(&pinPullUp, 1);
+    if (pinPullUp.attribute == PIO_OUTPUT_0) {
+
+        PIO_Clear(&pinPullUp);
+    }
+    else {
+
+        PIO_Set(&pinPullUp);
+    }
+#else
+    #error unsupported now
+#endif
+#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
+    #error Unsupported pull-up type.
+
+#endif
+
+    // Reset and enable IP UDPHS
+    AT91C_BASE_UDPHS->UDPHS_CTRL &= ~AT91C_UDPHS_EN_UDPHS;
+    AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_EN_UDPHS;
+    // Enable and disable of the transceiver is automaticaly done by the IP.
+
+    // With OR without DMA !!!
+    // Initialization of DMA
+    for( i=1; i<=((AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_DMA_CHANNEL_NBR)>>4); i++ ) {
+
+        // RESET endpoint canal DMA:
+        // DMA stop channel command
+        AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMACONTROL = 0;  // STOP command
+
+        // Disable endpoint
+        AT91C_BASE_UDPHS->UDPHS_EPT[i].UDPHS_EPTCTLDIS = AT91C_UDPHS_SHRT_PCKT
+                                                       | AT91C_UDPHS_BUSY_BANK
+                                                       | AT91C_UDPHS_NAK_OUT
+                                                       | AT91C_UDPHS_NAK_IN
+                                                       | AT91C_UDPHS_STALL_SNT
+                                                       | AT91C_UDPHS_RX_SETUP
+                                                       | AT91C_UDPHS_TX_PK_RDY
+                                                       | AT91C_UDPHS_TX_COMPLT
+                                                       | AT91C_UDPHS_RX_BK_RDY
+                                                       | AT91C_UDPHS_ERR_OVFLW
+                                                       | AT91C_UDPHS_MDATA_RX
+                                                       | AT91C_UDPHS_DATAX_RX
+                                                       | AT91C_UDPHS_NYET_DIS
+                                                       | AT91C_UDPHS_INTDIS_DMA
+                                                       | AT91C_UDPHS_AUTO_VALID
+                                                       | AT91C_UDPHS_EPT_DISABL;
+
+        // Clear status endpoint
+        AT91C_BASE_UDPHS->UDPHS_EPT[i].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ
+                                                       | AT91C_UDPHS_FRCESTALL
+                                                       | AT91C_UDPHS_RX_BK_RDY
+                                                       | AT91C_UDPHS_TX_COMPLT
+                                                       | AT91C_UDPHS_RX_SETUP
+                                                       | AT91C_UDPHS_STALL_SNT
+                                                       | AT91C_UDPHS_NAK_IN
+                                                       | AT91C_UDPHS_NAK_OUT;
+
+        // Reset endpoint config
+        AT91C_BASE_UDPHS->UDPHS_EPT[i].UDPHS_EPTCTLENB = 0;
+
+        // Reset DMA channel (Buff count and Control field)
+        AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMACONTROL = AT91C_UDPHS_LDNXT_DSC;  // NON STOP command
+
+        // Reset DMA channel 0 (STOP)
+        AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMACONTROL = 0;  // STOP command
+
+        // Clear DMA channel status (read the register for clear it)
+        AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMASTATUS = AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMASTATUS;
+
+    }
+
+    AT91C_BASE_UDPHS->UDPHS_TST = 0;
+    AT91C_BASE_UDPHS->UDPHS_IEN = 0;
+    AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_UPSTR_RES
+                                   | AT91C_UDPHS_ENDOFRSM
+                                   | AT91C_UDPHS_WAKE_UP
+                                   | AT91C_UDPHS_ENDRESET
+                                   | AT91C_UDPHS_IEN_SOF
+                                   | AT91C_UDPHS_MICRO_SOF
+                                   | AT91C_UDPHS_DET_SUSPD;
+    
+    // Device is in the Attached state
+    deviceState = USBD_STATE_SUSPENDED;
+    previousDeviceState = USBD_STATE_POWERED;
+
+    // Disable interrupts
+    AT91C_BASE_UDPHS->UDPHS_IEN = AT91C_UDPHS_ENDOFRSM
+                                | AT91C_UDPHS_WAKE_UP
+                                | AT91C_UDPHS_DET_SUSPD;
+
+    // Disable USB clocks
+    UDPHS_DisableUsbClock();
+
+    // Configure interrupts
+    USBDCallbacks_Initialized();
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current state of the USB device.
+/// \return Device current state.
+//------------------------------------------------------------------------------
+unsigned char USBD_GetState( void )
+{
+    return deviceState;
+}
+
+#endif // BOARD_USB_UDPHS
+
-- 
cgit v1.2.3