From 44174a0ae621076694049b31086a8ee8a2085156 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 25 Jun 2015 19:13:16 +0200
Subject: [PATCH] USB device refactoring (WIP)

---
 cores/arduino/USB/CDC.cpp            |  141 ++--
 cores/arduino/USB/HID.cpp            |   31 +-
 cores/arduino/USB/SAMD21_USBDevice.h |  197 +++++
 cores/arduino/USB/USBAPI.h           |  134 +--
 cores/arduino/USB/USBCore.cpp        | 1125 ++++++++++++++------------
 cores/arduino/USB/USBCore.h          |   12 +-
 cores/arduino/USB/USBDesc.h          |    2 +-
 cores/arduino/USB/USB_device.h       |   63 --
 cores/arduino/USB/USB_host.h         |    2 +-
 cores/arduino/USB/USB_interrupt.c    |   23 -
 cores/arduino/USB/samd21_device.c    |  349 --------
 cores/arduino/USB/samd21_device.h    |  108 ---
 cores/arduino/USB/samd21_host.c      |   72 +-
 cores/arduino/USB/samd21_host.h      |   24 +-
 14 files changed, 1030 insertions(+), 1253 deletions(-)
 create mode 100644 cores/arduino/USB/SAMD21_USBDevice.h
 delete mode 100644 cores/arduino/USB/USB_device.h
 delete mode 100644 cores/arduino/USB/USB_interrupt.c
 delete mode 100644 cores/arduino/USB/samd21_device.c
 delete mode 100644 cores/arduino/USB/samd21_device.h

diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp
index 33c7b7e8..c0e61a89 100644
--- a/cores/arduino/USB/CDC.cpp
+++ b/cores/arduino/USB/CDC.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -16,22 +16,13 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
+#include <Arduino.h>
+#include <Reset.h> // Needed for auto-reset with 1200bps port touch
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
 
-// Include Atmel headers
-#include "Arduino.h"
-#include "sam.h"
-#include "wiring_constants.h"
-#include "USBCore.h"
-#include "USB/USB_device.h"
-#include "USBDesc.h"
-#include "USBAPI.h"
-
-#include "Reset.h"
-
-
 #ifdef CDC_ENABLED
 
 #define CDC_SERIAL_BUFFER_SIZE	64
@@ -42,96 +33,93 @@
 
 #define CDC_LINESTATE_READY		(CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
 
-struct ring_buffer
-{
+struct ring_buffer {
 	uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
 	volatile uint32_t head;
 	volatile uint32_t tail;
 };
-
 ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
 
-typedef struct
-{
-	uint32_t	dwDTERate;
-	uint8_t		bCharFormat;
-	uint8_t 	bParityType;
-	uint8_t 	bDataBits;
-	uint8_t		lineState;
+typedef struct {
+	uint32_t dwDTERate;
+	uint8_t bCharFormat;
+	uint8_t bParityType;
+	uint8_t bDataBits;
+	uint8_t lineState;
 } LineInfo;
 
 _Pragma("pack(1)")
 static volatile LineInfo _usbLineInfo = {
-   115200, // dWDTERate
-    0x00,  // bCharFormat
-    0x00,  // bParityType
-    0x08,  // bDataBits
-    0x00   // lineState
+	115200, // dWDTERate
+	0x00,   // bCharFormat
+	0x00,   // bParityType
+	0x08,   // bDataBits
+	0x00    // lineState
 };
 
-static const CDCDescriptor _cdcInterface =
-{
-#if (defined CDC_ENABLED) && defined(HID_ENABLED)
+static const CDCDescriptor _cdcInterface = {
+	#if (defined CDC_ENABLED) && defined(HID_ENABLED)
 	D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
-#endif
-	//	CDC communication interface
-	D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
-	D_CDCCS( CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF ),	// Header (1.10 bcd)
-
-	D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6),				// SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
-	D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE),	// Communication interface is master, data interface is slave 0
-	D_CDCCS(CDC_CALL_MANAGEMENT,1,1),							// Device handles call management (not)
-	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10, 0x10),
-
-	//	CDC data interface
-	D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
-	D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,EPX_SIZE,0),
-	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,EPX_SIZE,0)
+	#endif
+
+	// CDC communication interface
+	D_INTERFACE(CDC_ACM_INTERFACE, 1, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
+	D_CDCCS(CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF), // Header (1.10 bcd)
+
+	D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT, 6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
+	D_CDCCS(CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
+	D_CDCCS(CDC_CALL_MANAGEMENT, 1, 1), // Device handles call management (not)
+	D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10),
+
+	// CDC data interface
+	D_INTERFACE(CDC_DATA_INTERFACE, 2, CDC_DATA_INTERFACE_CLASS, 0, 0),
+	D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0),
+	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0)
 };
 _Pragma("pack()")
 
-const void* WEAK CDC_GetInterface(void)
+const void* CDC_GetInterface(void)
 {
-	return  &_cdcInterface;
+	return &_cdcInterface;
 }
 
-uint32_t WEAK CDC_GetInterfaceLength(void)
+uint32_t CDC_GetInterfaceLength(void)
 {
-    return sizeof( _cdcInterface );
+	return sizeof(_cdcInterface);
 }
 
