Index: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/USBCore.cpp
===================================================================
--- rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/USBCore.cpp	(revision 136)
+++ rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/USBCore.cpp	(revision 224)
@@ -1,60 +1,39 @@
-// Copyright (c) 2010, Peter Barrett
 /*
-** 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.
+  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
 */
+/*
+**Modified 04/04/2016 by Arduino.org development team
+*/
+
+#include <Arduino.h>
+
+#include "SAMD21_USBDevice.h"
+#include "USB_host.h"
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
-//#include "../Arduino.h"
-
-#include "sam.h"
-#include "wiring_constants.h"
-#include "USBCore.h"
-#include "USB/USB_device.h"   // needed for USB PID define
-#include "USBDesc.h"
-#include "USBAPI.h"
-
-#define TRACE_CORE(x)
-
-//==================================================================
-
-
-
-/*
-#if (defined CDC_ENABLED) && defined(HID_ENABLED)
-//#define USB_PID_ZERO       0x004B  // CDC and HID
-#define USB_PID_ZERO       0x804d  // CDC only
-#else
-#if (defined CDC_ENABLED)
-#define USB_PID_ZERO       0x804d  // CDC only  usbserial.name
-#else
-#define USB_PID_ZERO       0x804d  // HID only
-#endif
-#endif
-*/
-
-#define USB_PID_ZERO_PRO	0x804d
-
-// USB Device
-//#define USB_VID 			0x2a03 // arduino srl vid
-//#undef USB_PID
-//#define USB_PID            USB_PID_ZERO
-
-//==================================================================
+#include <limits.h>
+
+USBDevice_SAMD21G18x usbd;
 
 static char isRemoteWakeUpEnabled = 0;
 static char isEndpointHalt = 0;
+
+extern void (*gpf_isr)(void);
 
 
@@ -64,4 +43,6 @@
 };
 
+#define USB_PID_ZERO_PRO	0x804d
+#define USB_PRODUCT "Arduino M0 Pro"
 #ifndef USB_PRODUCT
 // Use a hardcoded product name if none is provided
@@ -88,6 +69,4 @@
 
 
-
-//	DEVICE DESCRIPTOR
 #if (defined CDC_ENABLED) && defined(HID_ENABLED)
 const DeviceDescriptor USB_DeviceDescriptor =
@@ -101,673 +80,771 @@
 #endif
 
+
 //==================================================================
 
 volatile uint32_t _usbConfiguration = 0;
-volatile uint32_t _usbInitialized = 0;
 volatile uint32_t _usbSetInterface = 0;
 
+static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0")))
+uint8_t udd_ep_out_cache_buffer[7][64];
+
+static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0")))
+uint8_t udd_ep_in_cache_buffer[7][64];
+
 //==================================================================
 
-
-//	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 || len < 0)
+bool _dry_run = false;
+bool _pack_message = false;
+uint16_t _pack_size = 0;
+uint8_t _pack_buffer[256];
+
+
+void packMessages(bool val)
+{
+	if (val) {
+		_pack_message = true;
+		_pack_size = 0;
+	} else {
+		_pack_message = false;
+		USBD_SendControl(_pack_buffer, _pack_size);
+	}
+}
+
+// Blocking Send of data to an endpoint
+uint32_t USBD_Send(uint32_t ep, const void *data, uint32_t len)
+{
+	uint32_t length = 0;
+
+	if (!_usbConfiguration)
 		return -1;
-
-	uint32_t n = UDD_FifoByteCount(ep);
-	len = min(n,len);
-	n = len;
-	uint8_t* dst = (uint8_t*)d;
-	while (n--)
-		*dst++ = UDD_Recv8(ep);
-	
-	
-	
-	
-	if (len && !UDD_FifoByteCount(ep)) // release empty buffer
-		UDD_ReleaseRX(ep);
-		
-  //----- Tx & Rx led blinking during transmission ----- begin ----	
-	PORT->Group[1].OUTTGL.reg =0x00000008 ;  //RxLED
-	for(int i=0; i < 100000; i++)
-	{
-		asm("NOP");
-	}
-	PORT->Group[1].OUTTGL.reg =0x00000008 ;	
-  //----- Tx & Rx led blinking during transmission ----- end ----
+	if (len > 16384)
+		return -1;
+
+	PORT->Group[0].OUTCLR.reg =0x08000000 ; //TxLED on
+	// Flash area
+	while (len != 0)
+	{
+		if (len >= 64) {
+			length = 64;
+		} else {
+			length = len;
+		}
+
+		/* memcopy could be safer in multi threaded environment */
+		memcpy(&udd_ep_in_cache_buffer[ep], data, length);
+
+		usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
+
+		usbd.epBank1SetByteCount(ep, length);
+
+		// Clear the transfer complete flag
+		usbd.epBank1AckTransferComplete(ep);
+
+		// RAM buffer is full, we can send data (IN)
+		usbd.epBank1SetReady(ep);
+
+		// Wait for transfer to complete
+		while (!usbd.epBank1IsTransferComplete(ep)) {
+			;  // need fire exit.
+		}
+		len -= length;
+		data = (char *)data + length;
+	}
 	return len;
 }
 