-bool WEAK CDC_Setup(Setup& setup)
+bool CDC_Setup(Setup& setup)
 {
-	uint8_t r = setup.bRequest;
 	uint8_t requestType = setup.bmRequestType;
+	uint8_t r = setup.bRequest;
 
-	if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
+	if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
 	{
-		if (CDC_GET_LINE_CODING == r)
+		if (r == CDC_GET_LINE_CODING)
 		{
-			USBD_SendControl(0,(void*)&_usbLineInfo,7);
+			USBDevice.sendControl((void*)&_usbLineInfo, 7);
 			return true;
 		}
 	}
 
-	if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
+	if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
 	{
-		if (CDC_SET_LINE_CODING == r)
+		if (r == CDC_SET_LINE_CODING)
 		{
-			USBD_RecvControl((void*)&_usbLineInfo,7);
+			USBDevice.recvControl((void*)&_usbLineInfo, 7);
 		}
 
-		if (CDC_SET_CONTROL_LINE_STATE == r)
+		if (r == CDC_SET_CONTROL_LINE_STATE)
 		{
 			_usbLineInfo.lineState = setup.wValueL;
 		}
 
-		if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r)
+		if (r == CDC_SET_LINE_CODING || r == CDC_SET_CONTROL_LINE_STATE)
 		{
 			// auto-reset into the bootloader is triggered when the port, already
 			// open at 1200 bps, is closed. We check DTR state to determine if host 
 			// port is open (bit 0 of lineState).
-			if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
+			if (_usbLineInfo.dwDTERate == 1200 && (_usbLineInfo.lineState & 0x01) == 0)
 			{
 				initiateReset(250);
 			}
@@ -161,7 +149,7 @@ void Serial_::end(void)
 void Serial_::accept(void)
 {
 	uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
-	uint32_t len = USBD_Recv(CDC_ENDPOINT_OUT, (void*)&buffer, CDC_SERIAL_BUFFER_SIZE);
+	uint32_t len = usb.recv(CDC_ENDPOINT_OUT, &buffer, CDC_SERIAL_BUFFER_SIZE);
 
 	noInterrupts();
 	ring_buffer *ringBuffer = &cdc_rx_buffer;
@@ -173,7 +161,7 @@ void Serial_::accept(void)
 	// and so we don't write the character or advance the head.
 	uint32_t k = 0;
 	i = (i + 1) % CDC_SERIAL_BUFFER_SIZE;
-	while (i != ringBuffer->tail && len>0) {
+	while ((i != ringBuffer->tail) && (len > 0)) {
 		len--;
 		ringBuffer->buffer[ringBuffer->head] = buffer[k++];
 		ringBuffer->head = i;
@@ -185,6 +173,9 @@ void Serial_::accept(void)
 int Serial_::available(void)
 {
 	ring_buffer *buffer = &cdc_rx_buffer;
+	if (buffer->head == buffer->tail) {
+		USB->DEVICE.DeviceEndpoint[2].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1);
+	}
 	return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE;
 }
 
@@ -202,12 +193,22 @@ int Serial_::peek(void)
 	}
 }
 
+
+// if the ringBuffer is empty: try to fill it
+// if it's still empty: return -1
+// else return the last char
+// so the buffer is filled only when needed
 int Serial_::read(void)
 {
 	ring_buffer *buffer = &cdc_rx_buffer;
 
 	// if the head isn't ahead of the tail, we don't have any characters
 	if (buffer->head == buffer->tail)
+	{
+		if (usb.available(CDC_ENDPOINT_OUT))
+			accept();
+	}
+	if (buffer->head == buffer->tail)
 	{
 		return -1;
 	}
@@ -215,15 +216,15 @@ int Serial_::read(void)
 	{
 		unsigned char c = buffer->buffer[buffer->tail];
 		buffer->tail = (uint32_t)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
-		if (USBD_Available(CDC_ENDPOINT_OUT))
-			accept();
+// 		if (usb.available(CDC_ENDPOINT_OUT))
+// 			accept();
 		return c;
 	}
 }
 
 void Serial_::flush(void)
 {
-	USBD_Flush(CDC_ENDPOINT_IN);
+	usb.flush(CDC_ENDPOINT_IN);
 }
 
 size_t Serial_::write(const uint8_t *buffer, size_t size)
@@ -239,13 +240,11 @@ size_t Serial_::write(const uint8_t *buffer, size_t size)
 	// or locks up, or host virtual serial port hangs)
 //	if (_usbLineInfo.lineState > 0)  // Problem with Windows(R)
 	{
-		uint32_t r = USBD_Send(CDC_ENDPOINT_IN, buffer, size);
+		uint32_t r = usb.send(CDC_ENDPOINT_IN, buffer, size);
 
-		if (r > 0)
-		{
+		if (r > 0) {
 			return r;
-		} else
-		{
+		} else {
 			setWriteError();
 			return 0;
 		}
@@ -282,6 +281,6 @@ Serial_::operator bool()
 	return result;
 }
 
-Serial_ SerialUSB;
+Serial_ SerialUSB(USBDevice);
 
 #endif
diff --git a/cores/arduino/USB/HID.cpp b/cores/arduino/USB/HID.cpp
index f5d561e0..45208b2d 100644
--- a/cores/arduino/USB/HID.cpp
+++ b/cores/arduino/USB/HID.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -16,13 +16,7 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#include "USBAPI.h"
-#include "Reset.h"
-#include "USBCore.h"
-#include "USBDesc.h"
-#include "sam.h"
-#include "USB/USB_device.h"
-
+#include <Arduino.h>
 
 #ifdef HID_ENABLED
 
@@ -143,14 +137,12 @@ _Pragma("pack()")
 uint8_t _hid_protocol = 1;
 uint8_t _hid_idle = 1;
 
-#define WEAK __attribute__ ((weak))
-
-const void* WEAK HID_GetInterface(void)
+const void* HID_GetInterface(void)
 {
 	return  &_hidInterface;
 }
 
-uint32_t WEAK HID_GetInterfaceLength(void)
+uint32_t HID_GetInterfaceLength(void)
 {
     return sizeof( _hidInterface );
 }
@@ -160,12 +152,12 @@ uint32_t HID_SizeReportDescriptor(void)
 	return sizeof(_hidReportDescriptor);
 }
 
-uint32_t WEAK HID_GetDescriptor(void)
+uint32_t HID_GetDescriptor(void)
 {
-	return USBD_SendControl(0,_hidReportDescriptor,sizeof(_hidReportDescriptor));
+	return USBDevice.sendControl(_hidReportDescriptor, sizeof(_hidReportDescriptor));
 }
 
-void WEAK HID_SendReport(uint8_t id, const void* data, uint32_t len)
+void HID_SendReport(uint8_t id, const void* data, uint32_t len)
 {
 	uint8_t p[8];
 	const uint8_t *d = reinterpret_cast<const uint8_t *>(data);
@@ -175,10 +167,10 @@ void WEAK HID_SendReport(uint8_t id, const void* data, uint32_t len)
 	{
 		p[i+1] = d[i];
 	}
-	USBD_Send(HID_ENDPOINT_INT, p, len+1);
+	USBDevice.send(HID_ENDPOINT_INT, p, len+1);
 }
 
-bool WEAK HID_Setup(Setup& setup)
+bool HID_Setup(Setup& setup)
 {
 	uint8_t r = setup.bRequest;
 	uint8_t requestType = setup.bmRequestType;
@@ -197,8 +189,9 @@ bool WEAK HID_Setup(Setup& setup)
 		}
 		if (HID_GET_IDLE == r)
 		{
-			UDD_Send(0, &_hid_idle, 1);
-			UDD_ClearIN();
+			USBDevice.armSend(0, &_hid_idle, 1);
+			// RAM buffer is full, we can send data (IN)
+			USB->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = 1;
 			return true;
 		}
 	}
diff --git a/cores/arduino/USB/SAMD21_USBDevice.h b/cores/arduino/USB/SAMD21_USBDevice.h
new file mode 100644
index 00000000..203a1c78
--- /dev/null
+++ b/cores/arduino/USB/SAMD21_USBDevice.h
@@ -0,0 +1,197 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#pragma once
+
+#include <Arduino.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+typedef uint8_t ep_t;
+
+class USBDevice_SAMD21G18x {
+public:
+	USBDevice_SAMD21G18x() : usb(USB->DEVICE) {
+		// Empty
+	}
+
+	// USB Device function mapping
+	// ---------------------------
+
+	// Reset USB Device
+	void reset();
+
+	// Enable
+	inline void enable()  { usb.CTRLA.bit.ENABLE = 1; }
+	inline void disable() { usb.CTRLA.bit.ENABLE = 0; }
+
+	// USB mode (device/host)
+	inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; }
+	inline void setUSBHostMode()   { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_HOST_Val;   }
+
+	inline void runInStandby()   { usb.CTRLA.bit.RUNSTDBY = 1; }
+	inline void noRunInStandby() { usb.CTRLA.bit.RUNSTDBY = 0; }
+
+	// USB speed
+	inline void setFullSpeed()       { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;   }
+	inline void setLowSpeed()        { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val;   }
+	inline void setHiSpeed()         { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HS_Val;   }
+	inline void setHiSpeedTestMode() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HSTM_Val; }
+
+	// Authorize attach if Vbus is present
+	inline void attach() { usb.CTRLB.bit.DETACH = 0; }
+	inline void detach() { usb.CTRLB.bit.DETACH = 1; }
+
+	// USB Interrupts
+	inline bool isEndOfResetInterrupt()        { return usb.INTFLAG.bit.EORST; }
+	inline void ackEndOfResetInterrupt()       { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; }
+	inline void enableEndOfResetInterrupt()    { usb.INTENSET.bit.EORST = 1; } 
+	inline void disableEndOfResetInterrupt()   { usb.INTENCLR.bit.EORST = 1; } 
+
+	inline bool isStartOfFrameInterrupt()      { return usb.INTFLAG.bit.SOF; }
+	inline void ackStartOfFrameInterrupt()     { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; }
+	inline void enableStartOfFrameInterrupt()  { usb.INTENSET.bit.SOF = 1; }
+	inline void disableStartOfFrameInterrupt() { usb.INTENCLR.bit.SOF = 1; }
+
+	// USB Address
+	inline void setAddress(uint32_t addr)   { usb.DADD.bit.DADD = addr; usb.DADD.bit.ADDEN = 1; }
+	inline void unsetAddress()              { usb.DADD.bit.DADD = 0;    usb.DADD.bit.ADDEN = 0; }
+
+	// Frame number
+	inline uint16_t frameNumber() { return usb.FNUM.bit.FNUM; }
+
+	// Load calibration values
+	void calibrate();
+
+	// USB Device Endpoints function mapping
+	// -------------------------------------
+
+	// Config
+	inline void epBank0SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE0 = type; }
+	inline void epBank1SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE1 = type; }
+
+	// Interrupts
+	inline uint16_t epInterruptSummary() { return usb.EPINTSMRY.reg; }
+
+	inline bool epBank0IsSetupReceived(ep_t ep)     { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.RXSTP; }
+	inline bool epBank0IsStalled(ep_t ep)           { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL & 1; }
+	inline bool epBank1IsStalled(ep_t ep)           { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL & 2; }
+	inline bool epBank0IsTransferComplete(ep_t ep)  { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT & 1; }
+	inline bool epBank1IsTransferComplete(ep_t ep)  { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT & 2; }
+
+	inline void epBank0AckSetupReceived(ep_t ep)    { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; }
+	inline void epBank0AckStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(1); }
+	inline void epBank1AckStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2); }
+	inline void epBank0AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(1); }
+	inline void epBank1AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(2); }
+
+	inline void epBank0EnableSetupReceived(ep_t ep)    { usb.DeviceEndpoint[ep].EPINTENSET.bit.RXSTP = 1; }
+	inline void epBank0EnableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL = 1; }
+	inline void epBank1EnableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL = 2; }
+	inline void epBank0EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT = 1; }
+	inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT = 2; }
+
+	inline void epBank0DisableSetupReceived(ep_t ep)    { usb.DeviceEndpoint[ep].EPINTENCLR.bit.RXSTP = 1; }
+	inline void epBank0DisableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL = 1; }
+	inline void epBank1DisableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL = 2; }
+	inline void epBank0DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT = 1; }
+	inline void epBank1DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT = 2; }
+
+	// Status
+	inline bool epBank0IsReady(ep_t ep)    { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK0RDY; }
+	inline bool epBank1IsReady(ep_t ep)    { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK1RDY; }
+	inline void epBank0SetReady(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK0RDY = 1; }
+	inline void epBank1SetReady(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK1RDY = 1; }
+	inline void epBank0ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK0RDY = 1; }
+	inline void epBank1ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK1RDY = 1; }
+
+	inline void epBank0SetStallReq(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ = 1; }
+	inline void epBank1SetStallReq(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ = 2; }
+	inline void epBank0ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ = 1; }
+	inline void epBank1ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ = 2; }
+
+	// Packet
+	inline uint16_t epBank0ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT; }
+	inline uint16_t epBank1ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT; }
+	inline void epBank0SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = bc; }
+	inline void epBank1SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = bc; }
+	inline void epBank0SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = s; }
+	inline void epBank1SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = s; }
+
+	inline void epBank0SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)addr; }
+	inline void epBank1SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)addr; }
+	inline void epBank0SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); }
+	inline void epBank1SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); }
+	inline uint8_t EP_PCKSIZE_SIZE(uint16_t size) {
+		switch (size) {
+		case 8:    return 0;
+		case 16:   return 1;
+		case 32:   return 2;
+		case 64:   return 3;
+		case 128:  return 4;
+		case 256:  return 5;
+		case 512:  return 6;
+		case 1023: return 7;
+		default:   return 0;
+		}
+	}
+
+	inline void epBank0DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 0; }
+	inline void epBank1DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 0; }
+	inline void epBank0EnableAutoZLP(ep_t ep)  { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 1; }
+	inline void epBank1EnableAutoZLP(ep_t ep)  { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 1; }
+
+private:
+	// USB Device registers
+	UsbDevice &usb;
+
+	// Endpoints descriptors table
+	__attribute__((__aligned__(4)))	UsbDeviceDescriptor EP[USB_EPT_NUM];
+};
+
+void USBDevice_SAMD21G18x::reset() {
+	usb.CTRLA.bit.SWRST = 1;
+	memset(EP, 0, sizeof(EP));
+	while (usb.SYNCBUSY.bit.SWRST) {}
+	usb.DESCADD.reg = (uint32_t)(&EP);
+}
+
+void USBDevice_SAMD21G18x::calibrate() {
+	// Load Pad Calibration data from non-volatile memory
+	uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR;
+	uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR;
+	uint32_t *pad_trim_p   = (uint32_t *) USB_FUSES_TRIM_ADDR;
+
+	uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
+	uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
+	uint32_t pad_trim   = (*pad_trim_p   & USB_FUSES_TRIM_Msk  ) >> USB_FUSES_TRIM_Pos;
+
+	if (pad_transn == 0x1F)  // maximum value (31)
+		pad_transn = 5;
+	if (pad_transp == 0x1F)  // maximum value (31)
+		pad_transp = 29;
+	if (pad_trim == 0x7)     // maximum value (7)
+		pad_trim = 3;
+
+	usb.PADCAL.bit.TRANSN = pad_transn;
+	usb.PADCAL.bit.TRANSP = pad_transp;
+	usb.PADCAL.bit.TRIM   = pad_trim;
+}
+
diff --git a/cores/arduino/USB/USBAPI.h b/cores/arduino/USB/USBAPI.h
index 1229c3b7..b2d9d510 100644
--- a/cores/arduino/USB/USBAPI.h
+++ b/cores/arduino/USB/USBAPI.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -16,8 +16,7 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#ifndef __USBAPI__
-#define __USBAPI__
+#pragma once
 
 #define HSTPIPCFG_PTYPE_BLK 1
 #define HSTPIPCFG_PTOKEN_IN 2
@@ -25,17 +24,8 @@
 #define HSTPIPCFG_PBK_1_BANK 4
 #define HSTPIPCFG_PTYPE_INTRPT 5
 
-
-
-/* Define attribute */
-#if defined   ( __CC_ARM   ) /* Keil uVision 4 */
-    #define WEAK (__attribute__ ((weak)))
-#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
-    #define WEAK __weak
-#elif defined (  __GNUC__  ) /* GCC CS */
-    #define WEAK __attribute__ ((weak))
-#endif
-
+#define EP0      0
+#define EPX_SIZE 64 // 64 for Full Speed, EPT size max is 1024
 
 #if defined __cplusplus
 
@@ -43,31 +33,81 @@
 #include "RingBuffer.h"
 
 //================================================================================
-//================================================================================
-//	USB
+// USB
 
-class USBDevice_
-{
+// Low level API
+typedef struct {
+	union {
+		uint8_t bmRequestType;
+		struct {
+			uint8_t direction : 5;
+			uint8_t type : 2;
+			uint8_t transferDirection : 1;
+		};
+	};
+	uint8_t bRequest;
+	uint8_t wValueL;
+	uint8_t wValueH;
+	uint16_t wIndex;
+	uint16_t wLength;
+} Setup;
+
+class USBDeviceClass {
 public:
-	USBDevice_();
-	bool configured();
+	USBDeviceClass() {};
 
-	bool attach();
-	bool detach();	// Serial port goes down too...
-	void poll();
+	// USB Device API
 	void init();
+	bool attach();
+	bool detach();
+	void setAddress(uint32_t addr);
+
+	bool configured();
+	bool connected();
+
+	// Setup API
+	bool handleClassInterfaceSetup(Setup &setup);
+	bool handleStandardSetup(Setup &setup);
+	bool sendDescriptor(Setup &setup);
+
+	// Control EndPoint API
+	uint32_t sendControl(const void *data, uint32_t len);
+	uint32_t recvControl(void *data, uint32_t len);
+	bool sendConfiguration(uint32_t maxlen);
+	bool sendStringDescriptor(const uint8_t *string, uint8_t maxlen);
+
+	// Generic EndPoint API
+	void initEP(uint32_t ep, uint32_t type);
+	void handleEndpoint(uint8_t ep);
+
+	uint32_t send(uint32_t ep, const void *data, uint32_t len);
+	void sendZlp(uint32_t ep);
+	uint32_t recv(uint32_t ep, void *data, uint32_t len);
+	uint32_t recv(uint32_t ep);
+	uint32_t available(uint32_t ep);
+	void flush(uint32_t ep);
+	void stall(uint32_t ep);
+
+	// private?
+	uint32_t armSend(uint32_t ep, const void *data, uint32_t len);
+	uint8_t armRecv(uint32_t ep, uint32_t len);
+	uint8_t armRecvCtrlOUT(uint32_t ep, uint32_t len);
+
+	void ISRHandler();
+
+private:
+	bool initialized;
 };
-extern USBDevice_ USBDevice;
 
-//================================================================================
+extern USBDeviceClass USBDevice;
+
 //================================================================================
 //	Serial over CDC (Serial1 is the physical port)
 
 class Serial_ : public Stream
 {
-private:
-	RingBuffer *_cdc_rx_buffer;
 public:
+	Serial_(USBDeviceClass &_usb) : usb(_usb) { }
 	void begin(uint32_t baud_count);
 	void begin(unsigned long, uint8_t);
 	void end(void);
@@ -81,6 +121,9 @@ public:
 	virtual size_t write(const uint8_t *buffer, size_t size);
 	using Print::write; // pull in write(str) from Print
 	operator bool();
+private:
+	USBDeviceClass &usb;
+	RingBuffer *_cdc_rx_buffer;
 };
 extern Serial_ SerialUSB;
 
@@ -175,26 +218,12 @@ public:
 };
 extern Keyboard_ Keyboard;
 
-//================================================================================
-//================================================================================
-//	Low level API
-
-typedef struct
-{
-	uint8_t bmRequestType;
-	uint8_t bRequest;
-	uint8_t wValueL;
-	uint8_t wValueH;
-	uint16_t wIndex;
-	uint16_t wLength;
-} Setup;
-
 //================================================================================
 //================================================================================
 //	HID 'Driver'
 
-const void* WEAK HID_GetInterface(void);
-uint32_t WEAK HID_GetInterfaceLength(void);
+const void* HID_GetInterface(void);
+uint32_t HID_GetInterfaceLength(void);
 uint32_t HID_SizeReportDescriptor(void);
 
 uint32_t		HID_GetDescriptor(void);
@@ -215,26 +244,9 @@ bool	MSC_Data(uint8_t rx,uint8_t tx);
 //	CDC 'Driver'
 
 const void* CDC_GetInterface(/*uint8_t* interfaceNum*/);
-uint32_t WEAK CDC_GetInterfaceLength(void);
+uint32_t CDC_GetInterfaceLength(void);
 uint32_t		CDC_GetOtherInterface(uint8_t* interfaceNum);
 uint32_t		CDC_GetDescriptor(uint32_t i);
 bool	CDC_Setup(Setup& setup);
 
-//================================================================================
-//================================================================================
-
-uint32_t USBD_SendControl(uint8_t flags, const void* d, uint32_t len);
-uint32_t USBD_RecvControl(void* d, uint32_t len);
-uint32_t USBD_SendInterfaces(void);
-bool USBD_ClassInterfaceRequest(Setup& setup);
-
-uint32_t USBD_Available(uint32_t ep);
-uint32_t USBD_SendSpace(uint32_t ep);
-uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len);
-uint32_t USBD_Recv(uint32_t ep, void* data, uint32_t len);		// non-blocking
-uint32_t USBD_Recv(uint32_t ep);							// non-blocking
-void USBD_Flush(uint32_t ep);
-uint32_t USBD_Connected(void);
-
 #endif  // __cplusplus
-#endif  // __USBAPI__
diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp
index 31b8380a..cfcf101a 100644
--- a/cores/arduino/USB/USBCore.cpp
+++ b/cores/arduino/USB/USBCore.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -16,14 +16,15 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#include "../Arduino.h"
-#include "USBCore.h"
-#include "USB/USB_device.h"   // needed for USB PID define
-#include "USBDesc.h"
-#include "USBAPI.h"
+#include <Arduino.h>
 
-//#define TRACE_CORE(x)	x
-#define TRACE_CORE(x)
+#include "SAMD21_USBDevice.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+USBDevice_SAMD21G18x usbd;
 
 static char isRemoteWakeUpEnabled = 0;
 static char isEndpointHalt = 0;
@@ -50,184 +51,56 @@ const uint8_t STRING_PRODUCT[] = USB_PRODUCT;
 #  define USB_MANUFACTURER "Unknown"
 #endif
 
-const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER;
+const uint8_t STRING_MANUFACTURER[] = USB_MANUFACTURER;
 
 
 //	DEVICE DESCRIPTOR
 #if (defined CDC_ENABLED) && defined(HID_ENABLED)
-const DeviceDescriptor USB_DeviceDescriptor =
-	D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
 #elif defined(CDC_ENABLED)  // CDC only
-const DeviceDescriptor USB_DeviceDescriptor =
-	D_DEVICE(0x02,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x02, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
 #else // HID only
-const DeviceDescriptor USB_DeviceDescriptor =
-	D_DEVICE(0,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
 #endif
 
 //==================================================================
 
 volatile uint32_t _usbConfiguration = 0;
-volatile uint32_t _usbInitialized = 0;
 volatile uint32_t _usbSetInterface = 0;
 
-//==================================================================
-
-
-//	Number of bytes, assumes a rx endpoint
-uint32_t USBD_Available(uint32_t ep)
-{
-	return UDD_FifoByteCount(ep);
-}
-
-//	Non Blocking receive
-//	Return number of bytes read
-uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len)
-{
-	if (!_usbConfiguration)
-		return -1;
-
-	uint8_t *buffer;
-	uint8_t *data = (uint8_t *)d;
-
-	len = min(UDD_FifoByteCount(ep), len);
-
-	UDD_Recv_data(ep, len);
-	UDD_Recv(ep, &buffer);
-	for (uint32_t i=0; i<len; i++) {
-		data[i] = buffer[i];
-	}
-
-	if (len && !UDD_FifoByteCount(ep)) // release empty buffer
-		UDD_ReleaseRX(ep);
-
-	return len;
-}
+static __attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/
+uint8_t udd_ep_out_cache_buffer[4][64];
 
-//	Recv 1 byte if ready
-uint32_t USBD_Recv(uint32_t ep)
-{
-	uint8_t c;
-	if (USBD_Recv(ep, &c, 1) != 1)
-		return -1;
-	else
-		return c;
-}
+static __attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/
+uint8_t udd_ep_in_cache_buffer[4][128];
 
-//	Blocking Send of data to an endpoint
-uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len)
-{
-	int r = len;
-	const uint8_t* data = (const uint8_t*)d;
-
-    if (!_usbConfiguration)
-    {
-    	TRACE_CORE(printf("pb conf\n\r");)
-		return -1;
-    }
-	UDD_Send(ep, data, len);
-
-	/* Clear the transfer complete flag  */
-	udd_clear_IN_transf_cplt(ep);
-	/* Set the bank as ready */
-	udd_IN_transfer_allowed(ep);
-
-	/* Wait for transfer to complete */
-	while (! udd_is_IN_transf_cplt(ep));  // need fire exit.
-	return r;
-}
-
-uint32_t USBD_SendControl(uint8_t flags, const void* d, uint32_t len)
-{
-	const uint8_t* data = (const uint8_t*)d;
-	uint32_t length = len;
-	uint32_t sent = 0;
-	uint32_t pos = 0;
-
-	TRACE_CORE(printf("=> USBD_SendControl TOTAL len=%lu\r\n", len);)
-
- 		while (len > 0)
- 		{
-			sent = UDD_Send(EP0, data + pos, len);
-			TRACE_CORE(printf("=> USBD_SendControl sent=%lu\r\n", sent);)
-			pos += sent;
-			len -= sent;
- 		}
-
-	return length;
-}
+//==================================================================
 
 // Send a USB descriptor string. The string is stored as a
 // plain ASCII string but is sent out as UTF-16 with the
 // correct 2-byte prefix
-static bool USB_SendStringDescriptor(const uint8_t *string, int wLength)
+bool USBDeviceClass::sendStringDescriptor(const uint8_t *string, uint8_t maxlen)
 {
-	uint16_t buff[64];
+	if (maxlen < 2)
+		return false;
+
+	uint16_t buff[maxlen/2];
 	int l = 1;
 
-	wLength -= 2;
-	while (*string && wLength>0)
+	maxlen -= 2;
+	while (*string && maxlen>0)
 	{
 		buff[l++] = (uint8_t)(*string++);
-		wLength -= 2;
+		maxlen -= 2;
 	}
 	buff[0] = (3<<8) | (l*2);
 
-	return USBD_SendControl(0, (uint8_t*)buff, l*2);
+	return USBDevice.sendControl((uint8_t*)buff, l*2);
 }
 