-//	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;
-}
-
-//	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_transf_cplt(ep);
-	/* Set the bank as ready */
-	udd_bk_rdy(ep);
-
-	/* Wait for transfer to complete */
-	while (! udd_is_transf_cplt(ep));  // need fire exit.
-	
-  //----- Tx & Rx led blinking during transmission ----- begin ----
-	PORT->Group[0].OUTTGL.reg =0x08000000 ; //TxLED
-	for(int i=0; i < 100000; i++)
-	{
-		asm("NOP");
-	}
-	PORT->Group[0].OUTTGL.reg =0x08000000 ;
-	/*for(int i=0; i < 100000; i++)
-	{
-		asm("NOP");
-	}*/
-  //----- Tx & Rx led blinking during transmission ----- end ----	
-	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 USBD_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);
+
+	return len;
+}
+
+uint32_t USBD_SendControl(const void* _data, uint32_t len)
+{
+	const uint8_t *data = reinterpret_cast<const uint8_t *>(_data);
 	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;
- 		}
+	if (_dry_run == true)
+		return length;
+
+	if (_pack_message == true) {
+		memcpy(&_pack_buffer[_pack_size], data, len);
+		_pack_size += len;
+		return length;
+	}
+
+ 	while (len > 0)
+ 	{
+		sent = USBD_armSend(EP0, data + pos, len);
+		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)
-{
-	uint16_t buff[64];
+bool USBD_SendStringDescriptor(const uint8_t *string, uint8_t maxlen)
+{
+	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);
-}
-
-uint32_t USBD_RecvControl(void* d, uint32_t len)
-{
-	udd_ack_out_received(0);
-
-	return len;
-}
-
-//	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 USBD_SendControl((uint8_t*)buff, l*2);
+}
+
+uint8_t USBD_SendInterfaces(uint32_t* total)
+{
+	uint8_t interfaces = 0;
+
+#if defined(CDC_ENABLED)
+	total[0] += CDC_GetInterface(&interfaces);
+#endif
+
+	return interfaces;
+}
+
+// Construct a dynamic configuration descriptor
+// This really needs dynamic endpoint allocation etc
+uint32_t USBD_SendConfiguration(uint32_t maxlen)
+{
+	uint32_t total = 0;
+	// Count and measure interfaces
+	_dry_run = true;
+	uint8_t interfaces = USBD_SendInterfaces(&total);
+
+	_Pragma("pack(1)")
+	ConfigDescriptor config = D_CONFIG((uint16_t)(total + sizeof(ConfigDescriptor)), interfaces);
+	_Pragma("pack()")
+
+	//	Now send them
+	_dry_run = false;
+
+	if (maxlen == sizeof(ConfigDescriptor)) {
+		USBD_SendControl(&config, sizeof(ConfigDescriptor));
 		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)
-{
-	uint8_t cache_buffer[128];
-	uint8_t i;
-
-	const uint8_t* interfaces;
-	uint32_t interfaces_length = 0;
-	uint8_t num_interfaces[1];
-	
-	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;
-	interfaces = (const uint8_t*) CDC_GetInterface();
-	interfaces_length += CDC_GetInterfaceLength();
-	if( maxlen > CDC_GetInterfaceLength()+ sizeof(ConfigDescriptor) )
-	{
-		maxlen = CDC_GetInterfaceLength()+ sizeof(ConfigDescriptor);
-	}
-#endif
-
-#ifdef HID_ENABLED
-    num_interfaces[0] += 1;
-	interfaces = (const uint8_t*) HID_GetInterface();
-	interfaces_length += HID_GetInterfaceLength();
-	if( 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]);
-_Pragma("pack()")
-
-	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];
-	}
-	interfaces = (const uint8_t*) HID_GetInterface();
-	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];
-	}
-#endif
-
-#ifdef CDC_ENABLED
-	for ( i=0; i<interfaces_length; i++)
-	{
-		cache_buffer[i+sizeof(ConfigDescriptor)] = interfaces[i];
-	}
-#endif	
-#endif
-
-	if (maxlen > sizeof(cache_buffer))
-	{
-		 maxlen = sizeof(cache_buffer);
-	}
-	USBD_SendControl(0,cache_buffer, maxlen );
+
+	total = 0;
+
+	packMessages(true);
+	USBD_SendControl(&config, sizeof(ConfigDescriptor));
+	USBD_SendInterfaces(&total);
+	packMessages(false);
+
 	return true;
 }
 