-uint32_t USBD_RecvControl(void* d, uint32_t len)
-{
-	uint8_t *buffer;
-	uint8_t *data = (uint8_t *)d;
-	uint32_t read = UDD_Recv_data(EP0, len);
-	if (read > len)
-		read = len;
-	UDD_Recv(EP0, &buffer);
-	while (!udd_is_OUT_transf_cplt(EP0));
-	for (uint32_t i=0; i<read; i++) {
-		data[i] = buffer[i];
-	}
-	udd_OUT_transfer_allowed(EP0);
-	return read;
-}
-
-//	Handle CLASS_INTERFACE requests
-bool USBD_ClassInterfaceRequest(Setup& setup)
-{
-	uint8_t i = setup.wIndex;
-
-	TRACE_CORE(printf("=> USBD_ClassInterfaceRequest\r\n");)
-
-#ifdef CDC_ENABLED
-	if (CDC_ACM_INTERFACE == i)
-	{
-		if( CDC_Setup(setup) == false )
-		{
-			send_zlp();
-		}
-		return true;
-	}
-#endif
-
-#ifdef HID_ENABLED
-	if (HID_INTERFACE == i)
-	{
-		if( HID_Setup(setup) == true )
-		{
-			send_zlp();
-		}
-		return true;
-	}
-#endif
-
-	return false;
-}
-
-//	Construct a dynamic configuration descriptor
-//	This really needs dynamic endpoint allocation etc
-//	TODO
-static bool USBD_SendConfiguration(uint32_t maxlen)
+// Construct a dynamic configuration descriptor
+// This really needs dynamic endpoint allocation etc
+bool USBDeviceClass::sendConfiguration(uint32_t maxlen)
 {
 	uint8_t cache_buffer[128];
 	uint8_t i;
@@ -238,494 +111,728 @@ static bool USBD_SendConfiguration(uint32_t maxlen)
 
 	num_interfaces[0] = 0;
 
-#if (defined CDC_ENABLED) && defined(HID_ENABLED)
-    num_interfaces[0] += 3;
-    interfaces = (const uint8_t*) CDC_GetInterface();
-    interfaces_length = CDC_GetInterfaceLength() + HID_GetInterfaceLength();
-    if( maxlen > CDC_GetInterfaceLength() + HID_GetInterfaceLength() + sizeof(ConfigDescriptor) )
-    {
-	    maxlen = CDC_GetInterfaceLength() + HID_GetInterfaceLength() + sizeof(ConfigDescriptor);
-    }
-
-#else
-#ifdef CDC_ENABLED
-    num_interfaces[0] += 2;
+#if defined(CDC_ENABLED) && defined(HID_ENABLED)
+	num_interfaces[0] += 3;
+	interfaces = (const uint8_t*) CDC_GetInterface();
+	interfaces_length = CDC_GetInterfaceLength() + HID_GetInterfaceLength();
+	if (maxlen > CDC_GetInterfaceLength() + HID_GetInterfaceLength() + sizeof(ConfigDescriptor))
+	{
+		maxlen = CDC_GetInterfaceLength() + HID_GetInterfaceLength() + sizeof(ConfigDescriptor);
+	}
+#elif defined(CDC_ENABLED)
+	num_interfaces[0] += 2;
 	interfaces = (const uint8_t*) CDC_GetInterface();
 	interfaces_length += CDC_GetInterfaceLength();
-	if( maxlen > CDC_GetInterfaceLength()+ sizeof(ConfigDescriptor) )
+	if (maxlen > CDC_GetInterfaceLength() + sizeof(ConfigDescriptor))
 	{
-		maxlen = CDC_GetInterfaceLength()+ sizeof(ConfigDescriptor);
+		maxlen = CDC_GetInterfaceLength() + sizeof(ConfigDescriptor);
 	}
-#endif
-
-#ifdef HID_ENABLED
-    num_interfaces[0] += 1;
+#elif defined(HID_ENABLED)
+	num_interfaces[0] += 1;
 	interfaces = (const uint8_t*) HID_GetInterface();
 	interfaces_length += HID_GetInterfaceLength();
-	if( maxlen > HID_GetInterfaceLength()+ sizeof(ConfigDescriptor) )
+	if (maxlen > HID_GetInterfaceLength() + sizeof(ConfigDescriptor))
 	{
-		maxlen = HID_GetInterfaceLength()+ sizeof(ConfigDescriptor);
+		maxlen = HID_GetInterfaceLength() + sizeof(ConfigDescriptor);
 	}
 #endif
-#endif
 
 _Pragma("pack(1)")
-	ConfigDescriptor config = D_CONFIG((uint16_t)(interfaces_length + sizeof(ConfigDescriptor)),num_interfaces[0]);
+	ConfigDescriptor config = D_CONFIG((uint16_t)(interfaces_length + sizeof(ConfigDescriptor)), num_interfaces[0]);
 _Pragma("pack()")
 
-	memcpy( cache_buffer, &config, sizeof(ConfigDescriptor) );
+	memcpy(cache_buffer, &config, sizeof(ConfigDescriptor));
 
-#if (defined CDC_ENABLED) && defined(HID_ENABLED)
-	for ( i=0; i<CDC_GetInterfaceLength(); i++)
-	{
-		cache_buffer[i+sizeof(ConfigDescriptor)] = interfaces[i];
+#if defined(CDC_ENABLED) && defined(HID_ENABLED)
+	for (i=0; i<CDC_GetInterfaceLength(); i++) {
+		cache_buffer[i + sizeof(ConfigDescriptor)] = interfaces[i];
 	}
 	interfaces = (const uint8_t*) HID_GetInterface();
-	for ( i=0; i<HID_GetInterfaceLength(); i++)
-	{
-		cache_buffer[i+sizeof(ConfigDescriptor)+CDC_GetInterfaceLength()] = interfaces[i];
+	for (i=0; i<HID_GetInterfaceLength(); i++) {
+		cache_buffer[i + sizeof(ConfigDescriptor) + CDC_GetInterfaceLength()] = interfaces[i];
 	}
-#else
-#ifdef HID_ENABLED
-	for ( i=0; i<interfaces_length; i++)
-	{
-		cache_buffer[i+sizeof(ConfigDescriptor)] = interfaces[i];
+#elif defined(HID_ENABLED)
+	for (i=0; i<interfaces_length; i++) {
+		cache_buffer[i + sizeof(ConfigDescriptor)] = interfaces[i];
 	}
-#endif
-
-#ifdef CDC_ENABLED
-	for ( i=0; i<interfaces_length; i++)
-	{
-		cache_buffer[i+sizeof(ConfigDescriptor)] = interfaces[i];
+#elif defined(CDC_ENABLED)
+	for (i=0; i<interfaces_length; i++) {
+		cache_buffer[i + sizeof(ConfigDescriptor)] = interfaces[i];
 	}
-#endif
 #endif
 
-	if (maxlen > sizeof(cache_buffer))
-	{
+	if (maxlen > sizeof(cache_buffer)) {
 		 maxlen = sizeof(cache_buffer);
 	}
-	USBD_SendControl(0,cache_buffer, maxlen );
-	return true;
+	return sendControl(cache_buffer, maxlen);
 }
 
-static bool USBD_SendDescriptor(Setup* pSetup)
+bool USBDeviceClass::sendDescriptor(Setup &setup)
 {
-	uint8_t t = pSetup->wValueH;
+	uint8_t t = setup.wValueH;
 	uint8_t desc_length = 0;
-	const uint8_t* desc_addr = 0;
+	const uint8_t *desc_addr = 0;
 
-	if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
+	if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE)
 	{
-		TRACE_CORE(printf("=> USBD_SendDescriptor : USB_CONFIGURATION_DESCRIPTOR_TYPE length=%d\r\n", setup.wLength);)
-		return USBD_SendConfiguration(pSetup->wLength);
+		return USBDevice.sendConfiguration(setup.wLength);
 	}
 
-#ifdef HID_ENABLED
-	if (HID_REPORT_DESCRIPTOR_TYPE == t)
+#if defined(HID_ENABLED)
+	if (t == HID_REPORT_DESCRIPTOR_TYPE)
 	{
-		TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");)
 		return HID_GetDescriptor();
 	}
-	if (HID_HID_DESCRIPTOR_TYPE == t)
+
+	if (t == HID_HID_DESCRIPTOR_TYPE)
 	{
 		uint8_t tab[9] = D_HIDREPORT((uint8_t)HID_SizeReportDescriptor());
-
-		TRACE_CORE(puts("=> USBD_SendDescriptor : HID_HID_DESCRIPTOR_TYPE\r\n");)
-
-		return USBD_SendControl(0, tab, sizeof(tab));
+		return USBDevice.sendControl(tab, sizeof(tab));
 	}
 #endif
 
-	if (USB_DEVICE_DESCRIPTOR_TYPE == t)
+	if (t == USB_DEVICE_DESCRIPTOR_TYPE)
 	{
-		TRACE_CORE(puts("=> USBD_SendDescriptor : USB_DEVICE_DESCRIPTOR_TYPE\r\n");)
 		desc_addr = (const uint8_t*)&USB_DeviceDescriptor;
-        if( *desc_addr > pSetup->wLength ) {
-            desc_length = pSetup->wLength;
-        }
+		if (*desc_addr > setup.wLength) {
+			desc_length = setup.wLength;
+		}
 	}
 	else if (USB_STRING_DESCRIPTOR_TYPE == t)
 	{
-		TRACE_CORE(puts("=> USBD_SendDescriptor : USB_STRING_DESCRIPTOR_TYPE\r\n");)
-		if (pSetup->wValueL == 0) {
+		if (setup.wValueL == 0) {
 			desc_addr = (const uint8_t*)&STRING_LANGUAGE;
 		}
-		else if (pSetup->wValueL == IPRODUCT) {
-			return USB_SendStringDescriptor(STRING_PRODUCT, pSetup->wLength);
+		else if (setup.wValueL == IPRODUCT) {
+			return sendStringDescriptor(STRING_PRODUCT, setup.wLength);
 		}
-		else if (pSetup->wValueL == IMANUFACTURER) {
-			return USB_SendStringDescriptor(STRING_MANUFACTURER, pSetup->wLength);
+		else if (setup.wValueL == IMANUFACTURER) {
+			return sendStringDescriptor(STRING_MANUFACTURER, setup.wLength);
 		}
 		else {
 			return false;
 		}
-		if( *desc_addr > pSetup->wLength ) {
-			desc_length = pSetup->wLength;
+		if (*desc_addr > setup.wLength) {
+			desc_length = setup.wLength;
 		}
 	}
-    else
-    {
-        TRACE_CORE(printf("Device ERROR");)
-    }
-
-	if (desc_addr == 0)
+	else
 	{
+	}
+
+	if (desc_addr == 0) {
 		return false;
 	}
 
-	if (desc_length == 0)
-	{
+	if (desc_length == 0) {
 		desc_length = *desc_addr;
 	}
 
-	TRACE_CORE(printf("=> USBD_SendDescriptor : desc_addr=%p desc_length=%d\r\n", desc_addr, desc_length);)
-	USBD_SendControl(0, desc_addr, desc_length);
+	sendControl(desc_addr, desc_length);
 
 	return true;
 }
 
 
-void EndpointHandler(uint8_t bEndpoint)
+void USBDeviceClass::handleEndpoint(uint8_t ep)
 {
-#ifdef CDC_ENABLED
-	if( bEndpoint == CDC_ENDPOINT_OUT )
+#if defined(CDC_ENABLED)
+	if (ep == CDC_ENDPOINT_OUT)
 	{
-		udd_OUT_transfer_allowed(CDC_ENDPOINT_OUT);
+		// The RAM Buffer is empty: we can receive data
+		//usbd.epBank0ResetReady(CDC_ENDPOINT_OUT);
 
 		// Handle received bytes
-		if (USBD_Available(CDC_ENDPOINT_OUT))
-		{
+		if (available(CDC_ENDPOINT_OUT))
 			SerialUSB.accept();
-		}
 	}
-	if( bEndpoint == CDC_ENDPOINT_IN )
+	if (ep == CDC_ENDPOINT_IN)
 	{
-		udd_IN_stop_transfer(CDC_ENDPOINT_IN);
-		/* Clear the transfer complete flag  */
-		udd_clear_IN_transf_cplt(CDC_ENDPOINT_IN);
-
+		// NAK on endpoint IN, the bank is not yet filled in.
+		usbd.epBank1ResetReady(CDC_ENDPOINT_IN);
+		usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN);
 	}
-	if( bEndpoint == CDC_ENDPOINT_ACM )
+	if (ep == CDC_ENDPOINT_ACM)
 	{
-		udd_IN_stop_transfer(CDC_ENDPOINT_ACM);
-		/* Clear the transfer complete flag  */
-		udd_clear_IN_transf_cplt(CDC_ENDPOINT_ACM);
+		// NAK on endpoint IN, the bank is not yet filled in.
+		usbd.epBank1ResetReady(CDC_ENDPOINT_ACM);
+		usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM);
 	}
 #endif
 
-#ifdef HID_ENABLED
-	/* Nothing to do in our example */
+#if defined(HID_ENABLED)
+	// Empty
 #endif
 }
 
+void USBDeviceClass::init()
+{
+	// Enable USB clock
+	PM->APBBMASK.reg |= PM_APBBMASK_USB;
+
+	// Set up the USB DP/DN pins
+	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
+	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
+
+	// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
+	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6)     | // Generic Clock Multiplexer 6
+	                    GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+	                    GCLK_CLKCTRL_CLKEN;
+	while (GCLK->STATUS.bit.SYNCBUSY)
+		;
+
+	// Reset USB Device
+	usbd.reset();
+
+	usbd.calibrate();
+	usbd.setUSBDeviceMode();
+	usbd.runInStandby();
+	usbd.setFullSpeed();
+
+	// Configure interrupts
+	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
+	NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
+
+	usbd.enable();
+
+	initialized = true;
+}
 
-void USB_ISR(void)
+bool USBDeviceClass::attach()
 {
-	uint16_t flags;
-	uint8_t i;
-	uint8_t ept_int;
+	if (!initialized)
+		return false;
 
-	ept_int = udd_endpoint_interrupt();
+	usbd.attach();
+	usbd.enableEndOfResetInterrupt();
+	usbd.enableStartOfFrameInterrupt();
 
-	/* Not endpoint interrupt */
-	if (0 == ept_int)
-	{
-		udd_clear_wakeup_interrupt();
-		udd_clear_eorsm_interrupt();
-		udd_clear_suspend_interrupt();
+	_usbConfiguration = 0;
+	return true;
+}
 
-		// End of bus reset
-		if (Is_udd_reset())
-		{
-			TRACE_CORE(printf(">>> End of Reset\r\n");)
-			// Reset USB address to 0
-			udd_configure_address(0);
-
-			// Configure EP 0
-			UDD_InitEP(0, USB_ENDPOINT_TYPE_CONTROL);
-			udd_enable_setup_received_interrupt(0);
-			_usbConfiguration = 0;
-			udd_ack_reset();
+void USBDeviceClass::setAddress(uint32_t addr)
+{
+	usbd.epBank1SetByteCount(0, 0);
+	usbd.epBank1AckTransferComplete(0);
+
+	// RAM buffer is full, we can send data (IN)
+	usbd.epBank1SetReady(0);
+
+	// Wait for transfer to complete
+	while (!usbd.epBank1IsTransferComplete(0)) {}
+
+	// Set USB address to addr
+	USB->DEVICE.DADD.bit.DADD = addr; // Address
+	USB->DEVICE.DADD.bit.ADDEN = 1; // Enable
+}
+
+bool USBDeviceClass::detach()
+{
+	if (!initialized)
+		return false;
+	usbd.detach();
+	return true;
+}
+
+bool USBDeviceClass::configured()
+{
+	return _usbConfiguration != 0;
+}
+
+bool USBDeviceClass::handleClassInterfaceSetup(Setup& setup)
+{
+	uint8_t i = setup.wIndex;
+
+	#if defined(CDC_ENABLED)
+	if (CDC_ACM_INTERFACE == i)
+	{
+		if (CDC_Setup(setup) == false) {
+			sendZlp(0);
 		}
+		return true;
+	}
+	#endif
 
-		if (Is_udd_sof())
-		{
-			udd_ack_sof();
+	#if defined(HID_ENABLED)
+	if (HID_INTERFACE == i)
+	{
+		if (HID_Setup(setup) == true) {
+			sendZlp(0);
 		}
+		return true;
+	}
+	#endif
 
+	return false;
+}
+
+void USBDeviceClass::initEP(uint32_t ep, uint32_t config)
+{
+	if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)))
+	{
+		usbd.epBank1SetSize(ep, 8);
+		usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
+		usbd.epBank1SetType(ep, 4); // INTERRUPT IN
 	}
-	else
+	else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0)))
 	{
-		// Endpoint interrupt
-		flags = udd_read_endpoint_flag(0);
+		usbd.epBank0SetSize(ep, 64);
+		usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
+		usbd.epBank0SetType(ep, 3); // BULK OUT
+
+		// Release OUT EP
+		usbd.epBank0SetMultiPacketSize(ep, 64);
+		usbd.epBank0SetByteCount(ep, 0);
+		
+		// The RAM Buffer is empty: we can receive data
+		//usbd.epBank0ResetReady(ep);
+	}
+	else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)))
+	{
+		usbd.epBank1SetSize(ep, 64);
+		usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
 
-		// endpoint received setup interrupt
-		if (flags & USB_DEVICE_EPINTFLAG_RXSTP)
-		{
-			Setup *pSetupData;
+		// NAK on endpoint IN, the bank is not yet filled in.
+		usbd.epBank1ResetReady(ep);
 
-			/* Clear the Received Setup flag */
-			udd_read_endpoint_flag(0) = USB_DEVICE_EPINTFLAG_RXSTP;
+		usbd.epBank1SetType(ep, 3); // BULK IN
+	}
+	else if (config == USB_ENDPOINT_TYPE_CONTROL)
+	{
+		// XXX: Needed?
+		usbd.epBank0DisableAutoZLP(ep);
+		usbd.epBank1DisableAutoZLP(ep);
+
+		// Setup Control OUT
+		usbd.epBank0SetSize(ep, 64);
+		usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[0]);
+		usbd.epBank0SetType(ep, 1); // CONTROL OUT / SETUP
+
+		// Setup Control IN
+		usbd.epBank1SetSize(ep, 64);
+		usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[0]);
+		usbd.epBank1SetType(ep, 1); // CONTROL IN
+
+		// Release OUT EP
+		usbd.epBank0SetMultiPacketSize(ep, 64);
+		usbd.epBank0SetByteCount(ep, 0);
+
+		// NAK on endpoint OUT, the bank is full.
+		usbd.epBank0SetReady(ep);
+		// NAK on endpoint IN, the bank is not yet filled in.
+		//usbd.epBank1ResetReady(ep);
+	}
+}
 
-			UDD_Recv(EP0, (uint8_t**)&pSetupData);
+void USBDeviceClass::flush(uint32_t ep)
+{
+	if (available(ep)) {
+		// RAM buffer is full, we can send data (IN)
+		usbd.epBank1SetReady(ep);
 
-			/* Clear the Bank 0 ready flag on Control OUT */
-			udd_OUT_transfer_allowed(0);
+	 	// Clear the transfer complete flag
+		usbd.epBank1AckTransferComplete(ep);
+	}
+}
 
-			bool ok = true;
-			if (REQUEST_STANDARD == (pSetupData->bmRequestType & REQUEST_TYPE))
-			{
-				unsigned char data_to_be_send[2];
-
-				// Standard Requests
-				uint8_t r = pSetupData->bRequest;
-				if (GET_STATUS == r)
-				{
-					if( pSetupData->bmRequestType == 0 )  // device
-					{
-						// Send the device status
-     					TRACE_CORE(puts(">>> EP0 Int: GET_STATUS\r\n");)
-						// Check current configuration for power mode (if device is configured)
-						// TODO
-						// Check if remote wake-up is enabled
-						// TODO
-						data_to_be_send[0]=0;
-						data_to_be_send[1]=0;
-						UDD_Send(0, data_to_be_send, 2);
-					}
-					// if( pSetupData->bmRequestType == 2 ) // Endpoint:
-					else
-					{
-						// Send the endpoint status
-						// Check if the endpoint if currently halted
- 						if( isEndpointHalt == 1 )
-							data_to_be_send[0]=1;
- 						else
-							data_to_be_send[0]=0;
-						data_to_be_send[1]=0;
-						UDD_Send(0, data_to_be_send, 2);
-					}
-				}
-				else if (CLEAR_FEATURE == r)
-				{
-				   // Check which is the selected feature
-					if( pSetupData->wValueL == 1) // DEVICEREMOTEWAKEUP
-					{
-						// Enable remote wake-up and send a ZLP
-						if( isRemoteWakeUpEnabled == 1 )
-							data_to_be_send[0]=1;
-						else
-							data_to_be_send[0]=0;
-						data_to_be_send[1]=0;
-						UDD_Send(0, data_to_be_send, 2);
-					}
-					else // if( pSetupData->wValueL == 0) // ENDPOINTHALT
-					{
-						isEndpointHalt = 0;
-						send_zlp();
-					}
- 				}
-				else if (SET_FEATURE == r)
-				{
-					// Check which is the selected feature
-					if( pSetupData->wValueL == 1) // DEVICEREMOTEWAKEUP
-					{
-						// Enable remote wake-up and send a ZLP
-						isRemoteWakeUpEnabled = 1;
-	    				data_to_be_send[0] = 0;
-						UDD_Send(0, data_to_be_send, 1);
-					}
-					if( pSetupData->wValueL == 0) // ENDPOINTHALT
-					{
-						// Halt endpoint
-						isEndpointHalt = 1;
-						send_zlp();
-					}
-				}
-				else if (SET_ADDRESS == r)
-				{
-					TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");)
-					UDD_SetAddress(pSetupData->wValueL);
-				}
-				else if (GET_DESCRIPTOR == r)
-				{
-					TRACE_CORE(puts(">>> EP0 Int: GET_DESCRIPTOR\r\n");)
-					ok = USBD_SendDescriptor(pSetupData);
-				}
-				else if (SET_DESCRIPTOR == r)
-				{
-					TRACE_CORE(puts(">>> EP0 Int: SET_DESCRIPTOR\r\n");)
-					ok = false;
-				}
-				else if (GET_CONFIGURATION == r)
-				{
-					TRACE_CORE(puts(">>> EP0 Int: GET_CONFIGURATION\r\n");)
-					UDD_Send(0, (void*)&_usbConfiguration, 1);
-				}
-				else if (SET_CONFIGURATION == r)
-				{
-					if (REQUEST_DEVICE == (pSetupData->bmRequestType & REQUEST_RECIPIENT))
-					{
-						TRACE_CORE(printf(">>> EP0 Int: SET_CONFIGURATION REQUEST_DEVICE %d\r\n", pSetupData->wValueL);)
-#ifdef HID_ENABLED
-						UDD_InitEP( HID_ENDPOINT_INT, USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0));
-#endif
+void USBDeviceClass::stall(uint32_t ep)
+{
+	// TODO: test
+	// TODO: use .bit. notation
 
-#ifdef CDC_ENABLED
-						UDD_InitEP( CDC_ENDPOINT_ACM, USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0));
-						UDD_InitEP( CDC_ENDPOINT_OUT, USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0));
-						UDD_InitEP( CDC_ENDPOINT_IN, USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0));
-#endif
-						_usbConfiguration = pSetupData->wValueL;
+	// Stall endpoint
+	USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ(2);
+}
 
-#ifdef CDC_ENABLED
-						// Enable interrupt for CDC reception from host (OUT packet)
-						udd_ept_enable_it_IN_transf_cplt(CDC_ENDPOINT_ACM);
-						udd_ept_enable_it_OUT_transf_cplt(CDC_ENDPOINT_OUT);
-#endif
-						send_zlp();
-					}
-					else
-					{
-						TRACE_CORE(puts(">>> EP0 Int: SET_CONFIGURATION failed!\r\n");)
-						ok = false;
-					}
-				}
-				else if (GET_INTERFACE == r)
-				{
-					TRACE_CORE(puts(">>> EP0 Int: GET_INTERFACE\r\n");)
-					UDD_Send(0, (void*)&_usbSetInterface, 1);
-				}
-				else if (SET_INTERFACE == r)
-				{
-					_usbSetInterface = pSetupData->wValueL;
-					TRACE_CORE(puts(">>> EP0 Int: SET_INTERFACE\r\n");)
-					send_zlp();
-				}
-			}
-			else
-			{
-				TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");)
-				ok =  USBD_ClassInterfaceRequest(*pSetupData);
-			}
+bool USBDeviceClass::connected()
+{
+	// Count frame numbers
+	uint8_t f = USB->DEVICE.FNUM.bit.FNUM;
+	//delay(3);
+	return f != USB->DEVICE.FNUM.bit.FNUM;
+}
 
-			if (ok)
-			{
-				TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");)
-				UDD_ClearIN();
-			}
-			else
-			{
-				TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");)
-				UDD_Stall(0);
-			}
 
-			if( flags & USB_DEVICE_EPINTFLAG_STALL(2) )
-			{
-				/* Clear the stall flag */
-				udd_clear_stall_request(0);
+uint32_t USBDeviceClass::recvControl(void *_data, uint32_t len)
+{
+	uint8_t *data = reinterpret_cast<uint8_t *>(_data);
+// NO RXOUT ???????
 
-				// Remove stall request
-				udd_remove_stall_request(0);
-			}
-		}  // end if USB_DEVICE_EPINTFLAG_RXSTP
+	// The RAM Buffer is empty: we can receive data
+	usbd.epBank0ResetReady(0);
 
-		i=0;
-		ept_int &= 0xFE;  // Remove endpoint number 0 (setup)
-		while (ept_int != 0)
-		{
-            // Check if endpoint has a pending interrupt
-            if ((ept_int & (1 << i)) != 0)
-			{
-				if( (udd_read_endpoint_flag(i) & USB_DEVICE_EPINTFLAG_TRCPT_Msk ) != 0 )
+	//usbd.epBank0AckSetupReceived(0);
+	uint32_t read = armRecvCtrlOUT(0, len);
+	if (read > len)
+		read = len;
+	//while (!usbd.epBank0AckTransferComplete(0)) {}
+	uint8_t *buffer = udd_ep_out_cache_buffer[0];
+	for (uint32_t i=0; i<len; i++) {
+		data[i] = buffer[i];
+	}
+
+	return read;
+}
+
+// Number of bytes, assumes a rx endpoint
+uint32_t USBDeviceClass::available(uint32_t ep)
+{
+	return usbd.epBank0ByteCount(ep);
+}
+
+// Non Blocking receive
+// Return number of bytes read
+uint32_t USBDeviceClass::recv(uint32_t ep, void *_data, uint32_t len)
+{
+	if (!_usbConfiguration)
+		return -1;
+
+	if (available(ep) < len)
+		len = available(ep);
+
+	armRecv(ep, len);
 
-				{
-					EndpointHandler(i);
-				}
-                ept_int &= ~(1 << i);
+	usbd.epBank0DisableTransferComplete(ep);
 
-                if (ept_int != 0)
-				{
+	// NAK on endpoint OUT, the bank is full.
+	//usbd.epBank0SetReady(CDC_ENDPOINT_OUT);
 
-                    TRACE_CORE("\n\r  - ");
-                }
-            }
-            i++;
-			if( i> USB_EPT_NUM) break;  // fire exit
-        }
+	uint8_t *buffer = udd_ep_out_cache_buffer[ep];
+	uint8_t *data = reinterpret_cast<uint8_t *>(_data);
+	for (uint32_t i=0; i<len; i++) {
+		data[i] = buffer[i];
 	}
+
+	// release empty buffer
+	if (len && !available(ep)) {
+		// The RAM Buffer is empty: we can receive data
+		usbd.epBank0ResetReady(ep);
+		
+		// Clear Transfer complete 0 flag
+		usbd.epBank0AckTransferComplete(ep);
+	}
+
+	return len;
 }
 
+//	Recv 1 byte if ready
+uint32_t USBDeviceClass::recv(uint32_t ep)
+{
+	uint8_t c;
+	if (recv(ep, &c, 1) != 1) {
+		return -1;
+	} else {
+		return c;
+	}
+}
 
+uint8_t USBDeviceClass::armRecvCtrlOUT(uint32_t ep, uint32_t len)
+{
+	/* get endpoint configuration from setting register */
+	usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
+	usbd.epBank0SetMultiPacketSize(ep, 8);
+	usbd.epBank0SetByteCount(ep, 0);
+	//usbd.epBank0ResetReady(0);
+	//while (!usbd.epBank0IsTransferComplete(ep)) {}
+	//while (usbd.epBank0IsReady(ep)) {}
+
+	//usbd.epBank0SetByteCount(0, 0);
+	//usbd.epBank0SetMultiPacketSize(0, 8);
+	usbd.epBank0ResetReady(ep);
+
+	// Wait OUT
+	while (!usbd.epBank0IsReady(ep)) {}
+	while (!usbd.epBank0IsTransferComplete(ep)) {} // XXX: while(USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT == 0);
+	return usbd.epBank0ByteCount(ep);
+}
 