-static bool USBD_SendDescriptor(Setup* pSetup)
-{
-	uint8_t t = pSetup->wValueH;
+bool USBD_SendDescriptor(Setup &setup)
+{
+	uint8_t t = setup.wValueH;
 	uint8_t desc_length = 0;
-	const uint8_t* desc_addr = 0;
-
-	if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
-	{
-		TRACE_CORE(printf("=> USBD_SendDescriptor : USB_CONFIGURATION_DESCRIPTOR_TYPE length=%d\r\n", setup.wLength);)
-		return USBD_SendConfiguration(pSetup->wLength);
-	}
-
-#ifdef HID_ENABLED
-	if (HID_REPORT_DESCRIPTOR_TYPE == t)
-	{
-		TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");)
-		return HID_GetDescriptor();
-	}
-	if (HID_HID_DESCRIPTOR_TYPE == t)
-	{
-		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));
-	}
-#endif
-
-	if (USB_DEVICE_DESCRIPTOR_TYPE == t)
-	{
-		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;
-        }
+	bool _cdcComposite;
+	int ret;
+	const uint8_t *desc_addr = 0;
+
+	if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE)
+	{
+		return USBD_SendConfiguration(setup.wLength);
+	}
+
+	if (t == USB_DEVICE_DESCRIPTOR_TYPE)
+	{
+		if (setup.wLength == 8)
+			_cdcComposite = 1;
+
+		desc_addr = _cdcComposite ?  (const uint8_t*)&USB_DeviceDescriptor : (const uint8_t*)&USB_DeviceDescriptor;
+
+		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 (pSetup->wValueL == IMANUFACTURER) {
-			return USB_SendStringDescriptor(STRING_MANUFACTURER, pSetup->wLength);
+		else if (setup.wValueL == IPRODUCT) {
+			return USBD_SendStringDescriptor(STRING_PRODUCT, setup.wLength);
+		}
+		else if (setup.wValueL == IMANUFACTURER) {
+			return USBD_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength);
 		}
 		else {
 			return false;
 		}
-		if( *desc_addr > pSetup->wLength ) {
-			desc_length = pSetup->wLength;
-		}
-	}
-    else
-    {
-        TRACE_CORE(printf("Device ERROR");)
-    }
-
-	if (desc_addr == 0)
-	{
+		if (*desc_addr > setup.wLength) {
+			desc_length = setup.wLength;
+		}
+	}
+	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);
+	USBD_SendControl(desc_addr, desc_length);
 
 	return true;
 }
 