-void USBD_Flush(uint32_t ep)
+uint8_t USBDeviceClass::armRecv(uint32_t ep, uint32_t len)
 {
-	if (UDD_FifoByteCount(ep))
-	{
-		UDD_ReleaseTX(ep);
+	usbd.epBank0SetSize(ep, 64);
+	usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
+	usbd.epBank0SetMultiPacketSize(ep, 64); // XXX: Should be "len"?
+	uint16_t count = usbd.epBank0ByteCount(ep);
+	if (count >= 64) {
+		usbd.epBank0SetByteCount(ep, count - 64);
+	} else {
+		usbd.epBank0SetByteCount(ep, 0);
 	}
+	// The RAM Buffer is empty: we can receive data
+	//usbd.epBank0ResetReady(ep);
+
+	// Wait for transfer to complete
+	//while (!usbd.epBank0IsTransferComplete(ep)) {}
+	//while (usbd.epBank0IsReady(ep)) {}
+	// NAK on endpoint OUT, the bank is full.
+	//usbd.epBank0ResetReady(ep);
+
+	return usbd.epBank0ByteCount(ep);
 }
 
-//	Counting frames
-uint32_t USBD_Connected(void)
+//	Blocking Send of data to an endpoint
+uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
 {
-	uint8_t f = UDD_GetFrameNumber();
+	if (!_usbConfiguration)
+		return -1;
+
+	armSend(ep, data, len);
+
+	// Clear the transfer complete flag
+	usbd.epBank1AckTransferComplete(ep);
 
-    //delay(3);
+	// RAM buffer is full, we can send data (IN)
+	usbd.epBank1SetReady(ep);
 
-	return f != UDD_GetFrameNumber();
+	// Wait for transfer to complete
+	while (!usbd.epBank1IsTransferComplete(ep)) {
+		;  // need fire exit.
+	}
+	return len;
 }
 
+uint32_t USBDeviceClass::armSend(uint32_t ep, const void* data, uint32_t len)
+{
+	memcpy(&udd_ep_in_cache_buffer[ep], data, len);
 
-//=======================================================================
-//=======================================================================
+	// Get endpoint configuration from setting register
+	usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
+	usbd.epBank1SetMultiPacketSize(ep, 0);
+	usbd.epBank1SetByteCount(ep, len);
 
-USBDevice_ USBDevice;
+	return len;
+}
 
-USBDevice_::USBDevice_()
+uint32_t USBDeviceClass::sendControl(const void* _data, uint32_t len)
 {
-	UDD_SetStack(&USB_ISR);
+	const uint8_t *data = reinterpret_cast<const uint8_t *>(_data);
+	uint32_t length = len;
+	uint32_t sent = 0;
+	uint32_t pos = 0;
+
+ 	while (len > 0)
+ 	{
+		sent = armSend(EP0, data + pos, len);
+		pos += sent;
+		len -= sent;
+ 	}
+
+	return length;
 }
 
-bool USBDevice_::attach()
+void USBDeviceClass::sendZlp(uint32_t ep)
 {
-  if (_usbInitialized != 0UL)
-  {
-    UDD_Attach();
-	_usbConfiguration = 0;
-	return true;
-  }
-  else
-  {
-    return false;
-  }
+	// Set the byte count as zero
+	usbd.epBank1SetByteCount(ep, 0);
 }
 
-bool USBDevice_::detach()
+bool USBDeviceClass::handleStandardSetup(Setup &setup)
 {
-	if (_usbInitialized != 0UL)
-	{
-		UDD_Detach();
+	switch (setup.bRequest) {
+	case GET_STATUS:
+		if (setup.bmRequestType == 0)  // device
+		{
+			// Send the device status
+			// TODO: Check current configuration for power mode (if device is configured)
+			// TODO: Check if remote wake-up is enabled
+			uint8_t buff[] = { 0, 0 };
+			armSend(0, buff, 2);
+			return true;
+		}
+		// if( setup.bmRequestType == 2 ) // Endpoint:
+		else
+		{
+			// Send the endpoint status
+			// Check if the endpoint if currently halted
+			uint8_t buff[] = { 0, 0 };
+			if (isEndpointHalt == 1)
+				buff[0] = 1;
+			armSend(0, buff, 2);
+			return true;
+		}
+
+	case CLEAR_FEATURE:
+		// Check which is the selected feature
+		if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP
+		{
+			// Enable remote wake-up and send a ZLP
+			uint8_t buff[] = { 0, 0 };
+			if (isRemoteWakeUpEnabled == 1)
+				buff[0] = 1;
+			armSend(0, buff, 2);
+			return true;
+		}
+		else // if( setup.wValueL == 0) // ENDPOINTHALT
+		{
+			isEndpointHalt = 0;
+			sendZlp(0);
+			return true;
+		}
+
+	case SET_FEATURE:
+		// Check which is the selected feature
+		if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP
+		{
+			// Enable remote wake-up and send a ZLP
+			isRemoteWakeUpEnabled = 1;
+			uint8_t buff[] = { 0 };
+			armSend(0, buff, 1);
+			return true;
+		}
+		if (setup.wValueL == 0) // ENDPOINTHALT
+		{
+			// Halt endpoint
+			isEndpointHalt = 1;
+			sendZlp(0);
+			return true;
+		}
+
+	case SET_ADDRESS:
+		setAddress(setup.wValueL);
 		return true;
-	}
-	else
-	{
+
+	case GET_DESCRIPTOR:
+		return sendDescriptor(setup);
+
+	case SET_DESCRIPTOR:
 		return false;
+
+	case GET_CONFIGURATION:
+		armSend(0, (void*)&_usbConfiguration, 1);
+		return true;
+
+	case SET_CONFIGURATION:
+		if (REQUEST_DEVICE == (setup.bmRequestType & REQUEST_RECIPIENT)) {
+			#if defined(HID_ENABLED)
+			initEP(HID_ENDPOINT_INT, USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0));
+			#endif
+
+			#if defined(CDC_ENABLED)
+			initEP(CDC_ENDPOINT_ACM, USB_ENDPOINT_TYPE_BULK      | USB_ENDPOINT_IN(0));
+			initEP(CDC_ENDPOINT_OUT, USB_ENDPOINT_TYPE_BULK      | USB_ENDPOINT_OUT(0));
+			initEP(CDC_ENDPOINT_IN,  USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0));
+			#endif
+			_usbConfiguration = setup.wValueL;
+
+			#if defined(CDC_ENABLED)
+			// Enable interrupt for CDC reception from host (OUT packet)
+			usbd.epBank1EnableTransferComplete(CDC_ENDPOINT_ACM);
+			usbd.epBank0EnableTransferComplete(CDC_ENDPOINT_OUT);
+			#endif
+
+			sendZlp(0);
+			return true;
+		} else {
+			return false;
+		}
+
+	case GET_INTERFACE:
+		armSend(0, (void*)&_usbSetInterface, 1);
+		return true;
+
+	case SET_INTERFACE:
+		_usbSetInterface = setup.wValueL;
+		sendZlp(0);
+		return true;
+
+	default:
+		return true;
 	}
 }
 
-bool USBDevice_::configured()
+void USBDeviceClass::ISRHandler()
 {
-	return _usbConfiguration;
-}
+	// End-Of-Reset
+	if (usbd.isEndOfResetInterrupt())
+	{
+		// Configure EP 0
+		initEP(0, USB_ENDPOINT_TYPE_CONTROL);
 
-void USBDevice_::poll()
-{
+		// Enable Setup-Received interrupt
+		usbd.epBank0EnableSetupReceived(0);
+
+		_usbConfiguration = 0;
+
+		usbd.ackEndOfResetInterrupt();
+	}
+
+	// Start-Of-Frame
+	if (usbd.isStartOfFrameInterrupt())
+	{
+		usbd.ackStartOfFrameInterrupt();
+	}
+
+	// Endpoint 0 Received Setup interrupt
+	if (usbd.epBank0IsSetupReceived(0))
+	{
+		usbd.epBank0AckSetupReceived(0);
+
+		Setup *setup = reinterpret_cast<Setup *>(udd_ep_out_cache_buffer[0]);
+
+		/* Clear the Bank 0 ready flag on Control OUT */
+		// The RAM Buffer is empty: we can receive data
+		usbd.epBank0ResetReady(0);
+
+		bool ok;
+		if (REQUEST_STANDARD == (setup->bmRequestType & REQUEST_TYPE)) {
+			// Standard Requests
+			ok = handleStandardSetup(*setup);
+		} else {
+			// Class Interface Requests
+			ok = handleClassInterfaceSetup(*setup);
+		}
+
+		if (ok) {
+			usbd.epBank1SetReady(0);
+		} else {
+			stall(0);
+		}
+
+		// XXX: Should be really cleared?
+		if (usbd.epBank1IsStalled(0)) // XXX:(USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.STALL)
+		{
+			usbd.epBank1AckStalled(0);
+
+			// Remove stall request
+			usbd.epBank1DisableStalled(0);
+		}
+
+	} // end Received Setup handler
+
+	uint8_t i=0;
+	uint8_t ept_int = usbd.epInterruptSummary() & 0xFE; // Remove endpoint number 0 (setup)
+	while (ept_int != 0)
+	{
+		// Check if endpoint has a pending interrupt
+		if ((ept_int & (1 << i)) != 0)
+		{
+			// Endpoint Transfer Complete (0/1) Interrupt
+			if (usbd.epBank0IsTransferComplete(i) ||
+			    usbd.epBank1IsTransferComplete(i))
+			{
+				handleEndpoint(i);
+			}
+			ept_int &= ~(1 << i);
+		}
+		i++;
+		if (i > USB_EPT_NUM)
+			break;  // fire exit
+	}
 }
 
-void USBDevice_::init()
-{
-	UDD_Init();
-	_usbInitialized=1UL;
+/*
+ * USB Device instance
+ * -------------------
+ */
+
+// USBDevice class instance
+USBDeviceClass USBDevice;
+
+// USB_Handler ISR
+extern "C" void USB_Handler(void) {
+	USBDevice.ISRHandler();
 }
diff --git a/cores/arduino/USB/USBCore.h b/cores/arduino/USB/USBCore.h
index 1441a649..d584fdfc 100644
--- a/cores/arduino/USB/USBCore.h
+++ b/cores/arduino/USB/USBCore.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -31,6 +31,16 @@
 #define GET_INTERFACE				10
 #define SET_INTERFACE				11
 
+// bEndpointAddress in Endpoint Descriptor
+#define USB_ENDPOINT_DIRECTION_MASK            0x80
+#define USB_ENDPOINT_OUT(addr)                 ((addr) | 0x00)
+#define USB_ENDPOINT_IN(addr)                  ((addr) | 0x80)
+
+#define USB_ENDPOINT_TYPE_MASK                 0x03
+#define USB_ENDPOINT_TYPE_CONTROL              0x00
+#define USB_ENDPOINT_TYPE_ISOCHRONOUS          0x01
+#define USB_ENDPOINT_TYPE_BULK                 0x02
+#define USB_ENDPOINT_TYPE_INTERRUPT            0x03
 
 // bmRequestType
 #define REQUEST_HOSTTODEVICE		0x00
diff --git a/cores/arduino/USB/USBDesc.h b/cores/arduino/USB/USBDesc.h
index 9b1cdf8c..655fb6d0 100644
--- a/cores/arduino/USB/USBDesc.h
+++ b/cores/arduino/USB/USBDesc.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
diff --git a/cores/arduino/USB/USB_device.h b/cores/arduino/USB/USB_device.h
deleted file mode 100644
index 6353f977..00000000
--- a/cores/arduino/USB/USB_device.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-  Copyright (c) 2014 Arduino.  All right reserved.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef USB_DEVICE_H_INCLUDED
-#define USB_DEVICE_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-#include "USB/samd21_device.h"
-
-
-// bEndpointAddress in Endpoint Descriptor
-#define USB_ENDPOINT_DIRECTION_MASK            0x80
-#define USB_ENDPOINT_OUT(addr)                 ((addr) | 0x00)
-#define USB_ENDPOINT_IN(addr)                  ((addr) | 0x80)
-
-#define USB_ENDPOINT_TYPE_MASK                 0x03
-#define USB_ENDPOINT_TYPE_CONTROL              0x00
-#define USB_ENDPOINT_TYPE_ISOCHRONOUS          0x01
-#define USB_ENDPOINT_TYPE_BULK                 0x02
-#define USB_ENDPOINT_TYPE_INTERRUPT            0x03
-
-
-extern void UDD_ClearIN(void);
-extern uint32_t UDD_FifoByteCount(uint32_t ep);
-extern void UDD_ReleaseRX(uint32_t ep);
-extern void UDD_ReleaseTX(uint32_t ep);
-extern uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len);
-extern uint8_t UDD_Recv_data(uint32_t ep, uint32_t len);
-extern void UDD_Recv(uint32_t ep, uint8_t** data);
-extern void UDD_Init(void);
-extern void UDD_InitEP( uint32_t ul_ep, uint32_t ul_ep_cfg );
-extern void send_zlp (void);
-extern void UDD_Attach(void);
-extern void UDD_Detach(void);
-extern void UDD_SetAddress(uint32_t addr);
-extern void UDD_Stall(uint32_t ep);
-extern uint32_t UDD_GetFrameNumber(void);
-extern void UDD_SetStack(void (*pf_isr)(void)); 
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* USB_DEVICE_H_INCLUDED */
diff --git a/cores/arduino/USB/USB_host.h b/cores/arduino/USB/USB_host.h
index e20738e8..390e3dd1 100644
--- a/cores/arduino/USB/USB_host.h
+++ b/cores/arduino/USB/USB_host.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
diff --git a/cores/arduino/USB/USB_interrupt.c b/cores/arduino/USB/USB_interrupt.c
deleted file mode 100644
index 3f1f05f6..00000000
--- a/cores/arduino/USB/USB_interrupt.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-** Permission to use, copy, modify, and/or distribute this software for
-** any purpose with or without fee is hereby granted, provided that the
-** above copyright notice and this permission notice appear in all copies.
-**
-** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
-** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
-** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
-** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-** SOFTWARE.
-*/
-
-void (*gpf_isr)(void) = (0UL);
-
-void USB_Handler( void )
-{
-	if (gpf_isr)
-	gpf_isr();
-}
-
diff --git a/cores/arduino/USB/samd21_device.c b/cores/arduino/USB/samd21_device.c
deleted file mode 100644
index cff711f4..00000000
--- a/cores/arduino/USB/samd21_device.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
-  Copyright (c) 2014 Arduino.  All right reserved.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "variant.h"
-#include "USB/USB_device.h"
-#include "USB/samd21_device.h"
-#include "sam.h"
-
-#ifdef __cplusplus
-extern "C"{
-#endif // __cplusplus
-
-#ifdef SAMD_SERIES
-
-//#define TRACE_DEVICE(x)	x
-#define TRACE_DEVICE(x)
-
-__attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/ uint8_t udd_ep_out_cache_buffer[4][64];
-__attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/ uint8_t udd_ep_in_cache_buffer[4][128];
-
-/**
- * USB SRAM data containing pipe descriptor table
- * The content of the USB SRAM can be :
- * - modified by USB hardware interface to update pipe status.
- *   Thereby, it is read by software.
- * - modified by USB software to control pipe.
- *   Thereby, it is read by hardware.
- * This data section is volatile.
- */
- __attribute__((__aligned__(4))) UsbDeviceDescriptor usb_endpoint_table[USB_EPT_NUM];
-
-
-extern void (*gpf_isr)(void);
-
-
-void UDD_SetStack(void (*pf_isr)(void))
-{
-	gpf_isr = pf_isr;
-}
-
-// NVM Software Calibration Area Mapping
-// USB TRANSN calibration value. Should be written to the USB PADCAL register.
-#define NVM_USB_PAD_TRANSN_POS  45
-#define NVM_USB_PAD_TRANSN_SIZE 5
-// USB TRANSP calibration value. Should be written to the USB PADCAL register.
-#define NVM_USB_PAD_TRANSP_POS  50
-#define NVM_USB_PAD_TRANSP_SIZE 5
-// USB TRIM calibration value. Should be written to the USB PADCAL register.
-#define NVM_USB_PAD_TRIM_POS  55
-#define NVM_USB_PAD_TRIM_SIZE 3
-
-void UDD_Init(void)
-{
-	uint32_t pad_transn;
-    uint32_t pad_transp;
-    uint32_t pad_trim;
-	uint32_t i;
-
-	/* Enable USB clock */
-	PM->APBBMASK.reg |= PM_APBBMASK_USB;
-
-	/* Set up the USB DP/DN pins */
-	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
-	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
-	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
-	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
-	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
-	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
-
-	/* ----------------------------------------------------------------------------------------------
-	 * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
-	 */
-	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6
-					GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
-					GCLK_CLKCTRL_CLKEN ;
-
-	while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-	{
-	/* Wait for synchronization */
-	}
-
-	/* Reset */
-	USB->DEVICE.CTRLA.bit.SWRST = 1;
-	while (USB->DEVICE.SYNCBUSY.bit.SWRST) {
-		/* Sync wait */
-	}
-
-	udd_enable();
-
-	/* Load Pad Calibration */
-	pad_transn =( *((uint32_t *)(NVMCTRL_OTP4)  // Non-Volatile Memory Controller
-	+ (NVM_USB_PAD_TRANSN_POS / 32))
-	>> (NVM_USB_PAD_TRANSN_POS % 32))
-	& ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
-
-	if (pad_transn == 0x1F) {  // maximum value (31)
-		pad_transn = 5;
-	}
-
-	USB->DEVICE.PADCAL.bit.TRANSN = pad_transn;
-
-	pad_transp =( *((uint32_t *)(NVMCTRL_OTP4)
-	+ (NVM_USB_PAD_TRANSP_POS / 32))
-	>> (NVM_USB_PAD_TRANSP_POS % 32))
-	& ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
-
-	if (pad_transp == 0x1F) {  // maximum value (31)
-		pad_transp = 29;
-	}
-
-	USB->DEVICE.PADCAL.bit.TRANSP = pad_transp;
-
-	pad_trim =( *((uint32_t *)(NVMCTRL_OTP4)
-	+ (NVM_USB_PAD_TRIM_POS / 32))
-	>> (NVM_USB_PAD_TRIM_POS % 32))
-	& ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
-
-	if (pad_trim == 0x7) {  // maximum value (7)
-		pad_trim = 3;
-	}
-
-	USB->DEVICE.PADCAL.bit.TRIM = pad_trim;
-
-	/* Set the configuration */
-	udd_force_device_mode();
-	udd_device_run_in_standby();
-	// Set address of USB SRAM
-	USB->DEVICE.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
-	// For USB_SPEED_FULL
-	udd_force_full_speed();
-	memset(&usb_endpoint_table[0], 0, sizeof(usb_endpoint_table));
-
-	// Configure interrupts
-	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
-	NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
-}
-
-void UDD_Attach(void)
-{
-	TRACE_DEVICE(printf("=> UDD_Attach\r\n");)
-
-    // Authorize attach if Vbus is present
-	udd_attach_device();
-
-	// Enable USB line events
-	udd_enable_reset_interrupt();
-
-    // usefull for debug
-    udd_enable_sof_interrupt();
-}
-
-void UDD_Detach(void)
-{
-	TRACE_DEVICE(printf("=> UDD_Detach\r\n");)
-    udd_detach_device();
-}
-
-void send_zlp(void)
-{
-	/* Set the byte count as zero */
-	usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
-}
-
-
-void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
-{
-	TRACE_DEVICE(printf("=> UDD_InitEP : init EP %lu\r\n", (unsigned long)ul_ep_nb);)
-
-	if( ul_ep_cfg == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)) )
-	{
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(4);
-		/* Set maximum packet size as 8 bytes */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0;  // 8 bytes
-		/* Configure the data buffer */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[ul_ep_nb];
-	}
-	else if( ul_ep_cfg == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0)) )
-	{
-		/* Configure BULK OUT endpoint for CDC Data interface*/
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(3);
-		/* Set maximum packet size as 64 bytes */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.SIZE = 0x3;  // for 64 bytes
-		/* Configure the data buffer */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ul_ep_nb];
-
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 64;
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
-		// NACK if not ready
-		udd_OUT_transfer_allowed(ul_ep_nb);
-	}
-	else if( ul_ep_cfg == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)) )
-	{
-		/* Configure BULK IN endpoint for CDC Data interface */
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(3);
-		/* Set maximum packet size as 64 bytes */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0x3;  // for 64 bytes
-		/* Configure the data buffer */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[ul_ep_nb];
-		// NACK if not ready
-		udd_IN_stop_transfer(ul_ep_nb);
-	}
-	else if( ul_ep_cfg == USB_ENDPOINT_TYPE_CONTROL )
-	{
-		/* Configure CONTROL endpoint */
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1);
-		udd_OUT_stop_transfer(ul_ep_nb);
-		udd_IN_stop_transfer(ul_ep_nb);
-
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
-
-		/* Set maximum packet size as 64 bytes */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.SIZE = 0x3;  // for 64 bytes
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0x3;  // for 64 bytes
-
-		/* get endpoint configuration from setting register */
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[0];
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8;
-		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
-
-		// NACK if not ready
-		udd_OUT_stop_transfer(ul_ep_nb);
-		udd_IN_stop_transfer(ul_ep_nb);
-	}
-}
-
-
-// Send packet.
-void UDD_ClearIN(void)
-{
-	udd_IN_transfer_allowed(EP0);
-}
-
-
-
-uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
-{
-	memcpy(&udd_ep_in_cache_buffer[ep], data, len);
-
-	/* Get endpoint configuration from setting register */
-	usb_endpoint_table[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[ep];
-	usb_endpoint_table[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
-	usb_endpoint_table[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = len;
-
-	return len;
-}
-
-uint8_t UDD_Recv_data(uint32_t ep, uint32_t len)
-{
-	TRACE_DEVICE(printf("=> UDD_Recvdata : ep=%d\r\n", (char)ep);)
-
-	if (len>64) len=64;
-	usb_endpoint_table[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ep];
-	usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = len;
-	usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
-	udd_OUT_transfer_allowed(ep);
-	TRACE_DEVICE(printf("=> UDD_Recv_data : data=%lu\r\n", (unsigned long)data);)
-
-	/* Wait for transfer to complete */
-	while (!udd_is_OUT_transf_cplt(ep));
-	/* Clear Transfer complete 0 flag */
-	udd_clear_OUT_transf_cplt(ep);
-
-	return udd_ep_out_cache_buffer[ep][0];
-}
-
-void UDD_Recv(uint32_t ep, uint8_t** ppData)
-{
-	*ppData = udd_ep_out_cache_buffer[ep];
-}
-
-void UDD_Stall(uint32_t ep)
-{
-	uint8_t ep_num = ep;
-
-	// Stall endpoint
-	USB->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ(2);
-}
-
-uint32_t UDD_FifoByteCount(uint32_t ep)
-{
-	return ((uint16_t)(usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT));
-}
-
-void UDD_ReleaseRX(uint32_t ep)
-{
-	TRACE_DEVICE(puts("=> UDD_ReleaseRX\r\n");)
-	// The RAM Buffer is empty: we can receive data
-	udd_OUT_transfer_allowed(ep);
-	/* Clear Transfer complete 0 flag */
-	udd_clear_OUT_transf_cplt(ep);
-}
-
-void UDD_ReleaseTX(uint32_t ep)
-{
-	TRACE_DEVICE(printf("=> UDD_ReleaseTX ep=%lu\r\n", (unsigned long)ep);)
-	// The RAM Buffer is full: we can send data
-    udd_IN_transfer_allowed(ep);
- 	/* Clear the transfer complete flag  */
-    udd_clear_IN_transf_cplt(ep);
-}
-
-void UDD_SetAddress(uint32_t addr)
-{
-	TRACE_DEVICE(printf("=> UDD_SetAddress : setting address to %lu\r\n", (unsigned long)addr);)
-
-	/* Set the byte count as zero */
-	usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
- 	/* Clear the transfer complete flag  */
-    udd_clear_IN_transf_cplt(0);
-	/* Set the bank as ready */
-	udd_IN_transfer_allowed(0);
-
-	/* Wait for transfer to complete */
-	while (!udd_is_IN_transf_cplt(EP0)) {}
-
-	udd_configure_address(addr);
-}
-
-uint32_t UDD_GetFrameNumber(void)
-{
-	return udd_frame_number();
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* SAMD_SERIES */
-
diff --git a/cores/arduino/USB/samd21_device.h b/cores/arduino/USB/samd21_device.h
deleted file mode 100644
index deded25b..00000000
--- a/cores/arduino/USB/samd21_device.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-  Copyright (c) 2014 Arduino.  All right reserved.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef SAMD21_DEVICE_H_INCLUDED
-#define SAMD21_DEVICE_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define EP0				0
-#define EPX_SIZE		64// 64 for Full Speed, EPT size max is 1024
-
-// Force device low speed mode
-#define udd_force_low_speed()               USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_SPDCONF_Msk; USB->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_SPDCONF_1_Val
-// Force full speed mode
-#define udd_force_full_speed()              USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_SPDCONF_Msk
-
-// Attaches to USB bus
-#define udd_attach_device()                  USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH
-#define udd_detach_device()                  USB->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_DETACH
-
-// Manage reset event
-// Set when a USB "End of Reset" has been detected
-#define udd_enable_reset_interrupt()              USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_EORST
-#define udd_ack_reset()                           USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST
-#define Is_udd_reset()                            (USB->DEVICE.INTFLAG.reg & USB_DEVICE_INTFLAG_EORST)
-
-// Manage start of frame (SOF) event
-#define udd_enable_sof_interrupt()                USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF
-#define udd_ack_sof()                             USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF
-#define Is_udd_sof()                              (USB->DEVICE.INTENSET.reg & USB_DEVICE_INTENSET_SOF)
-#define udd_frame_number()                        ((USB->DEVICE.FNUM.reg & USB_DEVICE_FNUM_FNUM_Msk) >> USB_DEVICE_FNUM_FNUM_Pos)
-
-// configures the USB device address and enable it.
-#define udd_configure_address(address)            USB->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | address
-
-// Clear BK0RDY for know that the BANK0 ram buffer (udd_g_ep_table[ep].DeviceDescBank[0]) is empty and can receive data 
-#define udd_OUT_transfer_allowed(ep)              USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY
-// Set BK1RDY for know that the BANK1 ram buffer (udd_g_ep_table[ep].DeviceDescBank[1]) is full and can send data
-#define udd_IN_transfer_allowed(ep)               USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY
-
-// Stop OUT transfer
-#define udd_OUT_stop_transfer(ep)                 USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY
-// Stop IN transfer
-#define udd_IN_stop_transfer(ep)                  USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY
-
-#define udd_read_endpoint_flag(ep)                USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg
-// Is transfer completed ?
-#define udd_is_IN_transf_cplt(ep)                 (USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT(2))
-#define udd_is_OUT_transf_cplt(ep)                (USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT(1))
-// Clear the transfer complete flag
-#define udd_clear_IN_transf_cplt(ep)              USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(2)
-#define udd_clear_OUT_transf_cplt(ep)             USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(1)
-// Enable interrupt transfer complete
-#define udd_ept_enable_it_IN_transf_cplt(ep)      USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT(2)
-#define udd_ept_enable_it_OUT_transf_cplt(ep)     USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT(1)
-
-// Enables SETUP received interrupt
-#define udd_enable_setup_received_interrupt(ep)   USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTFLAG_RXSTP
-// Clear the stall flag
-#define udd_clear_stall_request(ep)			      USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2)
-// Remove stall
-#define udd_remove_stall_request(ep)		      USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ(2)
-
-// Endpoint Interrupt Summary
-#define udd_endpoint_interrupt()            USB->DEVICE.EPINTSMRY.reg
-
-#define udd_clear_wakeup_interrupt()        USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTENCLR_WAKEUP
-#define udd_clear_eorsm_interrupt()         USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTENCLR_EORSM
-#define udd_clear_suspend_interrupt()       USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTENCLR_SUSPEND
-
-
-
-// Force device mode
-#define udd_force_device_mode()             USB->DEVICE.CTRLA.reg &= ~USB_CTRLA_MODE
-// Run in Standby
-#define udd_device_run_in_standby()         USB->DEVICE.CTRLA.reg |= USB_CTRLA_RUNSTDBY
-// Force host mode
-#define udd_force_host_mode()               USB->DEVICE.CTRLA.reg |= USB_CTRLA_MODE
-
-
-// Enable USB macro
-#define udd_enable()                        USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE
-// Disable USB macro
-#define udd_disable()                       USB->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* SAMD21_DEVICE_H_INCLUDED */
-
diff --git a/cores/arduino/USB/samd21_host.c b/cores/arduino/USB/samd21_host.c
index 0ad32313..687cdcb0 100644
--- a/cores/arduino/USB/samd21_host.c
+++ b/cores/arduino/USB/samd21_host.c
@@ -1,20 +1,20 @@
-/*
-  Copyright (c) 2014 Arduino.  All right reserved.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
+/*
+  Copyright (c) 2014 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
 
 
 #include <stdio.h>
@@ -22,9 +22,11 @@
 #include <string.h>
 
 #include "../Arduino.h"
-#include "../wiring_private.h"
+#include "variant.h"
 #include "USB_host.h"
 #include "samd21_host.h"
+#include "sam.h"
+#include "wiring_digital.h"
 
 #define HOST_DEFINED
 #ifdef HOST_DEFINED
@@ -67,20 +69,20 @@ void UHD_Init(void)
 	uint32_t pad_trim;
 	uint32_t i;
 
-	UHD_SetStack(&UHD_Handler);
+	UHD_SetStack(&UHD_Handler);
 
 	/* Enable USB clock */
 	PM->APBBMASK.reg |= PM_APBBMASK_USB;
 
 	/* Set up the USB DP/DM pins */
-	pinPeripheral( PIN_USB_DM, PIO_COM );
-	pinPeripheral( PIN_USB_DP, PIO_COM );
-// 	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
-// 	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
-// 	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
-// 	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
-// 	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
-// 	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
+	pinPeripheral( PIN_USB_DM, PIO_COM );
+	pinPeripheral( PIN_USB_DP, PIO_COM );
+// 	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
+// 	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
+// 	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
+// 	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
+// 	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
+// 	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
 
 	/* ----------------------------------------------------------------------------------------------
 	* Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
@@ -102,9 +104,9 @@ void UHD_Init(void)
 	}
 
 	//  uhd_enable();
-	USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE | USB_CTRLA_MODE;
+	USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE | USB_CTRLA_MODE;
 	uhd_force_host_mode();
-	while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
+	while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
 
 	/* Load Pad Calibration */
 	pad_transn = (*((uint32_t *)(NVMCTRL_OTP4)       // Non-Volatile Memory Controller
@@ -183,8 +185,8 @@ void UHD_Handler(void)
 {
    uint16_t flags;
 
-	if (USB->HOST.CTRLA.bit.MODE) {
-		/*host mode ISR */
+	if (USB->HOST.CTRLA.bit.MODE) {
+		/*host mode ISR */
 
 		/* get interrupt flags */
 		flags = USB->HOST.INTFLAG.reg;
@@ -305,7 +307,7 @@ uhd_vbus_state_t UHD_GetVBUSState(void)
  */
 uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size)
 {
-	if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
+	if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
 		ul_ep_size = USB_PCKSIZE_SIZE_8_BYTES;  // Low Speed
 	else
 		ul_ep_size = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
@@ -356,7 +358,7 @@ uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_ty
       USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg  = USB_HOST_PSTATUSCLR_BK0RDY;
    }
 
-	if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
+	if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
 	   ul_maxsize = USB_PCKSIZE_SIZE_8_BYTES;  // Low Speed
 	else
 	   ul_maxsize = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
@@ -373,7 +375,7 @@ uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_ty
 
 void UHD_Pipe_CountZero(uint32_t ul_pipe)
 {
-	usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+	usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
 }
 
 /**
@@ -448,7 +450,7 @@ void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type)
    /* Start transfer */
 	if(ul_token_type == USB_HOST_PCFG_PTOKEN_SETUP )
 	{
-		USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TXSTP;
+		USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TXSTP;
 		USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
 	}
 	else if(ul_token_type == USB_HOST_PCFG_PTOKEN_IN )
diff --git a/cores/arduino/USB/samd21_host.h b/cores/arduino/USB/samd21_host.h
index 5e2e2c89..d2d9c9e0 100644
--- a/cores/arduino/USB/samd21_host.h
+++ b/cores/arduino/USB/samd21_host.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino LLC.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -28,18 +28,18 @@ extern __attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table
 #define  USB_EP_DIR_IN        0x80  // USB_SETUP_DEVICE_TO_HOST
 #define  USB_EP_DIR_OUT       0x00  // USB_SETUP_HOST_TO_DEVICE
 
-#define USB_HOST_PTYPE_DIS     USB_HOST_PCFG_PTYPE(0x0) // Pipe is disabled
-#define USB_HOST_PTYPE_CTRL    USB_HOST_PCFG_PTYPE(0x1) // Pipe is enabled and configured as CONTROL
-#define USB_HOST_PTYPE_ISO     USB_HOST_PCFG_PTYPE(0x2) // Pipe is enabled and configured as ISO
-#define USB_HOST_PTYPE_BULK    USB_HOST_PCFG_PTYPE(0x3) // Pipe is enabled and configured as BULK
-#define USB_HOST_PTYPE_INT     USB_HOST_PCFG_PTYPE(0x4) // Pipe is enabled and configured as INTERRUPT
-#define USB_HOST_PTYPE_EXT     USB_HOST_PCFG_PTYPE(0x5) // Pipe is enabled and configured as EXTENDED
+#define USB_HOST_PTYPE_DIS     USB_HOST_PCFG_PTYPE(0x0) // Pipe is disabled
+#define USB_HOST_PTYPE_CTRL    USB_HOST_PCFG_PTYPE(0x1) // Pipe is enabled and configured as CONTROL
+#define USB_HOST_PTYPE_ISO     USB_HOST_PCFG_PTYPE(0x2) // Pipe is enabled and configured as ISO
+#define USB_HOST_PTYPE_BULK    USB_HOST_PCFG_PTYPE(0x3) // Pipe is enabled and configured as BULK
+#define USB_HOST_PTYPE_INT     USB_HOST_PCFG_PTYPE(0x4) // Pipe is enabled and configured as INTERRUPT
+#define USB_HOST_PTYPE_EXT     USB_HOST_PCFG_PTYPE(0x5) // Pipe is enabled and configured as EXTENDED
 
 #define USB_HOST_NB_BK_1		1
 
-#define USB_HOST_PCFG_PTOKEN_SETUP  USB_HOST_PCFG_PTOKEN(0x0)
-#define USB_HOST_PCFG_PTOKEN_IN     USB_HOST_PCFG_PTOKEN(0x1)
-#define USB_HOST_PCFG_PTOKEN_OUT    USB_HOST_PCFG_PTOKEN(0x2)
+#define USB_HOST_PCFG_PTOKEN_SETUP  USB_HOST_PCFG_PTOKEN(0x0)
+#define USB_HOST_PCFG_PTOKEN_IN     USB_HOST_PCFG_PTOKEN(0x1)
+#define USB_HOST_PCFG_PTOKEN_OUT    USB_HOST_PCFG_PTOKEN(0x2)
 
 #define USB_ERRORFLOW	      USB_HOST_STATUS_BK_ERRORFLOW
 #define USB_ERRORTIMEOUT      USB_HOST_STATUS_PIPE_TOUTER
@@ -84,7 +84,7 @@ extern __attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table
 #define Is_uhd_sof()                                 (USB->HOST.INTFLAG.reg & USB_HOST_INTFLAG_HSOF)
 
 // USB address of pipes
-#define uhd_configure_address(pipe_num, addr) usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR = addr
+#define uhd_configure_address(pipe_num, addr) usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR = addr
 #define uhd_get_configured_address(pipe_num)  usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR
 
 // Pipes
@@ -104,7 +104,7 @@ extern __attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table
 #define uhd_ack_out_ready(p)                     USB->HOST.HostPipe[p].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT(1)
 #define Is_uhd_out_ready(p)                      ((USB->HOST.HostPipe[p].PINTFLAG.reg&USB_HOST_PINTFLAG_TRCPT(1)) == USB_HOST_PINTFLAG_TRCPT(1))
 #define uhd_ack_nak_received(p)                  usb_pipe_table[p].HostDescBank[1].STATUS_BK.reg &= ~USB_HOST_STATUS_BK_ERRORFLOW
-#define Is_uhd_nak_received(p)                   (usb_pipe_table[p].HostDescBank[1].STATUS_BK.reg & USB_HOST_STATUS_BK_ERRORFLOW)
+#define Is_uhd_nak_received(p)                   (usb_pipe_table[p].HostDescBank[1].STATUS_BK.reg & USB_HOST_STATUS_BK_ERRORFLOW)
 
 // Endpoint Interrupt Summary
 #define uhd_endpoint_interrupt()            USB->HOST.PINTSMRY.reg
-- 
GitLab