-
-void EndpointHandler(uint8_t bEndpoint)
-{
+void initEP(uint32_t ep, uint32_t config)
+{
+	if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)))
+	{
+		usbd.epBank1SetSize(ep, 64);
+		usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
+		usbd.epBank1SetType(ep, 4); // INTERRUPT IN
+	}
+	else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(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);
+	}
+	else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)))
+	{
+		usbd.epBank1SetSize(ep, 64);
+		usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
+
+		// NAK on endpoint IN, the bank is not yet filled in.
+		usbd.epBank1ResetReady(ep);
+
+		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[ep]);
+		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);
+	}
+}
+
+void sendZlp(uint32_t ep)
+{
+	// Set the byte count as zero
+	usbd.epBank1SetByteCount(ep, 0);
+}
+
+void 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
+}
+
+uint32_t EndPoints[] =
+{
+	USB_ENDPOINT_TYPE_CONTROL,
+
 #ifdef CDC_ENABLED
-	if( bEndpoint == CDC_ENDPOINT_OUT )
-	{
-		udd_ack_out_received(CDC_ENDPOINT_OUT);
-
-		// Handle received bytes		
+	USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0),           // CDC_ENDPOINT_ACM
+	USB_ENDPOINT_TYPE_BULK      | USB_ENDPOINT_OUT(0),               // CDC_ENDPOINT_OUT
+	USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0),                // CDC_ENDPOINT_IN
+#endif
+
+};
+
+void initEndpoints() {
+	for (uint8_t i = 1; i < sizeof(EndPoints) && EndPoints[i] != 0; i++) {
+		initEP(i, EndPoints[i]);
+	}
+}
+
+bool handleStandardSetup(Setup &setup)
+{
+	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 };
+			USBD_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;
+			USBD_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;
+			USBD_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 };
+			USBD_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;
+
+	case GET_DESCRIPTOR:
+		return USBD_SendDescriptor(setup);
+
+	case SET_DESCRIPTOR:
+		return false;
+
+	case GET_CONFIGURATION:
+		USBD_armSend(0, (void*)&_usbConfiguration, 1);
+		return true;
+
+	case SET_CONFIGURATION:
+		if (REQUEST_DEVICE == (setup.bmRequestType & REQUEST_RECIPIENT)) {
+
+			initEndpoints();
+			_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:
+		USBD_armSend(0, (void*)&_usbSetInterface, 1);
+		return true;
+
+	case SET_INTERFACE:
+		_usbSetInterface = setup.wValueL;
+		sendZlp(0);
+		return true;
+
+	default:
+		return true;
+	}
+}
+
+bool 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
+
+	return false;
+}
+
+void stall(uint32_t ep)
+{
+	// TODO: test
+	// TODO: use .bit. notation
+
+	// Stall endpoint
+	USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ(2);
+}
+
+void handleEndpoint(uint8_t ep)
+{
+#if defined(CDC_ENABLED)
+	if (ep == 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))
+			SerialUSB.accept();
+	}
+	if (ep == 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 (ep == 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
+
+}
+
+void ISRHandler()
+{
+
+	if (_pack_message == true) {
+		return;
+	}
+	// End-Of-Reset
+	if (usbd.isEndOfResetInterrupt())
+	{
+		// Configure EP 0
+		initEP(0, USB_ENDPOINT_TYPE_CONTROL);
+
+		// 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);
+		}
+
+		if (usbd.epBank1IsStalled(0))
 		{
-			SerialUSB.accept();
-		}
-	}
-	if( bEndpoint == CDC_ENDPOINT_IN )
-	{
-		udd_ack_in_received(CDC_ENDPOINT_IN);
-		/* Clear the transfer complete flag  */
-		udd_clear_transf_cplt(CDC_ENDPOINT_IN);
-		
-	}
-	if( bEndpoint == CDC_ENDPOINT_ACM )
-	{
-		udd_ack_in_received(CDC_ENDPOINT_ACM);
-		/* Clear the transfer complete flag  */
-		udd_clear_transf_cplt(CDC_ENDPOINT_ACM);
-	}
-#endif
-
-#ifdef HID_ENABLED
-	/* Nothing to do in our example */
-#endif
-}
-
-
-void USB_Handler(void)
-{
-	uint16_t flags;
-	uint8_t i;
-	uint8_t ept_int;
-
-	ept_int = udd_endpoint_interrupt();
+			usbd.epBank1AckStalled(0);
+
+			// Remove stall request
+			usbd.epBank1DisableStalled(0);
+		}
 	
-	/* Not endpoint interrupt */
-	if (0 == ept_int)
-	{
-		udd_clear_wakeup_interrupt();
-		udd_clear_eorsm_interrupt();
-		udd_clear_suspend_interrupt();
-
-		// End of bus reset
-		if (Is_udd_reset())
+	} // end Received Setup handler
+	PORT->Group[0].OUTSET.reg =0x08000000 ; //TxLED off
+	PORT->Group[1].OUTSET.reg =0x00000008 ; //RxLED off
+
+	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)
 		{
-			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();
-		}
-
-		if (Is_udd_sof())
-		{
-			udd_ack_sof();
-		}
-
-	}
-	else 
-	{
-		// Endpoint interrupt
-		flags = udd_read_endpoint_flag(0);
-
-		// endpoint received setup interrupt
-		if (flags & USB_DEVICE_EPINTFLAG_RXSTP)
-		{
-			Setup *pSetupData;
-
-			/* Clear the Received Setup flag */
-			udd_read_endpoint_flag(0) = USB_DEVICE_EPINTFLAG_RXSTP;
-
-			UDD_Recv(EP0, (uint8_t**)&pSetupData);
-
-			/* Clear the Bank 0 ready flag on Control OUT */
-			udd_ack_out_received(0);
-
-			bool ok = true;
-			if (REQUEST_STANDARD == (pSetupData->bmRequestType & REQUEST_TYPE))
+			// Endpoint Transfer Complete (0/1) Interrupt
+			if (usbd.epBank0IsTransferComplete(i) ||
+			    usbd.epBank1IsTransferComplete(i))
 			{
-				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)
-						
-						// Check if remote wake-up is enabled
-						
-						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
-
-#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;
-
-#ifdef CDC_ENABLED
-						// Enable interrupt for CDC reception from host (OUT packet)
-						udd_ept_enable_it_transf_cplt_in(CDC_ENDPOINT_ACM);
-						udd_ept_enable_it_transf_cplt_out(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();
-				}
+				handleEndpoint(i);
 			}
-			else
-			{
-				TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");)
-				ok =  USBD_ClassInterfaceRequest(*pSetupData);
-			}
-
-			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_STALL1 )
-			{
-				/* Clear the stall flag */
-				udd_clear_stall_request(0);
-
-				// Remove stall request
-				udd_remove_stall_request(0);
-			}
-		}  // end if USB_DEVICE_EPINTFLAG_RXSTP
-
-		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 )
-				
-				{
-					EndpointHandler(i);
-				}
-                ept_int &= ~(1 << i);
-                
-                if (ept_int != 0)
-				{
-                
-                    TRACE_CORE("\n\r  - ");
-                }
-            }
-            i++;
-			if( i> USB_EPT_NUM) break;  // exit
-        }
-	}
-}
-
+			ept_int &= ~(1 << i);
+		}
+		i++;
+		if (i > USB_EPT_NUM)
+			break;  // fire exit
+	}
+}
+
+// USB_Handler ISR
+extern "C" void UDD_Handler(void) {
+	ISRHandler();
+}
 
 
 void USBD_Flush(uint32_t ep)
 {
-	if (UDD_FifoByteCount(ep))
-	{
-		UDD_ReleaseTX(ep);
-	}
-}
-
-//	Counting frames
-uint32_t USBD_Connected(void)
-{
-	uint8_t f = UDD_GetFrameNumber();
-	return f != UDD_GetFrameNumber();
-}
-
-
-//=======================================================================
-//=======================================================================
-
-USBDevice_ USBDevice;
-
-USBDevice_::USBDevice_()
-{
+	if (USBD_Available(ep)) {
+		// RAM buffer is full, we can send data (IN)
+		usbd.epBank1SetReady(ep);
+
+	 	// Clear the transfer complete flag
+		usbd.epBank1AckTransferComplete(ep);
+	}
+}
+
+
+bool connected()
+{
+	// Count frame numbers
+	uint8_t f = USB->DEVICE.FNUM.bit.FNUM;
+	//delay(3);
+	return f != USB->DEVICE.FNUM.bit.FNUM;
+}
+
+uint8_t armRecvCtrlOUT(uint32_t ep)
+{
+	// 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(ep);
+
+	// Wait OUT
+	while (!usbd.epBank0IsReady(ep)) {}
+	while (!usbd.epBank0IsTransferComplete(ep)) {}
+	return usbd.epBank0ByteCount(ep);
+}
+
+
+uint32_t USBD_RecvControl(void *_data, uint32_t len)
+{
+	uint8_t *data = reinterpret_cast<uint8_t *>(_data);
+
+	// The RAM Buffer is empty: we can receive data
+	usbd.epBank0ResetReady(0);
+
+	//usbd.epBank0AckSetupReceived(0);
+	uint32_t read = armRecvCtrlOUT(0);
+	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 USBD_Available(uint32_t ep)
+{
+	return usbd.epBank0ByteCount(ep);
+}
+
+uint8_t armRecv(uint32_t ep)
+{
+	uint16_t count = usbd.epBank0ByteCount(ep);
+	if (count >= 64) {
+		usbd.epBank0SetByteCount(ep, count - 64);
+	} else {
+		usbd.epBank0SetByteCount(ep, 0);
+	}
+	return usbd.epBank0ByteCount(ep);
+}
+
+// Non Blocking receive
+// Return number of bytes read
+uint32_t USBD_Recv(uint32_t ep, void *_data, uint32_t len)
+{
+	if (!_usbConfiguration)
+		return -1;
+
+	PORT->Group[1].OUTCLR.reg =0x00000008 ; //RxLED on
+	if (USBD_Available(ep) < len)
+		len = USBD_Available(ep);
+
+	armRecv(ep);
+
+	usbd.epBank0DisableTransferComplete(ep);
+
+	memcpy(_data, udd_ep_out_cache_buffer[ep], len);
+
+	// release empty buffer
+	if (len && !USBD_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 USBD_Recv(uint32_t ep)
+{
+	uint8_t c;
+	if (USBD_Recv(ep, &c, 1) != 1) {
+		return -1;
+	} else {
+		return c;
+	}
+}
+
+
+
+//==================================================================
+
+void USBDevice_::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)
+		;
+
+	USB_SetHandler(&UDD_Handler);
+
+	// 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;
 }
 
 bool USBDevice_::attach()
 {
-  if (_usbInitialized != 0UL)
-  {
-    UDD_Attach();
+	if (!initialized)
+		return false;
+
+	usbd.attach();
+	usbd.enableEndOfResetInterrupt();
+	usbd.enableStartOfFrameInterrupt();
+
 	_usbConfiguration = 0;
 	return true;
-  }
-  else
-  {
-    return false;
-  }
-}
+}
+
 
 bool USBDevice_::detach()
 {
-	if (_usbInitialized != 0UL)
-	{
-		UDD_Detach();
-		return true;
-	}
-	else
-	{
+	if (!initialized)
 		return false;
-	}
+	usbd.detach();
+	return true;
 }
 
 bool USBDevice_::configured()
 {
-	return _usbConfiguration;
-}
-
-void USBDevice_::poll()
-{
-}
-
-void USBDevice_::init()
-{
-	UDD_Init();
-	_usbInitialized=1UL;
-}
+	return _usbConfiguration != 0;
+}
+
+
+	
+/*
+ * USB Device instance
+ * -------------------
+ */
+
+// USBDevice class instance
+USBDevice_ USBDevice;
