diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h
index 76df7ffe85ac5d932fbdf0ad581adb37d9d6af7c..7b6519b80a9d07e81c7bd17fc83c63dbf37a33c9 100644
--- a/cores/arduino/Arduino.h
+++ b/cores/arduino/Arduino.h
@@ -84,5 +84,6 @@ void loop( void ) ;
 #include "USB/USBDesc.h"
 #include "USB/USBCore.h"
 #include "USB/USBAPI.h"
+#include "USB/USB_host.h"
 
 #endif // Arduino_h
diff --git a/cores/arduino/USB/HID.cpp b/cores/arduino/USB/HID.cpp
index 6f7f5f5c043d0a0583a03a80ac2258d7908a4f4b..f5d561e0e7a941025dc7d411027a1eeebb4deca7 100644
--- a/cores/arduino/USB/HID.cpp
+++ b/cores/arduino/USB/HID.cpp
@@ -198,7 +198,7 @@ bool WEAK HID_Setup(Setup& setup)
 		if (HID_GET_IDLE == r)
 		{
 			UDD_Send(0, &_hid_idle, 1);
-			UDD_ReleaseIN();
+			UDD_ClearIN();
 			return true;
 		}
 	}
diff --git a/cores/arduino/USB/USBAPI.h b/cores/arduino/USB/USBAPI.h
index dbeefe11880012336d9030e8f573678fee9e3678..1229c3b7108ff1cb1f61bb0937a4a989ff6c06ca 100644
--- a/cores/arduino/USB/USBAPI.h
+++ b/cores/arduino/USB/USBAPI.h
@@ -19,6 +19,13 @@
 #ifndef __USBAPI__
 #define __USBAPI__
 
+#define HSTPIPCFG_PTYPE_BLK 1
+#define HSTPIPCFG_PTOKEN_IN 2
+#define HSTPIPCFG_PTOKEN_OUT 3
+#define HSTPIPCFG_PBK_1_BANK 4
+#define HSTPIPCFG_PTYPE_INTRPT 5
+
+
 
 /* Define attribute */
 #if defined   ( __CC_ARM   ) /* Keil uVision 4 */
diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp
index 7fc5a0fe913f7123df7145ba606f1ee1c88e8184..20fa0cea59986f2e3355294f82f5dd702b151576 100644
--- a/cores/arduino/USB/USBCore.cpp
+++ b/cores/arduino/USB/USBCore.cpp
@@ -113,7 +113,7 @@ uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len)
 	n = len;
 	uint8_t* dst = (uint8_t*)d;
 	while (n--)
-		*dst++ = UDD_Recv8(ep);
+		*dst++ = UDD_Recv_data(ep, 8);
 	if (len && !UDD_FifoByteCount(ep)) // release empty buffer
 		UDD_ReleaseRX(ep);
 
@@ -143,13 +143,13 @@ uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len)
     }
 	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.
+	/* 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;
 }
 
@@ -200,11 +200,11 @@ uint32_t USBD_RecvControl(void* d, uint32_t len)
 	if (read > len)
 		read = len;
 	UDD_Recv(EP0, &buffer);
-	UDD_WaitOUT();
+	while (!udd_is_OUT_transf_cplt(EP0));
 	for (int i=0; i<read; i++) {
 		data[i] = buffer[i];
 	}
-	UDD_ReleaseOUT();
+	udd_OUT_transfer_allowed(EP0);
 	return read;
 }
 
@@ -407,7 +407,7 @@ void EndpointHandler(uint8_t bEndpoint)
 #ifdef CDC_ENABLED
 	if( bEndpoint == CDC_ENDPOINT_OUT )
 	{
-		udd_ack_out_received(CDC_ENDPOINT_OUT);
+		udd_OUT_transfer_allowed(CDC_ENDPOINT_OUT);
 
 		// Handle received bytes
 		if (USBD_Available(CDC_ENDPOINT_OUT))
@@ -417,16 +417,16 @@ void EndpointHandler(uint8_t bEndpoint)
 	}
 	if( bEndpoint == CDC_ENDPOINT_IN )
 	{
-		udd_ack_in_received(CDC_ENDPOINT_IN);
-		/* Clear the transfer complete flag  */
-		udd_clear_transf_cplt(CDC_ENDPOINT_IN);
-
+		udd_IN_stop_transfer(CDC_ENDPOINT_IN);
+		/* Clear the transfer complete flag  */
+		udd_clear_IN_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);
+		udd_IN_stop_transfer(CDC_ENDPOINT_ACM);
+		/* Clear the transfer complete flag  */
+		udd_clear_IN_transf_cplt(CDC_ENDPOINT_ACM);
 	}
 #endif
 
@@ -436,7 +436,7 @@ void EndpointHandler(uint8_t bEndpoint)
 }
 
 
-void USB_Handler(void)
+void USB_ISR(void)
 {
 	uint16_t flags;
 	uint8_t i;
@@ -487,7 +487,7 @@ void USB_Handler(void)
 			UDD_Recv(EP0, (uint8_t**)&pSetupData);
 
 			/* Clear the Bank 0 ready flag on Control OUT */
-			udd_ack_out_received(0);
+			udd_OUT_transfer_allowed(0);
 
 			bool ok = true;
 			if (REQUEST_STANDARD == (pSetupData->bmRequestType & REQUEST_TYPE))
@@ -597,8 +597,8 @@ void USB_Handler(void)
 
 #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);
+						udd_ept_enable_it_IN_transf_cplt(CDC_ENDPOINT_ACM);
+						udd_ept_enable_it_OUT_transf_cplt(CDC_ENDPOINT_OUT);
 #endif
 						send_zlp();
 					}
@@ -629,7 +629,7 @@ void USB_Handler(void)
 			if (ok)
 			{
 				TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");)
-				UDD_ReleaseIN();
+				UDD_ClearIN();
 			}
 			else
 			{
@@ -688,7 +688,7 @@ uint32_t USBD_Connected(void)
 {
 	uint8_t f = UDD_GetFrameNumber();
 
-    //delay(3); JCB
+    //delay(3);
 
 	return f != UDD_GetFrameNumber();
 }
@@ -701,6 +701,7 @@ USBDevice_ USBDevice;
 
 USBDevice_::USBDevice_()
 {
+	UDD_SetStack(&USB_ISR);
 }
 
 bool USBDevice_::attach()
diff --git a/cores/arduino/USB/USB_device.h b/cores/arduino/USB/USB_device.h
index f7338fb701c17cf33147583325252b1b3baadd9a..6353f9770184e426a71f46b816c691ffaff65b4b 100644
--- a/cores/arduino/USB/USB_device.h
+++ b/cores/arduino/USB/USB_device.h
@@ -39,17 +39,13 @@ extern "C" {
 #define USB_ENDPOINT_TYPE_INTERRUPT            0x03
 
 
-extern void UDD_ReleaseIN(void);
-extern void UDD_ReleaseOUT(void);
-extern void UDD_WaitIN(void);
-extern void UDD_WaitOUT(void);
+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_Recv8(uint32_t ep);
-extern void UDD_Recv(uint32_t ep, uint8_t** data);
 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);
@@ -58,6 +54,7 @@ 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
 }
diff --git a/cores/arduino/USB/USB_host.h b/cores/arduino/USB/USB_host.h
index 20d2f599a819a7c6a39f1a20016fc1494f399573..e20738e85fd96ab35dae81f0bc0b5b64c80556c3 100644
--- a/cores/arduino/USB/USB_host.h
+++ b/cores/arduino/USB/USB_host.h
@@ -20,16 +20,16 @@
 #define USB_HOST_H_INCLUDED
 
 #include <stdint.h>
-
+#include "samd21_host.h"
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define tokSETUP		UOTGHS_HSTPIPCFG_PTOKEN_SETUP
-#define tokIN			UOTGHS_HSTPIPCFG_PTOKEN_IN
-#define tokOUT			UOTGHS_HSTPIPCFG_PTOKEN_OUT
-#define tokINHS			UOTGHS_HSTPIPCFG_PTOKEN_IN
-#define tokOUTHS		UOTGHS_HSTPIPCFG_PTOKEN_OUT
+#define tokSETUP		USB_HOST_PCFG_PTOKEN_SETUP
+#define tokIN			USB_HOST_PCFG_PTOKEN_IN
+#define tokOUT			USB_HOST_PCFG_PTOKEN_OUT
+#define tokINHS			USB_HOST_PCFG_PTOKEN_IN
+#define tokOUTHS		USB_HOST_PCFG_PTOKEN_OUT
 
 //! \brief Device speed
 /*typedef enum {
@@ -46,14 +46,13 @@ typedef enum {
 	UHD_STATE_ERROR = 3,
 } uhd_vbus_state_t;
 
-//extern uhd_speed_t uhd_get_speed(void);
-
-extern void UHD_SetStack(void (*pf_isr)(void));
 extern void UHD_Init(void);
-extern void UHD_BusReset(void);
+extern void UHD_Handler(void);
+extern void UHD_SetStack(void (*pf_isr)(void)); 
 extern uhd_vbus_state_t UHD_GetVBUSState(void);
 extern uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size);
 extern uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank);
+extern void UHD_Pipe_CountZero(uint32_t ul_pipe);
 extern void UHD_Pipe_Free(uint32_t ul_pipe);
 extern uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data);
 extern void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data);
diff --git a/cores/arduino/USB/USB_interrupt.c b/cores/arduino/USB/USB_interrupt.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f1f05f6ccd1ac231724bdd08591517cf43a0633
--- /dev/null
+++ b/cores/arduino/USB/USB_interrupt.c
@@ -0,0 +1,23 @@
+/*
+** 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
index e99e172d879603132f87e853fb54ffa0082110e6..cbc8351849ed994aa16a6de98e883487b6e3c977 100644
--- a/cores/arduino/USB/samd21_device.c
+++ b/cores/arduino/USB/samd21_device.c
@@ -48,6 +48,15 @@ __attribute__((__aligned__(4)))   __attribute__((__section__(".bss_hram0"))) uin
  */
  __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
@@ -198,7 +207,7 @@ void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
 		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
-	    USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
+		udd_OUT_transfer_allowed(ul_ep_nb);
 	}
 	else if( ul_ep_cfg == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)) )
 	{
@@ -209,14 +218,14 @@ void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
 		/* 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
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+		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);
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+		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;
@@ -231,32 +240,18 @@ void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
 		usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
 
 		// NACK if not ready
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
-		USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+		udd_OUT_stop_transfer(ul_ep_nb);
+		udd_IN_stop_transfer(ul_ep_nb);
 	}
 }
 
 
 // Send packet.
-void UDD_ReleaseIN(void)
-{
-	USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
-}
-
-void UDD_ReleaseOUT(void)
+void UDD_ClearIN(void)
 {
-	USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
+	udd_IN_transfer_allowed(EP0);
 }
 
-void UDD_WaitIN()
-{
-	while (!( USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY )) {}
-}
-
-void UDD_WaitOUT()
-{
-	while (!( USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK0RDY )) {}
-}
 
 
 uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
@@ -271,40 +266,22 @@ uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
 	return len;
 }
 
-uint8_t UDD_Recv8(uint32_t ep)
-{
-	TRACE_DEVICE(printf("=> UDD_Recv8 : ep=%d\r\n", (char)ep);)
-
-    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 = 8;
-	usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
-	USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
-	TRACE_DEVICE(printf("=> UDD_Recv8 : data=%lu\r\n", (unsigned long)data);)
-
+uint8_t UDD_Recv_data(uint32_t ep, uint32_t len)
+{
+	TRACE_DEVICE(printf("=> UDD_Recvdata : ep=%d\r\n", (char)ep);)
+
+	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 (!( USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0 ));
+	while (!udd_is_OUT_transf_cplt(ep));
 	/* Clear Transfer complete 0 flag */
-	USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0 = 1;
-
-	return udd_ep_out_cache_buffer[ep][0];
-}
-
-uint8_t UDD_Recv_data(uint32_t ep, uint32_t len)
-{
-	TRACE_DEVICE(printf("=> UDD_Recvdata : ep=%d\r\n", (char)ep);)
-
-	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;
-	USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
-	TRACE_DEVICE(printf("=> UDD_Recv8 : data=%lu\r\n", (unsigned long)data);)
-
-	/* Wait for transfer to complete */
-	while (!( USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0 ));
-	/* Clear Transfer complete 0 flag */
-	//USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0 = 1;
-
-	return udd_ep_out_cache_buffer[ep][0];
+	udd_clear_OUT_transf_cplt(ep);
+
+	return udd_ep_out_cache_buffer[ep][0];
 }
 
 void UDD_Recv(uint32_t ep, uint8_t** ppData)
@@ -328,15 +305,19 @@ uint32_t UDD_FifoByteCount(uint32_t ep)
 void UDD_ReleaseRX(uint32_t ep)
 {
 	TRACE_DEVICE(puts("=> UDD_ReleaseRX\r\n");)
-	USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
-    USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+	// 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);)
-    USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
-    USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+	// 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)
@@ -346,12 +327,12 @@ void UDD_SetAddress(uint32_t addr)
 	/* Set the byte count as zero */
 	usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
  	/* Clear the transfer complete flag  */
- 	USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 = 1;
+    udd_clear_IN_transf_cplt(0);
 	/* Set the bank as ready */
-	USB->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = 1;
+	udd_IN_transfer_allowed(0);
 
 	/* Wait for transfer to complete */
-	while (!( USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1 )) {}
+	while (!udd_is_IN_transf_cplt(EP0)) {}
 
 	udd_configure_address(addr);
 }
diff --git a/cores/arduino/USB/samd21_device.h b/cores/arduino/USB/samd21_device.h
index 8150fb174aa56d166d205f56af1f57de517a0b5c..db7b4d1eb9cf4dd6dfcafafdf48ddec7e213511a 100644
--- a/cores/arduino/USB/samd21_device.h
+++ b/cores/arduino/USB/samd21_device.h
@@ -50,22 +50,29 @@ extern "C" {
 // configures the USB device address and enable it.
 #define udd_configure_address(address)            USB->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | address
 
-// Enables SETUP received interrupt
-#define udd_enable_setup_received_interrupt(ep)   USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTFLAG_RXSTP
-// ACKs OUT received
-#define udd_ack_out_received(ep)                  USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY
-// ACKs OUT received
-#define udd_ack_in_received(ep)                   USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY
-// Is transfert completed ?
-#define udd_is_transf_cplt(ep)                   (USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1)
-// Clear the transfer complete flag
-#define udd_clear_transf_cplt(ep)                 USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT1 = 1
-// Set the bank as ready
-#define udd_bk_rdy(ep)                            USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.bit.BK1RDY = 1
+// 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_TRCPT1)
+#define udd_is_OUT_transf_cplt(ep)                (USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0)
+// Clear the transfer complete flag
+#define udd_clear_IN_transf_cplt(ep)              USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1
+#define udd_clear_OUT_transf_cplt(ep)             USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0
 // Enable interrupt transfer complete
-#define udd_ept_enable_it_transf_cplt_in(ep)      USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT1
-#define udd_ept_enable_it_transf_cplt_out(ep)     USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0
+#define udd_ept_enable_it_IN_transf_cplt(ep)      USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT1
+#define udd_ept_enable_it_OUT_transf_cplt(ep)     USB->DEVICE.DeviceEndpoint[ep].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0
+
+// 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_STALL1
 // Remove stall
diff --git a/cores/arduino/USB/samd21_host.c b/cores/arduino/USB/samd21_host.c
index 3255c0d294c81cb252cee36ae1ca0b05ee697b12..622569baf545de393583c8e11e95cfbea6876842 100644
--- a/cores/arduino/USB/samd21_host.c
+++ b/cores/arduino/USB/samd21_host.c
@@ -1,32 +1,33 @@
-/*
-  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.
+/*
+  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
+*/
 
-  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_host.h"
-// #include "USB/samd21_host.h"
-// #include "sam.h"
+#include <stdint.h>
+#include <string.h>
 
-//#if SAM3XA_SERIES
+#include "variant.h"
+#include "USB_host.h"
+#include "samd21_host.h"
+#include "sam.h"
+#include "wiring_digital.h"
 
+#define HOST_DEFINED
 #ifdef HOST_DEFINED
 
 //#define TRACE_UOTGHS_HOST(x)	x
@@ -37,19 +38,25 @@
 // Handle UOTGHS Host driver state
 static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
 
- __attribute__((__aligned__(4))) UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
+__attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
+
+extern void (*gpf_isr)(void);
 
+void UHD_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
+#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
+#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
+#define NVM_USB_PAD_TRIM_POS       55
+#define NVM_USB_PAD_TRIM_SIZE      3
 
 /**
  * \brief Initialize the SAMD21 host driver.
@@ -57,13 +64,16 @@ static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
 void UHD_Init(void)
 {
 	uint32_t pad_transn;
-    uint32_t pad_transp;
-    uint32_t pad_trim;
+	uint32_t pad_transp;
+	uint32_t pad_trim;
+	uint32_t i;
+
+	UHD_SetStack(&UHD_Handler);
 
 	/* Enable USB clock */
 	PM->APBBMASK.reg |= PM_APBBMASK_USB;
 
-	/* Set up the USB DP/DN pins */
+	/* Set up the USB DP/DM 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));
@@ -72,234 +82,171 @@ void UHD_Init(void)
 	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 ;
+	* 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 )
+	while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
 	{
-	/* Wait for synchronization */
+		/* Wait for synchronization */
 	}
 
 	/* Reset */
 	USB->HOST.CTRLA.bit.SWRST = 1;
-	while (USB->HOST.SYNCBUSY.bit.SWRST) {
+	while (USB->HOST.SYNCBUSY.bit.SWRST)
+	{
 		/* Sync wait */
 	}
 
-	udd_enable();
+	//  uhd_enable();
+	USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE | USB_CTRLA_MODE;
+	uhd_force_host_mode();
+	while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_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);
+	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)
+	if (pad_transn == 0x1F)         // maximum value (31)
+	{
 		pad_transn = 5;
 	}
 
 	USB->HOST.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);
+	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)
+	if (pad_transp == 0x1F)         // maximum value (31)
+	{
 		pad_transp = 29;
 	}
 
 	USB->HOST.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);
+	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)
+	if (pad_trim == 0x7)         // maximum value (7)
+	{
 		pad_trim = 3;
 	}
 
 	USB->HOST.PADCAL.bit.TRIM = pad_trim;
 
+
 	/* Set the configuration */
-	udd_force_host_mode();
-	udd_device_run_in_standby();
-    // Set address of USB SRAM
-	USB->HOST.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
+	uhd_run_in_standby();
+	// Set address of USB SRAM
+	USB->HOST.DESCADD.reg = (uint32_t)(&usb_pipe_table[0]);
 	// For USB_SPEED_FULL
-	udd_force_full_speed();
- 	for (uint32_t i = 0; i < sizeof(usb_endpoint_table); i++) {
- 		(*(uint32_t *)(&usb_endpoint_table[0]+i)) = 0;
- 	}
+	uhd_force_full_speed();
+	for (i = 0; i < sizeof(usb_pipe_table); i++)
+	{
+		(*(uint32_t *)(&usb_pipe_table[0] + i)) = 0;
+	}
 
 	uhd_state = UHD_STATE_NO_VBUS;
+	// Put VBUS on USB port
+	pinMode( 32, OUTPUT );
+	digitalWrite( 32, HIGH );
+
+	uhd_enable_connection_int();
+
+	USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DCONN;
+	USB->HOST.INTENSET.reg = USB_HOST_INTENSET_WAKEUP;
+	USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DDISC;
 
 	USB->HOST.CTRLB.bit.VBUSOK = 1;
 
 	// Configure interrupts
-	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
-	NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
+	NVIC_SetPriority((IRQn_Type)USB_IRQn, 0UL);
+	NVIC_EnableIRQ((IRQn_Type)USB_IRQn);
 }
 
-// /**
-//  * \brief Initialize the UOTGHS host driver.
-//  */
-// void UHD_Init(void)
-// {
-// //	irqflags_t flags;
-//
-// 	// To avoid USB interrupt before end of initialization
-// //	flags = cpu_irq_save();
-//
-// 	// Setup USB Host interrupt callback
-// //	UHD_SetStack(&UHD_ISR);
-//
-// 	// Enables the USB Clock
-// 	pmc_enable_upll_clock();
-// 	pmc_switch_udpck_to_upllck(0); // div=0+1
-// 	pmc_enable_udpck();
-// 	pmc_enable_periph_clk(ID_UOTGHS);
-//
-// 	// Always authorize asynchronous USB interrupts to exit of sleep mode
-// 	// For SAM3 USB wake up device except BACKUP mode
-// 	NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0);
-// 	NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
-//
-// 	// ID pin not used then force host mode
-// 	otg_disable_id_pin();
-// 	udd_force_host_mode();
-//
-// 	// Signal is active low (because all SAM3X Pins are high after startup)
-// 	// Hence VBOF must be low after connection request to power up the remote device
-// 	// uhd_set_vbof_active_low();
-//
-// 	// According to the Arduino Due circuit the VBOF must be active high to power up the remote device
-// 	uhd_set_vbof_active_high();
-//
-// 	otg_enable_pad();
-// 	otg_enable();
-//
-// 	otg_unfreeze_clock();
-//
-// 	// Check USB clock
-// 	while (!Is_otg_clock_usable())
-// 		;
-//
-// 	// Clear all interrupts that may have been set by a previous host mode
-// 	UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC | UOTGHS_HSTICR_DDISCIC
-// 			| UOTGHS_HSTICR_HSOFIC  | UOTGHS_HSTICR_HWUPIC
-// 			| UOTGHS_HSTICR_RSMEDIC | UOTGHS_HSTICR_RSTIC
-// 			| UOTGHS_HSTICR_RXRSMIC;
-//
-// 	otg_ack_vbus_transition();
-//
-// 	// Enable Vbus change and error interrupts
-// 	// Disable automatic Vbus control after Vbus error
-// 	Set_bits(UOTGHS->UOTGHS_CTRL,
-// 		UOTGHS_CTRL_VBUSHWC | UOTGHS_CTRL_VBUSTE | UOTGHS_CTRL_VBERRE);
-//
-// 	uhd_enable_vbus();
-//
-// 	// Force Vbus interrupt when Vbus is always high
-// 	// This is possible due to a short timing between a Host mode stop/start.
-// 	if (Is_otg_vbus_high())
-// 	{
-// 		otg_raise_vbus_transition();
-// 	}
-//
-// 	// Enable main control interrupt
-// 	// Connection, SOF and reset
-// 	UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTICR_DCONNIC;
-//
-// 	otg_freeze_clock();
-//
-// 	uhd_state = UHD_STATE_NO_VBUS;
-//
-// //	cpu_irq_restore(flags);
-// }
-
 
 /**
  * \brief Interrupt sub routine for USB Host state machine management.
  */
 //static void UHD_ISR(void)
-void USB_Handler(void)
+void UHD_Handler(void)
 {
-	uint16_t flags;
-	uint8_t i;
-	uint8_t ept_int;
+   uint16_t flags;
 
-	ept_int = udd_endpoint_interrupt();
-
-	/* Not endpoint interrupt */
-	if (0 == ept_int)
-	{
+	if (USB->HOST.CTRLA.bit.MODE) {
+		/*host mode ISR */
 
+		/* get interrupt flags */
+		flags = USB->HOST.INTFLAG.reg;
 
-	}
-	else
-	{
-		/* host interrupts */
-
-		/* get interrupt flags */
-		flags = USB->HOST.INTFLAG.reg;
-
-		/* host SOF interrupt */
-		if (flags & USB_HOST_INTFLAG_HSOF) {
-			/* clear the flag */
-			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF;
-			uhd_state = UHD_STATE_CONNECTED;
+		/* host SOF interrupt */
+		if (flags & USB_HOST_INTFLAG_HSOF)
+		{
+			/* clear the flag */
+			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF;
+			uhd_state             = UHD_STATE_CONNECTED;
 			return;
-		}
-
-		/* host reset interrupt */
-		if (flags & USB_HOST_INTFLAG_RST) {
-			/* clear the flag */
-			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST;
-			uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
+		}
+
+		/* host reset interrupt */
+		if (flags & USB_HOST_INTFLAG_RST)
+		{
+			/* clear the flag */
+			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST;
+			uhd_state             = UHD_STATE_DISCONNECTED;    //UHD_STATE_ERROR;
 			return;
-		}
-
-		/* host upstream resume interrupts */
-		if (flags & USB_HOST_INTFLAG_UPRSM) {
-			/* clear the flags */
-			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM;
-			uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
+		}
+
+		/* host upstream resume interrupts */
+		if (flags & USB_HOST_INTFLAG_UPRSM)
+		{
+			/* clear the flags */
+			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM;
+			uhd_state             = UHD_STATE_DISCONNECTED;    //UHD_STATE_ERROR;
 			return;
-		}
-
-		/* host downstream resume interrupts */
-		if (flags & USB_HOST_INTFLAG_DNRSM) {
-			/* clear the flags */
-			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM;
-			uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
+		}
+
+		/* host downstream resume interrupts */
+		if (flags & USB_HOST_INTFLAG_DNRSM)
+		{
+			/* clear the flags */
+			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM;
+			uhd_state             = UHD_STATE_DISCONNECTED;    //UHD_STATE_ERROR;
 			return;
-		}
-
-		/* host wakeup interrupts */
-		if (flags & USB_HOST_INTFLAG_WAKEUP) {
-			/* clear the flags */
-			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP;
-			uhd_state = UHD_STATE_CONNECTED; //UHD_STATE_ERROR;
+		}
+
+		/* host wakeup interrupts */
+		if (flags & USB_HOST_INTFLAG_WAKEUP)
+		{
+			/* clear the flags */
+			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP;
+			uhd_state             = UHD_STATE_CONNECTED;    //UHD_STATE_ERROR;
 			return;
-		}
-
-		/* host ram access interrupt  */
-		if (flags & USB_HOST_INTFLAG_RAMACER) {
-			/* clear the flag */
-			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER;
-			uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
+		}
+
+		/* host ram access interrupt  */
+		if (flags & USB_HOST_INTFLAG_RAMACER)
+		{
+			/* clear the flag */
+			USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER;
+			uhd_state             = UHD_STATE_DISCONNECTED;    //UHD_STATE_ERROR;
 			return;
-		}
-
-		/* host connect interrupt */
-		if (flags & USB_HOST_INTFLAG_DCONN) {
-			TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");)
-			/* clear the flag */
+		}
+
+		/* host connect interrupt */
+		if (flags & USB_HOST_INTFLAG_DCONN)
+		{
+			TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");
+							)
+			/* clear the flag */
 			uhd_ack_connection();
 			uhd_disable_connection_int();
 			uhd_ack_disconnection();
@@ -308,41 +255,32 @@ void USB_Handler(void)
 			uhd_state = UHD_STATE_CONNECTED;
 			return;
 		}
-
-		/* host disconnect interrupt 	*/
-		if (flags & USB_HOST_INTFLAG_DDISC) {
-			TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");)
-			/* clear the flag */
-			uhd_ack_disconnection();
+
+		/* host disconnect interrupt  */
+		if (flags & USB_HOST_INTFLAG_DDISC)
+		{
+			TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");
+							)
+			/* clear the flag */
+			uhd_ack_disconnection();
 			uhd_disable_disconnection_int();
 			// Stop reset signal, in case of disconnection during reset
 			uhd_stop_reset();
 			// Disable wakeup/resumes interrupts,
 			// in case of disconnection during suspend mode
-			//UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC
-			//		| UOTGHS_HSTIDR_RSMEDIEC
-			//		| UOTGHS_HSTIDR_RXRSMIEC;
 			uhd_ack_connection();
 			uhd_enable_connection_int();
 			uhd_state = UHD_STATE_DISCONNECTED;
 			return;
 		}
-
-	}
-
+	}
+	else {
+		while(1);
+	}
 }
 
 
 
-
-/**
- * \brief Trigger a USB bus reset.
- */
-void UHD_BusReset(void)
-{
-	USB->HOST.CTRLB.bit.BUSRESET = 1;;
-}
-
 /**
  * \brief Get VBUS state.
  *
@@ -350,11 +288,10 @@ void UHD_BusReset(void)
  */
 uhd_vbus_state_t UHD_GetVBUSState(void)
 {
-	return uhd_state;
+   return uhd_state;
 }
 
 
-
 /**
  * \brief Allocate FIFO for pipe 0.
  *
@@ -365,33 +302,20 @@ uhd_vbus_state_t UHD_GetVBUSState(void)
  * \retval 1 error.
  */
 uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size)
-{
-	struct usb_host_pipe_config cfg;
-
-	if (ep_size < 8)
-	{
-		return 0;
-	}
-
-	/* set pipe config */
-	USB->HOST.HostPipe[0].PCFG.bit.BK = 0;
-	USB->HOST.HostPipe[0].PCFG.bit.PTYPE = USB_HOST_PIPE_TYPE_CONTROL;
-	USB->HOST.HostPipe[0].BINTERVAL.reg = 0;
-	USB->HOST.HostPipe[0].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_SETUP;
-
-	memset((uint8_t *)&usb_pipe_table[pipe_num], 0, sizeof(usb_pipe_table[0]));
-	usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR = 0;
-	usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = 0;
-	usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.SIZE = 0x03;  // 64 bytes
-
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk;
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL | USB_HOST_PINTENSET_PERR;
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TXSTP;
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_STALL;
-
-	return 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
+
+	USB->HOST.HostPipe[0].PCFG.bit.PTYPE = 1; //USB_HOST_PCFG_PTYPE_CTRL;
+	usb_pipe_table[0].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = 0;
+	usb_pipe_table[0].HostDescBank[0].PCKSIZE.bit.SIZE = ul_ep_size;
+
+	return 0;
 }
 
+
 /**
  * \brief Allocate a new pipe.
  *
@@ -408,45 +332,48 @@ uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size)
  * \param ul_interval Polling interval (if applicable to pipe type).
  * \param ul_nb_bank Number of banks associated with this pipe.
  *
- * \return the newly allocated pipe number on success, 0 otherwise.
+ * \return 1.
  */
+uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank)
+{
+	/* set pipe config */
+	USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.BK    = ul_nb_bank;
+	// PTYPE:
+	USB->HOST.HostPipe[ul_dev_ep].PCFG.reg &= ~USB_HOST_PCFG_MASK;  // USB->HOST.HostPipe[0].PCFG.bit.PTYPE = 1; //USB_HOST_PCFG_PTYPE_CTRL;
+	USB->HOST.HostPipe[ul_dev_ep].PCFG.reg |= ul_type;
+	USB->HOST.HostPipe[ul_dev_ep].BINTERVAL.reg  = ul_interval;
+
+   if (ul_dir & USB_EP_DIR_IN)
+   {
+      USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_IN;
+      USB->HOST.HostPipe[ul_dev_ep].PSTATUSSET.reg  = USB_HOST_PSTATUSSET_BK0RDY;
+   }
+   else
+   {
+      USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_OUT;
+      USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg  = USB_HOST_PSTATUSCLR_BK0RDY;
+   }
+
+	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
 
-//		pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
+   memset((uint8_t *)&usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep]));
 
-uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank)
-//bool uhd_ep_alloc(usb_add_t add, usb_ep_desc_t *ep_desc)
-{
-	/* set pipe config */
-	USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.BK = ul_nb_bank;
-	USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTYPE = ul_type;
-	USB->HOST.HostPipe[ul_dev_ep].BINTERVAL.reg = ul_interval;
-
-	if (ul_dir & USB_EP_DIR_IN)
-	{
-		USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_IN;
-		USB->HOST.HostPipe[ul_dev_ep].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
-	}
-	else
-	{
-		USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_OUT;
-		USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg =  USB_HOST_PSTATUSCLR_BK0RDY;
-	}
-
-	memset((uint8_t *)&usb_descriptor_table.usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep]));
-
-	usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PDADDR = ul_dev_addr;
-	usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = ul_dev_ep;
-	usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].PCKSIZE.bit.SIZE = 0x03;  // 64 bytes
-
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk;
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL | USB_HOST_PINTENSET_PERR;
-//	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TXSTP;
-	USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_STALL;
-
-	return 1;
-}
+   usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PDADDR = ul_dev_addr;
+   usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = ul_dev_ep;
+   usb_pipe_table[ul_dev_ep].HostDescBank[0].PCKSIZE.bit.SIZE     = ul_maxsize;
+
+   return 1;
+}
 
 
+void UHD_Pipe_CountZero(uint32_t ul_pipe)
+{
+	usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+}
+
 /**
  * \brief Free a pipe.
  *
@@ -454,15 +381,11 @@ uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_ty
  */
 void UHD_Pipe_Free(uint32_t ul_pipe)
 {
-	// Unalloc pipe
-	uhd_disable_pipe(ul_pipe);
-	uhd_unallocate_memory(ul_pipe);
-	uhd_reset_pipe(ul_pipe);
-
-	// The Pipe is frozen and no additional requests will be sent to the device on this pipe address.
-	USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
+   // The Pipe is frozen and no additional requests will be sent to the device on this pipe address.
+   USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
 }
 
+
 /**
  * \brief Read from a pipe.
  *
@@ -472,28 +395,29 @@ void UHD_Pipe_Free(uint32_t ul_pipe)
  *
  * \return number of data read.
  */
-uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t* buf)
+uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t *buf)
 {
-	if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PIPE_TYPE_DISABLE)
-	{
-		return 0;
-	}
-
-	/* get pipe config from setting register */
-	usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
-	usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
-	usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
-	USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_IN;
-
-	/* Start transfer */
-	USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
-
-	// Unfreeze pipe
-	USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
+   if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PTYPE_DIS)
+   {
+      return 0;
+   }
+
+   /* get pipe config from setting register */
+   usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
+   usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT        = 0;
+   usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
+   USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_IN;
 
-	return buf_size;
+   /* Start transfer */
+   USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
+
+   // Unfreeze pipe
+   USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
+
+   return buf_size;
 }
 
+
 /**
  * \brief Write into a pipe.
  *
@@ -501,38 +425,12 @@ uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t* buf)
  * \param ul_size Maximum number of data to read.
  * \param data Buffer containing data to write.
  */
-void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data)
+void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t *buf)
 {
-
-	if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PIPE_TYPE_DISABLE)
-	{
-		return 0;
-	}
-
-	/* get pipe config from setting register */
-	usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
-	usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = buf_size;
-	usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
-	USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_OUT;
-
-
-	return 1;
-
-
-// 	volatile uint8_t *ptr_ep_data = 0;
-// 	uint32_t i = 0;
-//
-// 	// Check pipe
-// 	if (!Is_uhd_pipe_enabled(ul_pipe))
-// 	{
-// 		// Endpoint not valid
-// 		TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");)
-// 		return;
-// 	}
-//
-// 	ptr_ep_data = (volatile uint8_t *)&uhd_get_pipe_fifo_access(ul_pipe, 8);
-// 	for (i = 0; i < ul_size; ++i)
-// 		*ptr_ep_data++ = *data++;
+   /* get pipe config from setting register */
+   usb_pipe_table[ul_pipe].HostDescBank[0].ADDR.reg = (uint32_t)buf;
+   usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = ul_size;
+   usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
 }
 
 /**
@@ -543,36 +441,29 @@ void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data)
  */
 void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type)
 {
-	/* Start transfer */
-	USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
-
-	// Unfreeze pipe
-	USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
-
-// 	// Check pipe
-// 	if (!Is_uhd_pipe_enabled(ul_pipe))
-// 	{
-// 		// Endpoint not valid
-// 		TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe %lu is not enabled!\r\n", ul_pipe);)
-// 		return;
-// 	}
-//
-// 	// Set token type for zero length packet
-// 	// When actually using the FIFO, pipe token MUST be configured first
-// 	uhd_configure_pipe_token(ul_pipe, ul_token_type);
-//
-// 	// Clear interrupt flags
-// 	uhd_ack_setup_ready(ul_pipe);
-// 	uhd_ack_in_received(ul_pipe);
-// 	uhd_ack_out_ready(ul_pipe);
-// 	uhd_ack_short_packet(ul_pipe);
-// 	uhd_ack_nak_received(ul_pipe);
-//
-// 	// Send actual packet
-// 	uhd_ack_fifocon(ul_pipe);
-// 	uhd_unfreeze_pipe(ul_pipe);
+	USB->HOST.HostPipe[ul_pipe].PCFG.bit.PTOKEN = 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].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
+	}
+	else if(ul_token_type == USB_HOST_PCFG_PTOKEN_IN )
+	{
+		USB->HOST.HostPipe[ul_pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
+	}
+	else
+	{
+		USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT0;
+		USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
+	}
+   
+	// Unfreeze pipe
+    uhd_unfreeze_pipe(ul_pipe);
 }
 
+
 /**
  * \brief Check for pipe transfer completion.
  *
@@ -584,64 +475,40 @@ void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type)
  */
 uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
 {
-
-	// Freeze pipe
-	USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
-	switch(uhd_ctrl_request_phase) {
-		case UHD_CTRL_REQ_PHASE_DATA_IN:
-		_uhd_ctrl_phase_data_in(p_callback_para->transfered_size);
-		break;
-		case UHD_CTRL_REQ_PHASE_ZLP_IN:
-		_uhd_ctrl_request_end(UHD_TRANS_NOERROR);
-		break;
-		case UHD_CTRL_REQ_PHASE_DATA_OUT:
-		_uhd_ctrl_phase_data_out();
-		break;
-		case UHD_CTRL_REQ_PHASE_ZLP_OUT:
-		_uhd_ctrl_request_end(UHD_TRANS_NOERROR);
-		break;
-	}
-
-
-// 	// Check for transfer completion depending on token type
-// 	switch (ul_token_type)
-// 	{
-// 		case UOTGHS_HSTPIPCFG_PTOKEN_SETUP:
-// 			if (Is_uhd_setup_ready(ul_pipe))
-// 			{
-// 				uhd_freeze_pipe(ul_pipe);
-// 				uhd_ack_setup_ready(ul_pipe);
-// 				return 1;
-// 			}
-//
-// 		case UOTGHS_HSTPIPCFG_PTOKEN_IN:
-// 			if (Is_uhd_in_received(ul_pipe))
-// 			{
-// 				// In case of low USB speed and with a high CPU frequency,
-// 				// a ACK from host can be always running on USB line
-// 				// then wait end of ACK on IN pipe.
-// 				while(!Is_uhd_pipe_frozen(ul_pipe))
-// 					;
-//
-// 				// IN packet received
-// 				uhd_ack_in_received(ul_pipe);
-//
-// 				return 1;
-// 			}
-//
-// 		case UOTGHS_HSTPIPCFG_PTOKEN_OUT:
-// 			if (Is_uhd_out_ready(ul_pipe))
-// 			{
-// 				// OUT packet sent
-// 				uhd_freeze_pipe(ul_pipe);
-// 				uhd_ack_out_ready(ul_pipe);
-//
-// 				return 1;
-// 			}
-// 	}
-//
-	return 0;
+   // Check for transfer completion depending on token type
+   switch (ul_token_type)
+   {
+      case USB_HOST_PCFG_PTOKEN_SETUP:
+         if (Is_uhd_setup_ready(ul_pipe))
+         {
+            uhd_ack_setup_ready(ul_pipe);
+            uhd_freeze_pipe(ul_pipe);
+            return 1;
+         }
+		 break;
+
+      case USB_HOST_PCFG_PTOKEN_IN:
+         if (Is_uhd_in_received(ul_pipe))
+         {
+            // IN packet received
+            uhd_ack_in_received(ul_pipe);
+			// Freeze will stop after the transfer
+			uhd_freeze_pipe(ul_pipe);
+            return 1;
+         }
+		 break;
+ 
+      case USB_HOST_PCFG_PTOKEN_OUT:
+         if (Is_uhd_out_ready(ul_pipe))
+         {
+            // OUT packet sent
+            uhd_ack_out_ready(ul_pipe);
+            uhd_freeze_pipe(ul_pipe);
+            return 1;
+         }
+		 break;
+   }
+
+   return 0;
 }
-
-#endif /* SAM3XA_SERIES HOST_DEFINED */
-
+#endif //  HOST_DEFINED
diff --git a/cores/arduino/USB/samd21_host.h b/cores/arduino/USB/samd21_host.h
index 27f2a5b2496848c962ffe8645164f1023c53d808..04f93fc15316a9b6b44b819802b210f4924b7662 100644
--- a/cores/arduino/USB/samd21_host.h
+++ b/cores/arduino/USB/samd21_host.h
@@ -16,373 +16,114 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#ifndef UOTGHS_HOST_H_INCLUDED
-#define UOTGHS_HOST_H_INCLUDED
-
+#ifndef SAMD21_HOST_H_INCLUDED
+#define SAMD21_HOST_H_INCLUDED
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-//! \ingroup usb_host_group
-//! \defgroup uhd_group USB Host Driver (UHD)
-//! UOTGHS low-level driver for USB host mode
-//!
-//! @{
-
-//! @name UOTGHS Host IP properties
-//!
-//! @{
-//! Get maximal number of endpoints
-#define uhd_get_pipe_max_nbr()                (9)
-#define UOTGHS_EPT_NUM                        (uhd_get_pipe_max_nbr()+1)
-//! @}
-
-//! @name Host Vbus line control
-//!
-//! VBOF is an optional output pin which allows to enable or disable
-//! the external VBus generator.
-//!
-//! @{
-//! Enables hardware control of USB_VBOF output pin when a Vbus error occur
-#define uhd_enable_vbus_error_hw_control()    (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC))
-//! Disables hardware control of USB_VBOF output pin when a Vbus error occur
-#define uhd_disable_vbus_error_hw_control()   (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC))
-
-//! Pin and function for USB_VBOF according to configuration from USB_VBOF
-#define USB_VBOF_PIN            USB_VBOF_GPIO
-#define USB_VBOF_FUNCTION       USB_VBOF_FLAGS
-//! Output USB_VBOF onto its pin
-#define uhd_output_vbof_pin() do {\
-	pio_configure_pin(USB_VBOF_PIN, USB_VBOF_FUNCTION); \
-} while (0)
-
-//! Set USB_VBOF output pin polarity
-#define uhd_set_vbof_active_high()            (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO))
-#define uhd_set_vbof_active_low()             (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO))
-//! Requests VBus activation
-#define uhd_enable_vbus()                     (Set_bits(UOTGHS->UOTGHS_SFR, UOTGHS_SR_VBUSRQ))
-//! Requests VBus deactivation
-#define uhd_disable_vbus()                    (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SR_VBUSRQ))
-//! Tests if VBus activation has been requested
-#define Is_uhd_vbus_enabled()                 (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUSRQ))
-//! @}
-
-//! @name Host Vbus line monitoring
-//!
-//! The VBus level is always checked by USBC hardware.
-//!
-//! @{
-#define uhd_enable_vbus_error_interrupt()     (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
-#define uhd_disable_vbus_error_interrupt()    (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
-#define Is_uhd_vbus_error_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
-#define uhd_ack_vbus_error_interrupt()        (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SCR_VBERRIC))
-#define Is_uhd_vbus_error_interrupt()         (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBERRI))
-//! @}
-
-#define uhd_ack_errors_interrupt()            (UOTGHS->UOTGHS_SCR = (UOTGHS_SCR_VBERRIC|UOTGHS_SCR_BCERRIC|UOTGHS_SCR_HNPERRIC|UOTGHS_SCR_STOIC))
-#define Is_uhd_errors_interrupt()             (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE|UOTGHS_CTRL_BCERRE|UOTGHS_CTRL_HNPERRE|UOTGHS_CTRL_STOE))
-#define uhd_enable_suspend_error_interrupt()
-#define uhd_enable_hnp_error_interrupt()
-#define uhd_enable_bconn_error_interrupt()
-
-//! @name USB device connection/disconnection monitoring
-//! @{
-#define uhd_enable_connection_int()           (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DCONNIES)
-#define uhd_disable_connection_int()          (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DCONNIEC)
-#define Is_uhd_connection_int_enabled()       (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DCONNIE))
-#define uhd_ack_connection()                  (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC)
-#define Is_uhd_connection()                   (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DCONNI))
-
-#define uhd_enable_disconnection_int()        (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DDISCIES)
-#define uhd_disable_disconnection_int()       (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DDISCIEC)
-#define Is_uhd_disconnection_int_enabled()    (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DDISCIE))
-#define uhd_ack_disconnection()               (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DDISCIC)
-#define Is_uhd_disconnection()                (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DDISCI))
-//! @}
-
-//! @name USB device speed control
-//! @{
-#define uhd_get_speed_mode()                  (Rd_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_SPEED_Msk))
-#define Is_uhd_low_speed_mode()                 (uhd_get_speed_mode() == UOTGHS_SR_SPEED_LOW_SPEED)
-#define Is_uhd_full_speed_mode()                (uhd_get_speed_mode() == UOTGHS_SR_SPEED_FULL_SPEED)
-#define Is_uhd_high_speed_mode()                (uhd_get_speed_mode() == UOTGHS_SR_SPEED_HIGH_SPEED)
-//! Enable high speed mode
-# define uhd_enable_high_speed_mode()        (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_HIGH_SPEED))
-//! Disable high speed mode
-# define uhd_disable_high_speed_mode()       (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_FORCED_FS))
-//! @}
-
-//! @name Bus events control
-//! These macros manage the bus events: reset, SOF, resume, wakeup.
-//! @{
-
-//! Initiates a reset event
-//! @{
-#define uhd_start_reset()                            (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
-#define Is_uhd_starting_reset()                      (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
-#define uhd_stop_reset()                             (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
-
-#define uhd_enable_reset_sent_interrupt()            (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSTIES)
-#define uhd_disable_reset_sent_interrupt()           (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSTIEC)
-#define Is_uhd_reset_sent_interrupt_enabled()        (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSTIE))
-#define uhd_ack_reset_sent()                         (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSTIC)
-#define Is_uhd_reset_sent()                          (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSTI))
-//! @}
-
-//! Initiates a SOF events
-//! @{
-#define uhd_enable_sof()                             (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
-#define uhd_disable_sof()                            (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
-#define Is_uhd_sof_enabled()                         (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
-#define uhd_get_sof_number()                         ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_FNUM_Msk)>>UOTGHS_HSTFNUM_FNUM_Pos)
-#define uhd_get_microsof_number()                    ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_MFNUM_Msk)>>UOTGHS_HSTFNUM_MFNUM_Pos)
-#define uhd_get_frame_position()                     (Rd_bits(UOTGHS->UOTGHS_HSTFNUM, UOTGHS_HSTFNUM_FLENHIGH_Msk))
-#define uhd_enable_sof_interrupt()                   (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HSOFIES)
-#define uhd_disable_sof_interrupt()                  (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HSOFIEC)
-#define Is_uhd_sof_interrupt_enabled()               (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HSOFIE))
-#define uhd_ack_sof()                                (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HSOFIC)
-#define Is_uhd_sof()                                 (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HSOFI))
-//! @}
-
-//! Initiates a resume event
-//! It is called downstream resume event.
-//! @{
-#define uhd_send_resume()                            (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME))
-#define Is_uhd_sending_resume()                      (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME))
-
-#define uhd_enable_downstream_resume_interrupt()     (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSMEDIES)
-#define uhd_disable_downstream_resume_interrupt()    (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSMEDIEC)
-#define Is_uhd_downstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSMEDIE))
-#define uhd_ack_downstream_resume()                  (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSMEDIC)
-#define Is_uhd_downstream_resume()                   (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSMEDI))
-//! @}
-
-//! Detection of a wake-up event
-//! A wake-up event is received when the host controller is in the suspend mode:
-//! - and an upstream resume from the peripheral is detected.
-//! - and a peripheral disconnection is detected.
-//! @{
-#define uhd_enable_wakeup_interrupt()                (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HWUPIES)
-#define uhd_disable_wakeup_interrupt()               (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC)
-#define Is_uhd_wakeup_interrupt_enabled()            (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HWUPIE))
-#define uhd_ack_wakeup()                             (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HWUPIC)
-#define Is_uhd_wakeup()                              (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HWUPI))
-
-#define uhd_enable_upstream_resume_interrupt()       (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RXRSMIES)
-#define uhd_disable_upstream_resume_interrupt()      (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RXRSMIEC)
-#define Is_uhd_upstream_resume_interrupt_enabled()   (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RXRSMIE))
-#define uhd_ack_upstream_resume()                    (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RXRSMIC)
-#define Is_uhd_upstream_resume()                     (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RXRSMI))
-//! @}
-//! @}
-
-
-//! @name Pipes management
-//! @{
-
-//! USB address of pipes
-//! @{
-#define uhd_configure_address(p, addr) \
-		(Wr_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \
-		UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3), addr))
-#define uhd_get_configured_address(p) \
-		(Rd_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \
-		UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3)))
-//! @}
-
-//! Pipe enable
-//! Enable, disable, reset, freeze
-//! @{
-#define uhd_enable_pipe(p) \
-		(Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
-#define uhd_disable_pipe(p) \
-		(Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
-#define Is_uhd_pipe_enabled(p) \
-		(Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
-#define uhd_reset_pipe(p) \
-		(Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))); \
-		(Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
-#define Is_uhd_resetting_pipe(p) \
-		(Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
-#define uhd_freeze_pipe(p)                       (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PFREEZES)
-#define uhd_unfreeze_pipe(p)                     (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PFREEZEC)
-#define Is_uhd_pipe_frozen(p)                    (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PFREEZE))
-#define uhd_reset_data_toggle(p)                 (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RSTDTS)
-#define Is_uhd_data_toggle_reset(p)              (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RSTDT))
-//! @}
-
-//! Pipe configuration
-//! @{
-#define uhd_configure_pipe_int_req_freq(p,freq)  (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk, (freq)))
-#define uhd_get_pipe_int_req_freq(p)             (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk))
-#define uhd_configure_pipe_endpoint_number(p,ep) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PEPNUM_Msk, (ep)))
-#define uhd_get_pipe_endpoint_address(p) \
-		(uhd_is_pipe_in(p) ?\
-			(uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_IN) :\
-			(uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_OUT))
-#define uhd_get_pipe_endpoint_number(p)          (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PEPNUM_Msk)))
-#define uhd_configure_pipe_type(p, type)         (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk, type))
-#define uhd_get_pipe_type(p)                     (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk))
-#define uhd_enable_pipe_bank_autoswitch(p)       (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
-#define uhd_disable_pipe_bank_autoswitch(p)      (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
-#define Is_uhd_pipe_bank_autoswitch_enabled(p)   (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
-#define uhd_configure_pipe_token(p, token)       (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk, token))
-#define uhd_get_pipe_token(p)                    (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk))
-#define uhd_is_pipe_in(p)                        (UOTGHS_HSTPIPCFG_PTOKEN_IN==uhd_get_pipe_token(p))
-#define uhd_is_pipe_out(p)                       (UOTGHS_HSTPIPCFG_PTOKEN_OUT==uhd_get_pipe_token(p))
-//! Bounds given integer size to allowed range and rounds it up to the nearest
-//! available greater size, then applies register format of UOTGHS controller
-//! for pipe size bit-field.
-#define uhd_format_pipe_size(size) \
-		(32 - clz(((uint32_t)min(max(size, 8), 1024) << 1) - 1) - 1 - 3)
-#define uhd_configure_pipe_size(p,size) \
-		(Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PSIZE_Msk, uhd_format_pipe_size(size)))
-#define uhd_get_pipe_size(p)                     (8<<((Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PSIZE_Msk)))>> UOTGHS_HSTPIPCFG_PSIZE_Pos))
-#define uhd_configure_pipe_bank(p,bank)          (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk, (bank)))
-#define uhd_get_pipe_bank(p)                     (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk))
-#define uhd_allocate_memory(p)                   (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
-#define uhd_unallocate_memory(p)                 (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
-#define Is_uhd_memory_allocated(p)               (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
-
-//! Enable PING management only available in HS mode
-#  define uhd_enable_ping(p)                     (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PINGEN))
-//#endif
-#define uhd_configure_pipe(p, freq, ep_num, type, token, size, bank, bank_switch) \
-	(UOTGHS->UOTGHS_HSTPIPCFG[p] = \
-		(bank)|\
-		((uhd_format_pipe_size(size)<<UOTGHS_HSTPIPCFG_PSIZE_Pos)&UOTGHS_HSTPIPCFG_PSIZE_Msk)|\
-		((token)&UOTGHS_HSTPIPCFG_PTOKEN_Msk)|\
-		((type)&UOTGHS_HSTPIPCFG_PTYPE_Msk)|\
-		(((ep_num)<<UOTGHS_HSTPIPCFG_PEPNUM_Pos)&UOTGHS_HSTPIPCFG_PEPNUM_Msk)|\
-		bank_switch |\
-		(((freq)<<UOTGHS_HSTPIPCFG_INTFRQ_Pos)&UOTGHS_HSTPIPCFG_INTFRQ_Msk))
-
-#define Is_uhd_pipe_configured(p)                (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CFGOK))
-//! @}
-
-//! Pipe main interrupts management
-//! @{
-#define uhd_enable_pipe_interrupt(p) 		(UOTGHS->UOTGHS_HSTIER = (UOTGHS_HSTIER_PEP_0 << (p)))
-#define uhd_disable_pipe_interrupt(p) 		(UOTGHS->UOTGHS_HSTIDR = (UOTGHS_HSTIDR_PEP_0 << (p)))
-#define Is_uhd_pipe_interrupt_enabled(p) 	(Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_PEP_0 << (p)))
-#define Is_uhd_pipe_interrupt(p) 		(Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_PEP_0 << (p)))
-//! returns the lowest pipe number generating a pipe interrupt or UOTGHS_EPT_NUM if none
-#define uhd_get_interrupt_pipe_number() \
-	(ctz(((UOTGHS->UOTGHS_HSTISR >> 8) & (UOTGHS->UOTGHS_HSTIMR >> 8)) | (1 << UOTGHS_EPT_NUM)))
-//! @}
-
-//! Pipe overflow and underflow for isochronous and interrupt endpoints
-//! @{
-#define uhd_enable_overflow_interrupt(p)         (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_OVERFIES)
-#define uhd_disable_overflow_interrupt(p)        (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_OVERFIEC)
-#define Is_uhd_overflow_interrupt_enabled(p)     (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_OVERFIE))
-#define uhd_ack_overflow_interrupt(p)            (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_OVERFIC)
-#define Is_uhd_overflow(p)                       (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_OVERFI))
-
-#define uhd_enable_underflow_interrupt(p)        (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_UNDERFIES)
-#define uhd_disable_underflow_interrupt(p)       (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_UNDERFIEC)
-#define Is_uhd_underflow_interrupt_enabled(p)    (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_UNDERFIE))
-#define uhd_ack_underflow_interrupt(p)           (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_UNDERFIC)
-#define Is_uhd_underflow(p)                      (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_UNDERFI))
-//! @}
-
-//! USB packet errors management
-//! @{
-#define uhd_enable_stall_interrupt(p)            (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXSTALLDES)
-#define uhd_disable_stall_interrupt(p)           (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXSTALLDEC)
-#define Is_uhd_stall_interrupt_enabled(p)        (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXSTALLDE))
-#define uhd_ack_stall(p)                         (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXSTALLDIC)
-#define Is_uhd_stall(p)                          (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXSTALLDI))
-
-#define uhd_enable_pipe_error_interrupt(p)       (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PERRES)
-#define uhd_disable_pipe_error_interrupt(p)      (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PERREC)
-#define Is_uhd_pipe_error_interrupt_enabled(p)   (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PERRE))
-#define uhd_ack_all_errors(p)                    (UOTGHS->UOTGHS_HSTPIPERR[p] = 0UL)
-#define Is_uhd_pipe_error(p)                     (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PERRI))
-#define uhd_error_status(p)                      (UOTGHS->UOTGHS_HSTPIPERR[p])
-#define Is_uhd_bad_data_toggle(p)                (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATATGL))
-#define Is_uhd_data_pid_error(p)                 (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATAPID))
-#define Is_uhd_pid_error(p)                      (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_PID))
-#define Is_uhd_timeout_error(p)                  (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_TIMEOUT))
-#define Is_uhd_crc16_error(p)                    (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_CRC16))
-#define uhd_get_error_counter(p)                 (Rd_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_COUNTER))
-//! @}
-
-//! Pipe data management
-//! @{
-#define uhd_data_toggle(p)                       (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_DTSEQ))
-
-#define uhd_enable_bank_interrupt(p)             (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NBUSYBKES)
-#define uhd_disable_bank_interrupt(p)            (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NBUSYBKEC)
-#define Is_uhd_bank_interrupt_enabled(p)         (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NBUSYBKE))
-#define uhd_nb_busy_bank(p)                      (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NBUSYBK_Msk))
-#define uhd_current_bank(p)                      (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CURRBK_Msk ))
-
-#define uhd_enable_short_packet_interrupt(p)     (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_SHORTPACKETES)
-#define uhd_disable_short_packet_interrupt(p)    (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_SHORTPACKETIEC)
-#define Is_uhd_short_packet_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_SHORTPACKETIE))  )
-#define uhd_ack_short_packet(p)                  (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_SHORTPACKETIC)
-#define Is_uhd_short_packet(p)                   (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_SHORTPACKETI))
-#define uhd_byte_count(p)                        (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PBYCT_Msk))
-
-#define Is_uhd_fifocon(p)                        (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_FIFOCON))
-#define uhd_ack_fifocon(p)                       (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_FIFOCONC)
-
-#define uhd_enable_setup_ready_interrupt(p)      (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXSTPES)
-#define uhd_disable_setup_ready_interrupt(p)     (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXSTPEC)
-#define Is_uhd_setup_ready_interrupt_enabled(p)  (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXSTPE))
-#define uhd_ack_setup_ready(p)                   (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXSTPIC)
-#define Is_uhd_setup_ready(p)                    (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXSTPI))
-
-#define uhd_enable_in_received_interrupt(p)      (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXINES)
-#define uhd_disable_in_received_interrupt(p)     (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXINEC)
-#define Is_uhd_in_received_interrupt_enabled(p)  (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXINE))
-#define uhd_ack_in_received(p)                   (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXINIC)
-#define Is_uhd_in_received(p)                    (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXINI))
-
-#define uhd_enable_out_ready_interrupt(p)        (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXOUTES)
-#define uhd_disable_out_ready_interrupt(p)       (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXOUTEC)
-#define Is_uhd_out_ready_interrupt_enabled(p)    (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXOUTE))
-#define uhd_ack_out_ready(p)                     (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXOUTIC)
-#define Is_uhd_out_ready(p)                      (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXOUTI))
-#define uhd_raise_out_ready(p)                   (UOTGHS->UOTGHS_HSTPIPIFR[p] = UOTGHS_HSTPIPIFR_TXOUTIS)
-
-#define uhd_enable_nak_received_interrupt(p)     (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NAKEDES)
-#define uhd_disable_nak_received_interrupt(p)    (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NAKEDEC)
-#define Is_uhd_nak_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NAKEDE))
-#define uhd_ack_nak_received(p)                  (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_NAKEDIC)
-#define Is_uhd_nak_received(p)                   (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NAKEDI))
-
-#define Is_uhd_read_enabled(p)                   (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL))
-#define Is_uhd_write_enabled(p)                  (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL ))
-
-#define uhd_enable_continuous_in_mode(p)         (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
-#define uhd_disable_continuous_in_mode(p)        (Clr_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
-#define Is_uhd_continuous_in_mode_enabled(p)     (Tst_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
-
-#define uhd_in_request_number(p, in_num)         (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], (in_num)-1))
-#define uhd_get_in_request_number(p)             (((Rd_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INRQ_Msk))>>UOTGHS_HSTPIPINRQ_INRQ_Pos)+1)
-//! @}
-
-//! Maximum transfer size on USB DMA
-#define UHD_PIPE_MAX_TRANS 0x8000
-
-//! Get 64-, 32-, 16- or 8-bit access to FIFO data register of selected pipe.
-//! @param p      Target Pipe number
-//! @param scale  Data scale in bits: 64, 32, 16 or 8
-//! @return       Volatile 64-, 32-, 16- or 8-bit data pointer to FIFO data register
-//! @warning It is up to the user of this macro to make sure that all accesses
-//! are aligned with their natural boundaries except 64-bit accesses which
-//! require only 32-bit alignment.
-//! @warning It is up to the user of this macro to make sure that used HSB
-//! addresses are identical to the DPRAM internal pointer modulo 32 bits.
-#define uhd_get_pipe_fifo_access(p, scale) \
-	(((volatile TPASTE2(U, scale) (*)[UHD_PIPE_MAX_TRANS / ((scale) / 8)])UOTGHS_RAM_ADDR)[(p)])
-
+extern __attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
+
+#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_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_ERRORFLOW	      USB_HOST_STATUS_BK_ERRORFLOW
+#define USB_ERRORTIMEOUT      USB_HOST_STATUS_PIPE_TOUTER
+#define USB_ERROR_DATATOGGLE  USB_HOST_STATUS_PIPE_DTGLER
+
+#define USB_PCKSIZE_SIZE_8_BYTES        0
+#define USB_PCKSIZE_SIZE_16_BYTES       1
+#define USB_PCKSIZE_SIZE_32_BYTES       2
+#define USB_PCKSIZE_SIZE_64_BYTES       3 
+#define USB_PCKSIZE_SIZE_128_BYTES      4
+#define USB_PCKSIZE_SIZE_256_BYTES      5
+#define USB_PCKSIZE_SIZE_512_BYTES      6
+#define USB_PCKSIZE_SIZE_1023_BYTES_FS  7   
+#define USB_PCKSIZE_SIZE_1024_BYTES_HS  7  
+
+#define USB_HOST_DTGL(p)               (USB->HOST.HostPipe[p].PSTATUS.reg & USB_HOST_PSTATUS_DTGL)>>USB_HOST_PSTATUS_DTGL_Pos
+
+// USB host connection/disconnection monitoring
+#define uhd_enable_connection_int()           USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DCONN
+#define uhd_disable_connection_int()          USB->HOST.INTENCLR.reg = USB_HOST_INTENCLR_DCONN
+#define uhd_ack_connection()                  USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DCONN
+
+#define uhd_enable_disconnection_int()        USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DDISC
+#define uhd_disable_disconnection_int()       USB->HOST.INTENCLR.reg = USB_HOST_INTENCLR_DDISC
+#define uhd_ack_disconnection()               USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DDISC
+
+// Initiates a USB register reset
+#define uhd_start_USB_reg_reset()             USB->HOST.CTRLA.bit.SWRST = 1;
+
+// Bus Reset
+#define Is_uhd_starting_reset()             (USB->HOST.CTRLB.bit.BUSRESET == 1)
+#define UHD_BusReset()                      USB->HOST.CTRLB.bit.BUSRESET = 1
+#define uhd_stop_reset()                    // nothing to do
+
+#define uhd_ack_reset_sent()                         USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST
+#define Is_uhd_reset_sent()                          (USB->HOST.INTFLAG.reg & USB_HOST_INTFLAG_RST)
+
+// Initiates a SOF events
+#define uhd_enable_sof()                             USB->HOST.CTRLB.bit.SOFE = 1
+#define uhd_disable_sof()                            USB->HOST.CTRLB.bit.SOFE = 0
+#define Is_uhd_sof_enabled()                         (USB->HOST.CTRLB & USB_HOST_CTRLB_SOFE)
+#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_get_configured_address(pipe_num)  usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR
+
+// Pipes
+#define uhd_freeze_pipe(p)                       USB->HOST.HostPipe[p].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE
+#define uhd_unfreeze_pipe(p)                     USB->HOST.HostPipe[p].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE
+#define Is_uhd_pipe_frozen(p)                    ((USB->HOST.HostPipe[p].PSTATUS.reg&USB_HOST_PSTATUS_PFREEZE)==USB_HOST_PSTATUS_PFREEZE)
+
+// Pipe configuration
+#define uhd_configure_pipe_token(p, token)       USB->HOST.HostPipe[p].PCFG.bit.PTOKEN = token
+
+// Pipe data management
+#define uhd_byte_count(p)                        usb_pipe_table[p].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT
+#define uhd_ack_setup_ready(p)                   USB->HOST.HostPipe[p].PINTFLAG.reg = USB_HOST_PINTFLAG_TXSTP
+#define Is_uhd_setup_ready(p)                    ((USB->HOST.HostPipe[p].PINTFLAG.reg&USB_HOST_PINTFLAG_TXSTP) == USB_HOST_PINTFLAG_TXSTP)
+#define uhd_ack_in_received(p)                   USB->HOST.HostPipe[p].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT0
+#define Is_uhd_in_received(p)                    ( (USB->HOST.HostPipe[p].PINTFLAG.reg&USB_HOST_PINTFLAG_TRCPT0) == USB_HOST_PINTFLAG_TRCPT0   )
+#define uhd_ack_out_ready(p)                     USB->HOST.HostPipe[p].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT0
+#define Is_uhd_out_ready(p)                      ((USB->HOST.HostPipe[p].PINTFLAG.reg&USB_HOST_PINTFLAG_TRCPT0) == USB_HOST_PINTFLAG_TRCPT0)
+#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)
+
+// Endpoint Interrupt Summary
+#define uhd_endpoint_interrupt()            USB->HOST.PINTSMRY.reg
+
+// Run in Standby
+#define uhd_run_in_standby()                USB->HOST.CTRLA.reg |= USB_CTRLA_RUNSTDBY
+// Force host mode
+#define uhd_force_host_mode()               USB->HOST.CTRLA.reg |= USB_CTRLA_MODE
+
+// Enable USB macro
+#define uhd_enable()                        USB->HOST.CTRLA.reg |= USB_CTRLA_ENABLE
+// Disable USB macro
+#define uhd_disable()                       USB->HOST.CTRLA.reg &= ~USB_CTRLA_ENABLE
+
+// Force full speed mode
+#define uhd_force_full_speed()              USB->HOST.CTRLB.reg &= ~USB_HOST_CTRLB_SPDCONF_Msk
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* UOTGHS_HOST_H_INCLUDED */
+#endif /* SAMD21_HOST_H_INCLUDED */
diff --git a/cores/validation/validation_usb_device/build_as6/test.cppproj b/cores/validation/validation_usb_device/build_as6/test.cppproj
index a2d9c7e507f9a5eb101c712674f56afd48a9fe3f..d542166005f1c6d410bdc963ea581a932ce714f5 100644
--- a/cores/validation/validation_usb_device/build_as6/test.cppproj
+++ b/cores/validation/validation_usb_device/build_as6/test.cppproj
@@ -137,90 +137,90 @@
   <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <ToolchainSettings>
       <ArmGccCpp>
-  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
-  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
-  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
-  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
-  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
-  <armgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</armgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
-  <armgcc.compiler.symbols.DefSymbols>
-    <ListValues>
-      <Value>DEBUG</Value>
-    </ListValues>
-  </armgcc.compiler.symbols.DefSymbols>
-  <armgcc.compiler.directories.DefaultIncludePath>False</armgcc.compiler.directories.DefaultIncludePath>
-  <armgcc.compiler.directories.IncludePaths>
-    <ListValues>
-      <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
-      <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
-      <Value>../../../../arduino</Value>
-      <Value>../../../../arduino/USB</Value>
-      <Value>../../../../../variants/arduino_zero</Value>
-      <Value>../../../../../libraries/SPI</Value>
-      <Value>../../../../../libraries/Wire</Value>
-    </ListValues>
-  </armgcc.compiler.directories.IncludePaths>
-  <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
-  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
-  <armgcc.compiler.optimization.PrepareDataForGarbageCollection>True</armgcc.compiler.optimization.PrepareDataForGarbageCollection>
-  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
-  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
-  <armgcc.compiler.miscellaneous.OtherFlags>-std=c99</armgcc.compiler.miscellaneous.OtherFlags>
-  <armgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</armgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
-  <armgcccpp.compiler.symbols.DefSymbols>
-    <ListValues>
-      <Value>DEBUG</Value>
-      <Value>USB_VID=0x2341</Value>
-      <Value>USB_PID=0x004d</Value>
-      <Value>USBCON</Value>
-    </ListValues>
-  </armgcccpp.compiler.symbols.DefSymbols>
-  <armgcccpp.compiler.directories.DefaultIncludePath>False</armgcccpp.compiler.directories.DefaultIncludePath>
-  <armgcccpp.compiler.directories.IncludePaths>
-    <ListValues>
-      <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
-      <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
-      <Value>../../../../arduino</Value>
-      <Value>../../../../arduino/USB</Value>
-      <Value>../../../../../variants/arduino_zero</Value>
-      <Value>../../../../../libraries/SPI</Value>
-      <Value>../../../../../libraries/Wire</Value>
-    </ListValues>
-  </armgcccpp.compiler.directories.IncludePaths>
-  <armgcccpp.compiler.optimization.level>Optimize (-O1)</armgcccpp.compiler.optimization.level>
-  <armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>
-  <armgcccpp.compiler.optimization.PrepareDataForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareDataForGarbageCollection>
-  <armgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</armgcccpp.compiler.optimization.DebugLevel>
-  <armgcccpp.compiler.warnings.AllWarnings>True</armgcccpp.compiler.warnings.AllWarnings>
-  <armgcccpp.compiler.miscellaneous.OtherFlags>-std=c++98</armgcccpp.compiler.miscellaneous.OtherFlags>
-  <armgcccpp.linker.general.UseNewlibNano>True</armgcccpp.linker.general.UseNewlibNano>
-  <armgcccpp.linker.libraries.Libraries>
-    <ListValues>
-      <Value>libm</Value>
-    </ListValues>
-  </armgcccpp.linker.libraries.Libraries>
-  <armgcccpp.linker.libraries.LibrarySearchPaths>
-    <ListValues>
-      <Value>../../../../../variants/arduino_zero/linker_scripts/gcc</Value>
-    </ListValues>
-  </armgcccpp.linker.libraries.LibrarySearchPaths>
-  <armgcccpp.linker.optimization.GarbageCollectUnusedSections>True</armgcccpp.linker.optimization.GarbageCollectUnusedSections>
-  <armgcccpp.linker.memorysettings.ExternalRAM />
+        <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+        <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+        <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+        <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+        <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+        <armgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</armgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
+        <armgcc.compiler.symbols.DefSymbols>
+          <ListValues>
+            <Value>DEBUG</Value>
+          </ListValues>
+        </armgcc.compiler.symbols.DefSymbols>
+        <armgcc.compiler.directories.DefaultIncludePath>False</armgcc.compiler.directories.DefaultIncludePath>
+        <armgcc.compiler.directories.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/Wire</Value>
+          </ListValues>
+        </armgcc.compiler.directories.IncludePaths>
+        <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
+        <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+        <armgcc.compiler.optimization.PrepareDataForGarbageCollection>True</armgcc.compiler.optimization.PrepareDataForGarbageCollection>
+        <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
+        <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+        <armgcc.compiler.miscellaneous.OtherFlags>-std=c99</armgcc.compiler.miscellaneous.OtherFlags>
+        <armgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</armgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
+        <armgcccpp.compiler.symbols.DefSymbols>
+          <ListValues>
+            <Value>DEBUG</Value>
+            <Value>USB_VID=0x2341</Value>
+            <Value>USB_PID=0x004d</Value>
+            <Value>USBCON</Value>
+          </ListValues>
+        </armgcccpp.compiler.symbols.DefSymbols>
+        <armgcccpp.compiler.directories.DefaultIncludePath>False</armgcccpp.compiler.directories.DefaultIncludePath>
+        <armgcccpp.compiler.directories.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/Wire</Value>
+          </ListValues>
+        </armgcccpp.compiler.directories.IncludePaths>
+        <armgcccpp.compiler.optimization.level>Optimize (-O1)</armgcccpp.compiler.optimization.level>
+        <armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>
+        <armgcccpp.compiler.optimization.PrepareDataForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareDataForGarbageCollection>
+        <armgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</armgcccpp.compiler.optimization.DebugLevel>
+        <armgcccpp.compiler.warnings.AllWarnings>True</armgcccpp.compiler.warnings.AllWarnings>
+        <armgcccpp.compiler.miscellaneous.OtherFlags>-std=c++98</armgcccpp.compiler.miscellaneous.OtherFlags>
+        <armgcccpp.linker.general.UseNewlibNano>True</armgcccpp.linker.general.UseNewlibNano>
+        <armgcccpp.linker.libraries.Libraries>
+          <ListValues>
+            <Value>libm</Value>
+          </ListValues>
+        </armgcccpp.linker.libraries.Libraries>
+        <armgcccpp.linker.libraries.LibrarySearchPaths>
+          <ListValues>
+            <Value>../../../../../variants/arduino_zero/linker_scripts/gcc</Value>
+          </ListValues>
+        </armgcccpp.linker.libraries.LibrarySearchPaths>
+        <armgcccpp.linker.optimization.GarbageCollectUnusedSections>True</armgcccpp.linker.optimization.GarbageCollectUnusedSections>
+        <armgcccpp.linker.memorysettings.ExternalRAM />
         <armgcccpp.linker.miscellaneous.LinkerFlags>--specs=nosys.specs  -Tflash_with_bootloader.ld</armgcccpp.linker.miscellaneous.LinkerFlags>
-  <armgcccpp.assembler.general.IncludePaths>
-    <ListValues>
-      <Value>../../../arduino</Value>
-    </ListValues>
-  </armgcccpp.assembler.general.IncludePaths>
-  <armgcccpp.assembler.debugging.DebugLevel>Default (-g)</armgcccpp.assembler.debugging.DebugLevel>
-  <armgcccpp.preprocessingassembler.general.DefaultIncludePath>False</armgcccpp.preprocessingassembler.general.DefaultIncludePath>
-  <armgcccpp.preprocessingassembler.general.IncludePaths>
-    <ListValues>
-      <Value>../../../arduino</Value>
-    </ListValues>
-  </armgcccpp.preprocessingassembler.general.IncludePaths>
-  <armgcccpp.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcccpp.preprocessingassembler.debugging.DebugLevel>
-</ArmGccCpp>
+        <armgcccpp.assembler.general.IncludePaths>
+          <ListValues>
+            <Value>../../../arduino</Value>
+          </ListValues>
+        </armgcccpp.assembler.general.IncludePaths>
+        <armgcccpp.assembler.debugging.DebugLevel>Default (-g)</armgcccpp.assembler.debugging.DebugLevel>
+        <armgcccpp.preprocessingassembler.general.DefaultIncludePath>False</armgcccpp.preprocessingassembler.general.DefaultIncludePath>
+        <armgcccpp.preprocessingassembler.general.IncludePaths>
+          <ListValues>
+            <Value>../../../arduino</Value>
+          </ListValues>
+        </armgcccpp.preprocessingassembler.general.IncludePaths>
+        <armgcccpp.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcccpp.preprocessingassembler.debugging.DebugLevel>
+      </ArmGccCpp>
     </ToolchainSettings>
   </PropertyGroup>
   <ItemGroup>
@@ -415,6 +415,10 @@
       <SubType>compile</SubType>
       <Link>core\USB\USB_host.h</Link>
     </Compile>
+    <Compile Include="..\..\..\arduino\USB\USB_interrupt.c">
+      <SubType>compile</SubType>
+      <Link>core\USB\USB_interrupt.c</Link>
+    </Compile>
     <Compile Include="..\..\..\arduino\WCharacter.h">
       <SubType>compile</SubType>
       <Link>core\WCharacter.h</Link>
diff --git a/cores/validation/validation_usb_host/build_as6/test.atsln b/cores/validation/validation_usb_host/build_as6/test.atsln
new file mode 100644
index 0000000000000000000000000000000000000000..749e8031642f7e15c4630fbe5342fce033772a6c
--- /dev/null
+++ b/cores/validation/validation_usb_host/build_as6/test.atsln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Atmel Studio Solution File, Format Version 11.00
+Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "test", "test.cppproj", "{B3F859AD-E162-4C2F-9684-EAC6932FEC80}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Release|ARM = Release|ARM
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B3F859AD-E162-4C2F-9684-EAC6932FEC80}.Debug|ARM.ActiveCfg = Debug|ARM
+		{B3F859AD-E162-4C2F-9684-EAC6932FEC80}.Debug|ARM.Build.0 = Debug|ARM
+		{B3F859AD-E162-4C2F-9684-EAC6932FEC80}.Release|ARM.ActiveCfg = Release|ARM
+		{B3F859AD-E162-4C2F-9684-EAC6932FEC80}.Release|ARM.Build.0 = Release|ARM
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/cores/validation/validation_usb_host/build_as6/test.cppproj b/cores/validation/validation_usb_host/build_as6/test.cppproj
new file mode 100644
index 0000000000000000000000000000000000000000..294776ba8f1760c505045653e91b7848afa51d4f
--- /dev/null
+++ b/cores/validation/validation_usb_host/build_as6/test.cppproj
@@ -0,0 +1,609 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectVersion>6.2</ProjectVersion>
+    <ToolchainName>com.Atmel.ARMGCC.CPP</ToolchainName>
+    <ProjectGuid>{b3f859ad-e162-4c2f-9684-eac6932fec80}</ProjectGuid>
+    <avrdevice>ATSAMD21G18A</avrdevice>
+    <avrdeviceseries>none</avrdeviceseries>
+    <OutputType>Executable</OutputType>
+    <Language>CPP</Language>
+    <OutputFileName>$(MSBuildProjectName)</OutputFileName>
+    <OutputFileExtension>.elf</OutputFileExtension>
+    <OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
+    <AssemblyName>test</AssemblyName>
+    <Name>test</Name>
+    <RootNamespace>test</RootNamespace>
+    <ToolchainFlavour>Native</ToolchainFlavour>
+    <KeepTimersRunning>true</KeepTimersRunning>
+    <OverrideVtor>false</OverrideVtor>
+    <CacheFlash>false</CacheFlash>
+    <ProgFlashFromRam>true</ProgFlashFromRam>
+    <RamSnippetAddress>0x20000000</RamSnippetAddress>
+    <UncachedRange />
+    <OverrideVtorValue>exception_table</OverrideVtorValue>
+    <BootSegment>2</BootSegment>
+    <eraseonlaunchrule>1</eraseonlaunchrule>
+    <AsfFrameworkConfig>
+      <framework-data xmlns="">
+        <options />
+        <configurations />
+        <files />
+        <documentation help="" />
+        <offline-documentation help="" />
+        <dependencies>
+          <content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.17.0" />
+        </dependencies>
+      </framework-data>
+    </AsfFrameworkConfig>
+    <avrtool>com.atmel.avrdbg.tool.edbg</avrtool>
+    <avrtoolinterface>SWD</avrtoolinterface>
+    <com_atmel_avrdbg_tool_samice>
+      <ToolOptions>
+        <InterfaceProperties>
+        </InterfaceProperties>
+        <InterfaceName>SWD</InterfaceName>
+      </ToolOptions>
+      <ToolType>com.atmel.avrdbg.tool.samice</ToolType>
+      <ToolNumber>28001042</ToolNumber>
+      <ToolName>SAM-ICE</ToolName>
+    </com_atmel_avrdbg_tool_samice>
+    <UseGdb>True</UseGdb>
+    <com_atmel_avrdbg_tool_edbg>
+      <ToolOptions>
+        <InterfaceProperties>
+          <SwdClock>4000000</SwdClock>
+        </InterfaceProperties>
+        <InterfaceName>SWD</InterfaceName>
+      </ToolOptions>
+      <ToolType>com.atmel.avrdbg.tool.edbg</ToolType>
+      <ToolNumber>ATML2320021800000007</ToolNumber>
+      <ToolName>EDBG</ToolName>
+    </com_atmel_avrdbg_tool_edbg>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <ToolchainSettings>
+      <ArmGccCpp>
+        <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+        <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+        <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+        <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+        <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+        <armgcc.compiler.symbols.DefSymbols>
+          <ListValues>
+            <Value>NDEBUG</Value>
+          </ListValues>
+        </armgcc.compiler.symbols.DefSymbols>
+        <armgcc.compiler.directories.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/USBHost/src</Value>
+            <Value>../../../../../libraries/Wire</Value>
+          </ListValues>
+        </armgcc.compiler.directories.IncludePaths>
+        <armgcc.compiler.optimization.level>Optimize for size (-Os)</armgcc.compiler.optimization.level>
+        <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+        <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+        <armgcccpp.compiler.symbols.DefSymbols>
+          <ListValues>
+            <Value>NDEBUG</Value>
+          </ListValues>
+        </armgcccpp.compiler.symbols.DefSymbols>
+        <armgcccpp.compiler.directories.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/USBHost/src</Value>
+            <Value>../../../../../libraries/Wire</Value>
+          </ListValues>
+        </armgcccpp.compiler.directories.IncludePaths>
+        <armgcccpp.compiler.optimization.level>Optimize for size (-Os)</armgcccpp.compiler.optimization.level>
+        <armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>
+        <armgcccpp.compiler.warnings.AllWarnings>True</armgcccpp.compiler.warnings.AllWarnings>
+        <armgcccpp.linker.libraries.Libraries>
+          <ListValues>
+            <Value>libm</Value>
+          </ListValues>
+        </armgcccpp.linker.libraries.Libraries>
+        <armgcccpp.linker.libraries.LibrarySearchPaths>
+          <ListValues>
+            <Value>../cmsis/linkerScripts</Value>
+          </ListValues>
+        </armgcccpp.linker.libraries.LibrarySearchPaths>
+        <armgcccpp.linker.optimization.GarbageCollectUnusedSections>True</armgcccpp.linker.optimization.GarbageCollectUnusedSections>
+        <armgcccpp.linker.miscellaneous.LinkerFlags>-Tsamd21g18a_flash.ld</armgcccpp.linker.miscellaneous.LinkerFlags>
+        <armgcccpp.preprocessingassembler.general.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/USBHost/src</Value>
+            <Value>../../../../../libraries/Wire</Value>
+          </ListValues>
+        </armgcccpp.preprocessingassembler.general.IncludePaths>
+      </ArmGccCpp>
+    </ToolchainSettings>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <ToolchainSettings>
+      <ArmGccCpp>
+        <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+        <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+        <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+        <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+        <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+        <armgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</armgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
+        <armgcc.compiler.symbols.DefSymbols>
+          <ListValues>
+            <Value>DEBUG</Value>
+            <Value>MAX_DEVICES_ALLOWED=8</Value>
+            <Value>DEBUG_USB_HOST</Value>
+          </ListValues>
+        </armgcc.compiler.symbols.DefSymbols>
+        <armgcc.compiler.directories.DefaultIncludePath>False</armgcc.compiler.directories.DefaultIncludePath>
+        <armgcc.compiler.directories.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/USBHost/src</Value>
+            <Value>../../../../../libraries/Wire</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+          </ListValues>
+        </armgcc.compiler.directories.IncludePaths>
+        <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
+        <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+        <armgcc.compiler.optimization.PrepareDataForGarbageCollection>True</armgcc.compiler.optimization.PrepareDataForGarbageCollection>
+        <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
+        <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+        <armgcc.compiler.miscellaneous.OtherFlags>-std=c99</armgcc.compiler.miscellaneous.OtherFlags>
+        <armgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</armgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
+        <armgcccpp.compiler.symbols.DefSymbols>
+          <ListValues>
+            <Value>DEBUG</Value>
+            <Value>USB_VID=0x2341</Value>
+            <Value>USB_PID=0x004d</Value>
+            <Value>ARDUINO_SAM_ZERO</Value>
+            <Value>DEBUG_USB_HOST</Value>
+          </ListValues>
+        </armgcccpp.compiler.symbols.DefSymbols>
+        <armgcccpp.compiler.directories.DefaultIncludePath>False</armgcccpp.compiler.directories.DefaultIncludePath>
+        <armgcccpp.compiler.directories.IncludePaths>
+          <ListValues>
+            <Value>../../../../../../../tools/CMSIS/Device/ATMEL</Value>
+            <Value>../../../../../../../tools/CMSIS/CMSIS/Include</Value>
+            <Value>../../../../arduino</Value>
+            <Value>../../../../arduino/USB</Value>
+            <Value>../../../../../variants/arduino_zero</Value>
+            <Value>../../../../../libraries/SPI</Value>
+            <Value>../../../../../libraries/USBHost/src</Value>
+            <Value>../../../../../libraries/Wire</Value>
+            <Value>../../../../../../../../libraries/USBHost/src</Value>
+          </ListValues>
+        </armgcccpp.compiler.directories.IncludePaths>
+        <armgcccpp.compiler.optimization.level>Optimize (-O1)</armgcccpp.compiler.optimization.level>
+        <armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareFunctionsForGarbageCollection>
+        <armgcccpp.compiler.optimization.PrepareDataForGarbageCollection>True</armgcccpp.compiler.optimization.PrepareDataForGarbageCollection>
+        <armgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</armgcccpp.compiler.optimization.DebugLevel>
+        <armgcccpp.compiler.warnings.AllWarnings>True</armgcccpp.compiler.warnings.AllWarnings>
+        <armgcccpp.compiler.miscellaneous.OtherFlags>-std=c++98</armgcccpp.compiler.miscellaneous.OtherFlags>
+        <armgcccpp.linker.general.UseNewlibNano>True</armgcccpp.linker.general.UseNewlibNano>
+        <armgcccpp.linker.libraries.Libraries>
+          <ListValues>
+            <Value>libm</Value>
+          </ListValues>
+        </armgcccpp.linker.libraries.Libraries>
+        <armgcccpp.linker.libraries.LibrarySearchPaths>
+          <ListValues>
+            <Value>../../../../../variants/arduino_zero/linker_scripts/gcc</Value>
+          </ListValues>
+        </armgcccpp.linker.libraries.LibrarySearchPaths>
+        <armgcccpp.linker.optimization.GarbageCollectUnusedSections>True</armgcccpp.linker.optimization.GarbageCollectUnusedSections>
+        <armgcccpp.linker.memorysettings.ExternalRAM />
+        <armgcccpp.linker.miscellaneous.LinkerFlags>-Tflash.ld</armgcccpp.linker.miscellaneous.LinkerFlags>
+        <armgcccpp.assembler.general.IncludePaths>
+          <ListValues>
+            <Value>../../../arduino</Value>
+          </ListValues>
+        </armgcccpp.assembler.general.IncludePaths>
+        <armgcccpp.assembler.debugging.DebugLevel>Default (-g)</armgcccpp.assembler.debugging.DebugLevel>
+        <armgcccpp.preprocessingassembler.general.DefaultIncludePath>False</armgcccpp.preprocessingassembler.general.DefaultIncludePath>
+        <armgcccpp.preprocessingassembler.general.IncludePaths>
+          <ListValues>
+            <Value>../../../arduino</Value>
+          </ListValues>
+        </armgcccpp.preprocessingassembler.general.IncludePaths>
+        <armgcccpp.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcccpp.preprocessingassembler.debugging.DebugLevel>
+      </ArmGccCpp>
+    </ToolchainSettings>
+  </PropertyGroup>
+  <ItemGroup>
+    <Folder Include="core" />
+    <Folder Include="core\host_example" />
+    <Folder Include="core\main\" />
+    <Folder Include="core\USB" />
+    <Folder Include="variant" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\..\..\variants\arduino_zero\pins_arduino.h">
+      <SubType>compile</SubType>
+      <Link>variant\pins_arduino.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\variants\arduino_zero\variant.cpp">
+      <SubType>compile</SubType>
+      <Link>variant\variant.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\..\variants\arduino_zero\variant.h">
+      <SubType>compile</SubType>
+      <Link>variant\variant.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Arduino.h">
+      <SubType>compile</SubType>
+      <Link>core\Arduino.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\binary.h">
+      <SubType>compile</SubType>
+      <Link>core\binary.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Client.h">
+      <SubType>compile</SubType>
+      <Link>core\Client.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\delay.c">
+      <SubType>compile</SubType>
+      <Link>core\delay.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\delay.h">
+      <SubType>compile</SubType>
+      <Link>core\delay.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\HardwareSerial.h">
+      <SubType>compile</SubType>
+      <Link>core\HardwareSerial.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\hooks.c">
+      <SubType>compile</SubType>
+      <Link>core\hooks.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\IPAddress.cpp">
+      <SubType>compile</SubType>
+      <Link>core\IPAddress.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\IPAddress.h">
+      <SubType>compile</SubType>
+      <Link>core\IPAddress.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\itoa.c">
+      <SubType>compile</SubType>
+      <Link>core\itoa.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\itoa.h">
+      <SubType>compile</SubType>
+      <Link>core\itoa.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\main.cpp">
+      <SubType>compile</SubType>
+      <Link>core\main.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Print.cpp">
+      <SubType>compile</SubType>
+      <Link>core\Print.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Print.h">
+      <SubType>compile</SubType>
+      <Link>core\Print.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Printable.h">
+      <SubType>compile</SubType>
+      <Link>core\Printable.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Reset.cpp">
+      <SubType>compile</SubType>
+      <Link>core\Reset.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Reset.h">
+      <SubType>compile</SubType>
+      <Link>core\Reset.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\RingBuffer.cpp">
+      <SubType>compile</SubType>
+      <Link>core\RingBuffer.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\RingBuffer.h">
+      <SubType>compile</SubType>
+      <Link>core\RingBuffer.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\SERCOM.cpp">
+      <SubType>compile</SubType>
+      <Link>core\SERCOM.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\SERCOM.h">
+      <SubType>compile</SubType>
+      <Link>core\SERCOM.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Server.h">
+      <SubType>compile</SubType>
+      <Link>core\Server.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\startup.c">
+      <SubType>compile</SubType>
+      <Link>core\startup.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Stream.cpp">
+      <SubType>compile</SubType>
+      <Link>core\Stream.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Stream.h">
+      <SubType>compile</SubType>
+      <Link>core\Stream.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Tone.h">
+      <SubType>compile</SubType>
+      <Link>core\Tone.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Uart.cpp">
+      <SubType>compile</SubType>
+      <Link>core\Uart.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Uart.h">
+      <SubType>compile</SubType>
+      <Link>core\Uart.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\Udp.h">
+      <SubType>compile</SubType>
+      <Link>core\Udp.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\USB\samd21_host.c">
+      <SubType>compile</SubType>
+      <Link>core\USB\samd21_host.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\USB\samd21_host.h">
+      <SubType>compile</SubType>
+      <Link>core\USB\samd21_host.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\USB\USBAPI.h">
+      <SubType>compile</SubType>
+      <Link>core\USB\USBAPI.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\USB\USBDesc.h">
+      <SubType>compile</SubType>
+      <Link>core\USB\USBDesc.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\USB\USB_host.h">
+      <SubType>compile</SubType>
+      <Link>core\USB\USB_host.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WCharacter.h">
+      <SubType>compile</SubType>
+      <Link>core\WCharacter.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WInterrupts.h">
+      <SubType>compile</SubType>
+      <Link>core\WInterrupts.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring.c">
+      <SubType>compile</SubType>
+      <Link>core\wiring.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_analog.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring_analog.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_constants.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring_constants.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_digital.c">
+      <SubType>compile</SubType>
+      <Link>core\wiring_digital.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_digital.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring_digital.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_private.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring_private.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_pulse.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring_pulse.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_shift.c">
+      <SubType>compile</SubType>
+      <Link>core\wiring_shift.c</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\wiring_shift.h">
+      <SubType>compile</SubType>
+      <Link>core\wiring_shift.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WMath.cpp">
+      <SubType>compile</SubType>
+      <Link>core\WMath.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WMath.h">
+      <SubType>compile</SubType>
+      <Link>core\WMath.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WString.cpp">
+      <SubType>compile</SubType>
+      <Link>core\WString.cpp</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WString.h">
+      <SubType>compile</SubType>
+      <Link>core\WString.h</Link>
+    </Compile>
+    <Compile Include="..\..\..\arduino\WVariant.h">
+      <SubType>compile</SubType>
+      <Link>core\WVariant.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\cores\validation\validation_usb_host\test_usb_host_adk.cpp">
+      <SubType>compile</SubType>
+      <Link>core\main\test_usb_host_adk.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\address.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\address.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\adk.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\adk.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\adk.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\adk.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\confdescparser.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\confdescparser.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hexdump.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hexdump.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hid.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hid.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hid.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hid.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hidboot.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hidboot.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hidboot.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hidboot.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hidescriptorparser.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hidescriptorparser.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hidescriptorparser.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hidescriptorparser.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hiduniversal.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hiduniversal.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hiduniversal.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hiduniversal.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\hidusagestr.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\hidusagestr.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\KeyboardController.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\KeyboardController.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\KeyboardController.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\KeyboardController.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\macros.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\macros.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\message.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\message.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\message.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\message.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\MouseController.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\MouseController.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\MouseController.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\MouseController.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\parsetools.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\parsetools.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\parsetools.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\parsetools.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\printhex.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\printhex.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\sink_parser.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\sink_parser.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\Usb.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\Usb.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\Usb.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\Usb.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\UsbCore.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\UsbCore.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\usbhub.cpp">
+      <SubType>compile</SubType>
+      <Link>core\host_example\usbhub.cpp</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\usbhub.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\usbhub.h</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\libraries\USBHost\src\usb_ch9.h">
+      <SubType>compile</SubType>
+      <Link>core\host_example\usb_ch9.h</Link>
+    </Compile>
+    <None Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\cores\validation\validation_usb_host\test_usb_host_KeyboardController.cpp">
+      <SubType>compile</SubType>
+      <Link>core\main\test_usb_host_KeyboardController.cpp</Link>
+    </None>
+    <None Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\cores\validation\validation_usb_host\test_usb_host_MouseController.cpp">
+      <SubType>compile</SubType>
+      <Link>core\main\test_usb_host_MouseController.cpp</Link>
+    </None>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\cores\arduino\USB\USB_interrupt.c">
+      <SubType>compile</SubType>
+      <Link>core\USB\USB_interrupt.c</Link>
+    </Compile>
+    <Compile Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\cores\validation\validation_usb_host\pgmstrings.h">
+      <SubType>compile</SubType>
+      <Link>core\main\pgmstrings.h</Link>
+    </Compile>
+    <None Include="C:\jcb\support\arduino\ArduinoZero\hardware\arduino\samd\cores\validation\validation_usb_host\test_USB_desc.cpp">
+      <SubType>compile</SubType>
+      <Link>core\main\test_USB_desc.cpp</Link>
+    </None>
+  </ItemGroup>
+  <Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
+</Project>
\ No newline at end of file
diff --git a/cores/validation/validation_usb_host/pgmstrings.h b/cores/validation/validation_usb_host/pgmstrings.h
new file mode 100644
index 0000000000000000000000000000000000000000..bdb0077eccf2e30b4091595b5159c1da1789553d
--- /dev/null
+++ b/cores/validation/validation_usb_host/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256    //buffer size
+ 
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; 
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor  ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+ 
+#endif // __PGMSTRINGS_H__
\ No newline at end of file
diff --git a/cores/validation/validation_usb_host/test_USB_desc.cpp b/cores/validation/validation_usb_host/test_USB_desc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0bc039b58e6499412f0f8788531266d171b6ab6b
--- /dev/null
+++ b/cores/validation/validation_usb_host/test_USB_desc.cpp
@@ -0,0 +1,387 @@
+
+
+#include "Arduino.h"
+#include <usbhub.h>
+#include "wiring_constants.h"
+#include "pgmstrings.h"
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#endif
+
+USBHost     usb;
+//USBHub  Hub1(&Usb);
+//USBHub  Hub2(&Usb);
+//USBHub  Hub3(&Usb);
+//USBHub  Hub4(&Usb);
+//USBHub  Hub5(&Usb);
+//USBHub  Hub6(&Usb);
+//USBHub  Hub7(&Usb);
+
+uint32_t next_time;
+
+void print_hex(int v, int num_places);
+void printintfdescr( uint8_t* descr_ptr );
+byte getconfdescr( byte addr, byte conf );
+void printconfdescr( uint8_t* descr_ptr );
+void printunkdescr( uint8_t* descr_ptr );
+void printepdescr( uint8_t* descr_ptr );
+void printProgStr(const prog_char str[]);
+void printHIDdescr( uint8_t* descr_ptr );
+
+void PrintAllAddresses(UsbDeviceDefinition *pdev)
+{
+    UsbDeviceAddress adr;
+    adr.devAddress = pdev->address.devAddress;
+    SERIAL_PORT_MONITOR.print("\r\nAddr:");
+    SERIAL_PORT_MONITOR.print(adr.devAddress, HEX);
+    SERIAL_PORT_MONITOR.print("(");
+    SERIAL_PORT_MONITOR.print(adr.bmHub, HEX);
+    SERIAL_PORT_MONITOR.print(".");
+    SERIAL_PORT_MONITOR.print(adr.bmParent, HEX);
+    SERIAL_PORT_MONITOR.print(".");
+    SERIAL_PORT_MONITOR.print(adr.bmAddress, HEX);
+    SERIAL_PORT_MONITOR.println(")");
+}
+
+void PrintAddress(uint8_t addr)
+{
+    UsbDeviceAddress adr;
+    adr.devAddress = addr;
+    SERIAL_PORT_MONITOR.print("\r\nADDR:\t");
+    SERIAL_PORT_MONITOR.println(adr.devAddress,HEX);
+    SERIAL_PORT_MONITOR.print("DEV:\t");
+    SERIAL_PORT_MONITOR.println(adr.bmAddress,HEX);
+    SERIAL_PORT_MONITOR.print("PRNT:\t");
+    SERIAL_PORT_MONITOR.println(adr.bmParent,HEX);
+    SERIAL_PORT_MONITOR.print("HUB:\t");
+    SERIAL_PORT_MONITOR.println(adr.bmHub,HEX);
+}
+
+void setup()
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("Start USB Desc");
+
+  if (usb.Init() == -1)
+      SERIAL_PORT_MONITOR.println("OSC did not start.");
+
+  delay( 20 );
+
+  next_time = millis() + 10000;
+}
+
+byte getdevdescr( byte addr, byte &num_conf );
+
+void PrintDescriptors(uint8_t addr)
+{
+    uint8_t rcode = 0;
+    byte num_conf = 0;
+
+    rcode = getdevdescr( (byte)addr, num_conf );
+    if( rcode )
+    {
+      printProgStr(Gen_Error_str);
+      print_hex( rcode, 8 );
+    }
+    SERIAL_PORT_MONITOR.print("\r\n");
+
+    for (int i=0; i<num_conf; i++)
+    {
+        rcode = getconfdescr( addr, i );                 // get configuration descriptor
+        if( rcode )
+        {
+          printProgStr(Gen_Error_str);
+          print_hex(rcode, 8);
+        }
+        SERIAL_PORT_MONITOR.println("\r\n");
+    }
+}
+
+void PrintAllDescriptors(UsbDeviceDefinition *pdev)
+{
+    SERIAL_PORT_MONITOR.println("\r\n");
+    print_hex(pdev->address.devAddress, 8);
+    SERIAL_PORT_MONITOR.println("\r\n--");
+    PrintDescriptors( pdev->address.devAddress );
+}
+
+void loop()
+{
+  usb.Task();
+
+  if( usb.getUsbTaskState() == USB_STATE_RUNNING )
+  {
+    //if (millis() >= next_time)
+    {
+        usb.ForEachUsbDevice(&PrintAllDescriptors);
+        usb.ForEachUsbDevice(&PrintAllAddresses);
+
+        while( 1 );                           //stop
+    }
+  }
+}
+
+byte getdevdescr( byte addr, byte &num_conf )
+{
+  USB_DEVICE_DESCRIPTOR buf;
+  byte rcode;
+  rcode = usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );
+  if( rcode ) {
+    return( rcode );
+  }
+  printProgStr(Dev_Header_str);
+  printProgStr(Dev_Length_str);
+  print_hex( buf.bLength, 8 );
+  printProgStr(Dev_Type_str);
+  print_hex( buf.bDescriptorType, 8 );
+  printProgStr(Dev_Version_str);
+  print_hex( buf.bcdUSB, 16 );
+  printProgStr(Dev_Class_str);
+  print_hex( buf.bDeviceClass, 8 );
+  printProgStr(Dev_Subclass_str);
+  print_hex( buf.bDeviceSubClass, 8 );
+  printProgStr(Dev_Protocol_str);
+  print_hex( buf.bDeviceProtocol, 8 );
+  printProgStr(Dev_Pktsize_str);
+  print_hex( buf.bMaxPacketSize0, 8 );
+  printProgStr(Dev_Vendor_str);
+  print_hex( buf.idVendor, 16 );
+  printProgStr(Dev_Product_str);
+  print_hex( buf.idProduct, 16 );
+  printProgStr(Dev_Revision_str);
+  print_hex( buf.bcdDevice, 16 );
+  printProgStr(Dev_Mfg_str);
+  print_hex( buf.iManufacturer, 8 );
+  printProgStr(Dev_Prod_str);
+  print_hex( buf.iProduct, 8 );
+  printProgStr(Dev_Serial_str);
+  print_hex( buf.iSerialNumber, 8 );
+  printProgStr(Dev_Nconf_str);
+  print_hex( buf.bNumConfigurations, 8 );
+  num_conf = buf.bNumConfigurations;
+  return( 0 );
+}
+
+void printhubdescr(uint8_t *descrptr, uint8_t addr)
+{
+    HubDescriptor  *pHub = (HubDescriptor*) descrptr;
+    uint8_t        len = *((uint8_t*)descrptr);
+
+    printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
+    printProgStr(PSTR("bDescLength:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bDescLength, HEX);
+
+    printProgStr(PSTR("bDescriptorType:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bDescriptorType, HEX);
+
+    printProgStr(PSTR("bNbrPorts:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bNbrPorts, HEX);
+
+    printProgStr(PSTR("LogPwrSwitchMode:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->LogPwrSwitchMode, BIN);
+
+    printProgStr(PSTR("CompoundDevice:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->CompoundDevice, BIN);
+
+    printProgStr(PSTR("OverCurrentProtectMode:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->OverCurrentProtectMode, BIN);
+
+    printProgStr(PSTR("TTThinkTime:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->TTThinkTime, BIN);
+
+    printProgStr(PSTR("PortIndicatorsSupported:"));
+    SERIAL_PORT_MONITOR.println(pHub->PortIndicatorsSupported, BIN);
+
+    printProgStr(PSTR("Reserved:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->Reserved, HEX);
+
+    printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bPwrOn2PwrGood, HEX);
+
+    printProgStr(PSTR("bHubContrCurrent:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bHubContrCurrent, HEX);
+
+    for (uint8_t i=7; i<len; i++)
+        print_hex(descrptr[i], 8);
+
+    //for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
+    //    PrintHubPortStatus(&Usb, addr, i, 1);
+}
+
+byte getconfdescr( byte addr, byte conf )
+{
+  uint8_t buf[ BUFSIZE ];
+  uint8_t* buf_ptr = buf;
+  byte rcode;
+  byte descr_length;
+  byte descr_type;
+  unsigned int total_length;
+  rcode = usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length
+  LOBYTE( total_length ) = buf[ 2 ];
+  HIBYTE( total_length ) = buf[ 3 ];
+  if( total_length > 256 ) {    //check if total length is larger than buffer
+    printProgStr(Conf_Trunc_str);
+    total_length = 256;
+  }
+  rcode = usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
+  while( buf_ptr < buf + total_length ) {  //parsing descriptors
+    descr_length = *( buf_ptr );
+    descr_type = *( buf_ptr + 1 );
+    switch( descr_type ) {
+      case( USB_DESCRIPTOR_CONFIGURATION ):
+        printconfdescr( buf_ptr );
+        break;
+      case( USB_DESCRIPTOR_INTERFACE ):
+        printintfdescr( buf_ptr );
+        break;
+      case( USB_DESCRIPTOR_ENDPOINT ):
+        printepdescr( buf_ptr );
+        break;
+      case 0x21:  // HID Descriptor
+        printHIDdescr( buf_ptr );
+        break;
+      case 0x29:
+        printhubdescr( buf_ptr, addr );
+        break;
+      default:
+        printunkdescr( buf_ptr );
+        break;
+        }//switch( descr_type
+    buf_ptr = ( buf_ptr + descr_length );    //advance buffer pointer
+  }//while( buf_ptr <=...
+  return( 0 );
+}
+/* prints hex numbers with leading zeroes */
+// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
+// source: http://www.phanderson.com/arduino/arduino_display.html
+void print_hex(int v, int num_places)
+{
+  int mask=0, n, num_nibbles, digit;
+
+  for (n=1; n<=num_places; n++) {
+    mask = (mask << 1) | 0x0001;
+  }
+  v = v & mask; // truncate v to specified number of places
+
+  num_nibbles = num_places / 4;
+  if ((num_places % 4) != 0) {
+    ++num_nibbles;
+  }
+  do {
+    digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
+    SERIAL_PORT_MONITOR.print(digit, HEX);
+  }
+  while(--num_nibbles);
+}
+/* function to print configuration descriptor */
+void printconfdescr( uint8_t* descr_ptr )
+{
+ USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
+  printProgStr(Conf_Header_str);
+  printProgStr(Conf_Totlen_str);
+  print_hex( conf_ptr->wTotalLength, 16 );
+  printProgStr(Conf_Nint_str);
+  print_hex( conf_ptr->bNumInterfaces, 8 );
+  printProgStr(Conf_Value_str);
+  print_hex( conf_ptr->bConfigurationValue, 8 );
+  printProgStr(Conf_String_str);
+  print_hex( conf_ptr->iConfiguration, 8 );
+  printProgStr(Conf_Attr_str);
+  print_hex( conf_ptr->bmAttributes, 8 );
+  printProgStr(Conf_Pwr_str);
+  print_hex( conf_ptr->bMaxPower, 8 );
+  return;
+}
+/* function to print interface descriptor */
+void printintfdescr( uint8_t* descr_ptr )
+{
+ USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
+  printProgStr(Int_Header_str);
+  printProgStr(Int_Number_str);
+  print_hex( intf_ptr->bInterfaceNumber, 8 );
+  printProgStr(Int_Alt_str);
+  print_hex( intf_ptr->bAlternateSetting, 8 );
+  printProgStr(Int_Endpoints_str);
+  print_hex( intf_ptr->bNumEndpoints, 8 );
+  printProgStr(Int_Class_str);
+  print_hex( intf_ptr->bInterfaceClass, 8 );
+  printProgStr(Int_Subclass_str);
+  print_hex( intf_ptr->bInterfaceSubClass, 8 );
+  printProgStr(Int_Protocol_str);
+  print_hex( intf_ptr->bInterfaceProtocol, 8 );
+  printProgStr(Int_String_str);
+  print_hex( intf_ptr->iInterface, 8 );
+  return;
+}
+
+/* function to print HID descriptor */
+void printHIDdescr( uint8_t* descr_ptr )
+{
+	USB_HID_DESCRIPTOR* ep_ptr = ( USB_HID_DESCRIPTOR* )descr_ptr;
+
+    printProgStr(PSTR("\r\n\r\nHID Descriptor:\r\n"));
+    printProgStr(PSTR("HID Class Release:\t"));
+	print_hex( ep_ptr->bcdHID, 16 );
+    printProgStr(PSTR("\r\nCountry Code:\t\t"));
+	print_hex( ep_ptr->bCountryCode, 8 );
+    printProgStr(PSTR("\r\nNumb Class Descriptor:\t"));
+	print_hex( ep_ptr->bNumDescriptors, 8 );
+    printProgStr(PSTR("\r\nDescriptor Type:\t"));
+	if( ep_ptr->bDescrType == 0x22 ) 
+		printProgStr(PSTR("REPORT DESCRIPTOR"));
+	else
+		print_hex( ep_ptr->bDescrType, 8 );
+    printProgStr(PSTR("\r\nCSize Report Descr:\t"));
+	print_hex( ep_ptr->wDescriptorLength, 16 );
+}
+
+/* function to print endpoint descriptor */
+void printepdescr( uint8_t* descr_ptr )
+{
+ USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
+  printProgStr(End_Header_str);
+  printProgStr(End_Address_str);
+  if( 0x80 & ep_ptr->bEndpointAddress ) printProgStr(PSTR("IN\t\t"));
+  else printProgStr(PSTR("OUT\t\t"));
+  print_hex( (ep_ptr->bEndpointAddress & 0xF), 8 );
+  printProgStr(End_Attr_str);
+  if( 0x03 & ep_ptr->bmAttributes ) printProgStr(PSTR("INTERRUPT\t"));
+  else if( 0x02 & ep_ptr->bmAttributes ) printProgStr(PSTR("BULK\t"));
+  else if( 0x01 & ep_ptr->bmAttributes ) printProgStr(PSTR("ISO\t"));
+  print_hex( ep_ptr->bmAttributes, 8 );
+  printProgStr(End_Pktsize_str);
+  print_hex( ep_ptr->wMaxPacketSize, 16 );
+  printProgStr(End_Interval_str);
+  print_hex( ep_ptr->bInterval, 8 );
+
+  return;
+}
+/*function to print unknown descriptor */
+void printunkdescr( uint8_t* descr_ptr )
+{
+  byte length = *descr_ptr;
+  byte i;
+  printProgStr(Unk_Header_str);
+  printProgStr(Unk_Length_str);
+  print_hex( *descr_ptr, 8 );
+  printProgStr(Unk_Type_str);
+  print_hex( *(descr_ptr + 1 ), 8 );
+  printProgStr(Unk_Contents_str);
+  descr_ptr += 2;
+  for( i = 0; i < length; i++ ) {
+    print_hex( *descr_ptr, 8 );
+    descr_ptr++;
+  }
+}
+
+
+/* Print a string from Program Memory directly to save RAM */
+void printProgStr(const prog_char str[])
+{
+  char c;
+  if(!str) return;
+  while((c = pgm_read_byte(str++)))
+    SERIAL_PORT_MONITOR.print(c);
+}
diff --git a/cores/validation/validation_usb_host/test_usb_host.cpp b/cores/validation/validation_usb_host/test_usb_host.cpp
deleted file mode 100644
index b7490ece04cdcae7d0a866e7153f5febc65374f5..0000000000000000000000000000000000000000
--- a/cores/validation/validation_usb_host/test_usb_host.cpp
+++ /dev/null
@@ -1,72 +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 "variant.h"
-#include <stdio.h>
-#include <adk.h>
-
-// Accessory descriptor. It's how Arduino identifies itself to Android.
-char applicationName[] = "Arduino_Terminal"; // the app on your phone
-char accessoryName[] = "Arduino Due X"; // your Arduino board
-char companyName[] = "Arduino SA";
-
-// Make up anything you want for these
-char versionNumber[] = "1.0";
-char serialNumber[] = "1";
-char url[] = "http://labs.arduino.cc/uploads/ADK/ArduinoTerminal/ThibaultTerminal_ICS_0001.apk";
-
-USBHost Usb;
-ADK adk(&Usb, companyName, applicationName, accessoryName,versionNumber,url,serialNumber);
-
-void setup()
-{
-	cpu_irq_enable();
-	printf("\r\nADK demo start\r\n");
-	delay(200);
-}
-
-#define RCVSIZE 128
-
-void loop()
-{
-	uint8_t buf[RCVSIZE];
-	uint32_t nbread = 0;
-	char helloworld[] = "Hello World!\r\n";
-
-	Usb.Task();
-
-	if (adk.isReady())
-	{
-		/* Write hello string to ADK */
-		adk.write(strlen(helloworld), (uint8_t *)helloworld);
-
-		delay(1000);
-
-		/* Read data from ADK and print to UART */
-		adk.read(&nbread, RCVSIZE, buf);
-		if (nbread > 0)
-		{
-			printf("RCV: ");
-			for (uint32_t i = 0; i < nbread; ++i)
-			{
-				printf("%c", (char)buf[i]);
-			}
-			printf("\r\n");
-		}
-	}
-}
diff --git a/cores/validation/validation_usb_host/test_usb_host_KeyboardController.cpp b/cores/validation/validation_usb_host/test_usb_host_KeyboardController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b869ad8035e752d5064c957219ebf1f9d90c0145
--- /dev/null
+++ b/cores/validation/validation_usb_host/test_usb_host_KeyboardController.cpp
@@ -0,0 +1,89 @@
+/*
+ Keyboard Controller Example
+
+ Shows the output of a USB Keyboard connected to
+ the Native USB port on an Arduino Due Board.
+
+ created 8 Oct 2012
+ by Cristian Maglie
+
+ http://arduino.cc/en/Tutorial/KeyboardController
+
+ This sample code is part of the public domain.
+ */
+
+// Require keyboard control library
+#include <KeyboardController.h>
+
+// Initialize USB Controller
+USBHost usb;
+
+// Attach keyboard controller to USB
+KeyboardController keyboard(usb);
+
+void printKey();
+
+// This function intercepts key press
+void keyPressed() {
+  SERIAL_PORT_MONITOR.print("Pressed:  ");
+  printKey();
+}
+
+// This function intercepts key release
+void keyReleased() {
+  SERIAL_PORT_MONITOR.print("Released: ");
+  printKey();
+}
+
+void printKey() {
+  // getOemKey() returns the OEM-code associated with the key
+  SERIAL_PORT_MONITOR.print(" key:");
+  SERIAL_PORT_MONITOR.print(keyboard.getOemKey());
+
+  // getModifiers() returns a bits field with the modifiers-keys
+  int mod = keyboard.getModifiers();
+  SERIAL_PORT_MONITOR.print(" mod:");
+  SERIAL_PORT_MONITOR.print(mod);
+
+  SERIAL_PORT_MONITOR.print(" => ");
+
+  if (mod & LeftCtrl)
+    SERIAL_PORT_MONITOR.print("L-Ctrl ");
+  if (mod & LeftShift)
+    SERIAL_PORT_MONITOR.print("L-Shift ");
+  if (mod & Alt)
+    SERIAL_PORT_MONITOR.print("Alt ");
+  if (mod & LeftCmd)
+    SERIAL_PORT_MONITOR.print("L-Cmd ");
+  if (mod & RightCtrl)
+    SERIAL_PORT_MONITOR.print("R-Ctrl ");
+  if (mod & RightShift)
+    SERIAL_PORT_MONITOR.print("R-Shift ");
+  if (mod & AltGr)
+    SERIAL_PORT_MONITOR.print("AltGr ");
+  if (mod & RightCmd)
+    SERIAL_PORT_MONITOR.print("R-Cmd ");
+
+  // getKey() returns the ASCII translation of OEM key
+  // combined with modifiers.
+  SERIAL_PORT_MONITOR.write(keyboard.getKey());
+  SERIAL_PORT_MONITOR.println();
+}
+
+void setup()
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("Keyboard Controller Program started");
+
+  if (usb.Init() == -1)
+	  SERIAL_PORT_MONITOR.println("OSC did not start.");
+  
+  delay( 20 );
+}
+
+void loop()
+{
+  // Process USB tasks
+  usb.Task();
+}
diff --git a/cores/validation/validation_usb_host/test_usb_host_MouseController.cpp b/cores/validation/validation_usb_host/test_usb_host_MouseController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5f90d59a713414edab8d390083d876dce2b9f541
--- /dev/null
+++ b/cores/validation/validation_usb_host/test_usb_host_MouseController.cpp
@@ -0,0 +1,97 @@
+/*
+ Mouse Controller Example
+
+ Shows the output of a USB Mouse connected to
+ the Native USB port on an Arduino Due Board.
+
+ created 8 Oct 2012
+ by Cristian Maglie
+
+ http://arduino.cc/en/Tutorial/MouseController
+
+ This sample code is part of the public domain.
+ */
+
+// Require mouse control library
+#include <MouseController.h>
+
+// Initialize USB Controller
+USBHost usb;
+
+// Attach mouse controller to USB
+MouseController mouse(usb);
+
+// variables for mouse button states
+boolean leftButton = false;
+boolean middleButton = false;
+boolean rightButton = false;
+
+// This function intercepts mouse movements
+void mouseMoved() {
+  SERIAL_PORT_MONITOR.print("Move: ");
+  SERIAL_PORT_MONITOR.print(mouse.getXChange());
+  SERIAL_PORT_MONITOR.print(", ");
+  SERIAL_PORT_MONITOR.println(mouse.getYChange());
+}
+
+// This function intercepts mouse movements while a button is pressed
+void mouseDragged() {
+  SERIAL_PORT_MONITOR.print("DRAG: ");
+  SERIAL_PORT_MONITOR.print(mouse.getXChange());
+  SERIAL_PORT_MONITOR.print(", ");
+  SERIAL_PORT_MONITOR.println(mouse.getYChange());
+}
+
+// This function intercepts mouse button press
+void mousePressed() {
+  SERIAL_PORT_MONITOR.print("Pressed: ");
+  if (mouse.getButton(LEFT_BUTTON)) {
+    SERIAL_PORT_MONITOR.print("L");
+    leftButton = true;
+  }
+  if (mouse.getButton(MIDDLE_BUTTON)) {
+    SERIAL_PORT_MONITOR.print("M");
+    middleButton = true;
+  }
+  if (mouse.getButton(RIGHT_BUTTON)) {
+    SERIAL_PORT_MONITOR.print("R");
+    SERIAL_PORT_MONITOR.println();
+    rightButton = true;
+  }
+}
+
+// This function intercepts mouse button release
+void mouseReleased() {
+  SERIAL_PORT_MONITOR.print("Released: ");
+  if (!mouse.getButton(LEFT_BUTTON) && leftButton == true) {
+    SERIAL_PORT_MONITOR.print("L");
+    leftButton = false;
+  }
+  if (!mouse.getButton(MIDDLE_BUTTON) && middleButton == true) {
+    SERIAL_PORT_MONITOR.print("M");
+    middleButton = false;
+  }
+  if (!mouse.getButton(RIGHT_BUTTON) && rightButton == true) {
+    SERIAL_PORT_MONITOR.print("R");
+    rightButton = false;
+  }
+  SERIAL_PORT_MONITOR.println();
+}
+
+void setup()
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("Mouse Controller Program started");
+
+  if (usb.Init() == -1)
+      SERIAL_PORT_MONITOR.println("OSC did not start.");
+
+  delay( 20 );
+}
+
+void loop()
+{
+  // Process USB tasks
+  usb.Task();
+}
diff --git a/cores/validation/validation_usb_host/test_usb_host_adk.cpp b/cores/validation/validation_usb_host/test_usb_host_adk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c84a02e4ec2984cb629bb1592231bb4ab7662fee
--- /dev/null
+++ b/cores/validation/validation_usb_host/test_usb_host_adk.cpp
@@ -0,0 +1,128 @@
+/*
+  Copyright (c) 2012 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
+*/
+
+#define ARDUINO_MAIN
+//#include "variant.h"
+#include "Arduino.h" 
+#include <stdio.h>
+#include <adk.h>
+
+
+USBHost usb;
+ADK adk(&usb,"Arduino SA",
+            "Arduino_Terminal",
+            "Arduino Terminal for Android",
+            "1.0",
+            "http://labs.arduino.cc/uploads/ADK/ArduinoTerminal/ThibaultTerminal_ICS_0001.apk",
+            //"http://www.circuitsathome.com",
+            "1");
+
+void setup(void)
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("\r\nADK demo start");
+
+  if (usb.Init() == -1)
+	SERIAL_PORT_MONITOR.println("OSC did not start.");
+
+  delay(20);
+}
+
+#define RCVSIZE 128
+
+
+
+void loop1(void)
+{
+  uint8_t rcode;
+  uint8_t msg[64] = { 0x00 };
+  const char* recv = "Received: "; 
+
+   usb.Task();
+   
+   if( adk.isReady() == false ) {
+     return;
+   }
+   uint16_t len = 64;
+   
+   SERIAL_PORT_MONITOR.println("ADK Ready");
+   rcode = adk.RcvData((uint8_t *)&len, msg);
+   if( rcode & ( rcode != USB_ERRORFLOW )) {
+     SERIAL_PORT_MONITOR.print("Data rcv. :");
+     SERIAL_PORT_MONITOR.println(rcode, DEC );
+   } 
+   if(len > 0) {
+     SERIAL_PORT_MONITOR.println("Data Packet.");
+
+    for( uint8_t i = 0; i < len; i++ ) {
+      SERIAL_PORT_MONITOR.print((char)msg[i]);
+    }
+    /* sending back what was received */    
+    rcode = adk.SndData( strlen( recv ), (uint8_t *)recv );    
+    rcode = adk.SndData( strlen(( char * )msg ), msg );
+
+   }//if( len > 0 )...
+
+   delay( 1000 );       
+}
+
+
+void loop(void)
+{
+	uint8_t buf[RCVSIZE];
+	uint32_t nbread = 0;
+	char helloworld[] = "Hello World!\r\n";
+
+	usb.Task();
+
+	if( adk.isReady() == false ) {
+		return;
+	}
+	/* Write hello string to ADK */
+	adk.SndData(strlen(helloworld), (uint8_t *)helloworld);
+
+	delay(1000);
+
+	/* Read data from ADK and print to UART */
+	adk.RcvData((uint8_t *)&nbread, buf);
+	if (nbread > 0)
+	{
+		SERIAL_PORT_MONITOR.print("RCV: ");
+		for (uint32_t i = 0; i < nbread; ++i)
+		{
+			SERIAL_PORT_MONITOR.print((char)buf[i]);
+		}
+		SERIAL_PORT_MONITOR.print("\r\n");
+	}	
+}
+
+
+// void loop2(void)
+// {
+//   uint8_t msg[3];
+//  
+// //	if (acc.isConnected()) {
+//                 SERIAL_PORT_MONITOR.print("Accessory connected. ");
+// 		int len = adk.RcvData(msg, (uint8_t)sizeof(msg));  //, 1);
+//                 SERIAL_PORT_MONITOR.print("Message length: ");
+//                 SERIAL_PORT_MONITOR.println(len, DEC);
+//         }
+//  
+// 	delay(100);
+// }
\ No newline at end of file
diff --git a/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino b/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino
new file mode 100644
index 0000000000000000000000000000000000000000..ea7509cbce84fe4e9d44e07ad72afb321e08703d
--- /dev/null
+++ b/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino
@@ -0,0 +1,75 @@
+/*
+  Copyright (c) 2012 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
+*/
+
+#define ARDUINO_MAIN
+//#include "variant.h"
+#include "Arduino.h" 
+#include <stdio.h>
+#include <adk.h>
+
+
+USBHost usb;
+ADK adk(&usb,"Arduino SA",
+            "Arduino_Terminal",
+            "Arduino Terminal for Android",
+            "1.0",
+            "http://labs.arduino.cc/uploads/ADK/ArduinoTerminal/ThibaultTerminal_ICS_0001.apk",
+            "1");
+
+void setup(void)
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("\r\nADK demo start");
+
+  if (usb.Init() == -1)
+	SERIAL_PORT_MONITOR.println("OSC did not start.");
+
+  delay(20);
+}
+
+#define RCVSIZE 128
+
+void loop(void)
+{
+	uint8_t buf[RCVSIZE];
+	uint32_t nbread = 0;
+	char helloworld[] = "Hello World!\r\n";
+
+	usb.Task();
+
+	if( adk.isReady() == false ) {
+		return;
+	}
+	/* Write hello string to ADK */
+	adk.SndData(strlen(helloworld), (uint8_t *)helloworld);
+
+	delay(1000);
+
+	/* Read data from ADK and print to UART */
+	adk.RcvData((uint8_t *)&nbread, buf);
+	if (nbread > 0)
+	{
+		SERIAL_PORT_MONITOR.print("RCV: ");
+		for (uint32_t i = 0; i < nbread; ++i)
+		{
+			SERIAL_PORT_MONITOR.print((char)buf[i]);
+		}
+		SERIAL_PORT_MONITOR.print("\r\n");
+	}	
+}
diff --git a/libraries/USBHost/examples/KeyboardController/KeyboardController.ino b/libraries/USBHost/examples/KeyboardController/KeyboardController.ino
new file mode 100644
index 0000000000000000000000000000000000000000..b869ad8035e752d5064c957219ebf1f9d90c0145
--- /dev/null
+++ b/libraries/USBHost/examples/KeyboardController/KeyboardController.ino
@@ -0,0 +1,89 @@
+/*
+ Keyboard Controller Example
+
+ Shows the output of a USB Keyboard connected to
+ the Native USB port on an Arduino Due Board.
+
+ created 8 Oct 2012
+ by Cristian Maglie
+
+ http://arduino.cc/en/Tutorial/KeyboardController
+
+ This sample code is part of the public domain.
+ */
+
+// Require keyboard control library
+#include <KeyboardController.h>
+
+// Initialize USB Controller
+USBHost usb;
+
+// Attach keyboard controller to USB
+KeyboardController keyboard(usb);
+
+void printKey();
+
+// This function intercepts key press
+void keyPressed() {
+  SERIAL_PORT_MONITOR.print("Pressed:  ");
+  printKey();
+}
+
+// This function intercepts key release
+void keyReleased() {
+  SERIAL_PORT_MONITOR.print("Released: ");
+  printKey();
+}
+
+void printKey() {
+  // getOemKey() returns the OEM-code associated with the key
+  SERIAL_PORT_MONITOR.print(" key:");
+  SERIAL_PORT_MONITOR.print(keyboard.getOemKey());
+
+  // getModifiers() returns a bits field with the modifiers-keys
+  int mod = keyboard.getModifiers();
+  SERIAL_PORT_MONITOR.print(" mod:");
+  SERIAL_PORT_MONITOR.print(mod);
+
+  SERIAL_PORT_MONITOR.print(" => ");
+
+  if (mod & LeftCtrl)
+    SERIAL_PORT_MONITOR.print("L-Ctrl ");
+  if (mod & LeftShift)
+    SERIAL_PORT_MONITOR.print("L-Shift ");
+  if (mod & Alt)
+    SERIAL_PORT_MONITOR.print("Alt ");
+  if (mod & LeftCmd)
+    SERIAL_PORT_MONITOR.print("L-Cmd ");
+  if (mod & RightCtrl)
+    SERIAL_PORT_MONITOR.print("R-Ctrl ");
+  if (mod & RightShift)
+    SERIAL_PORT_MONITOR.print("R-Shift ");
+  if (mod & AltGr)
+    SERIAL_PORT_MONITOR.print("AltGr ");
+  if (mod & RightCmd)
+    SERIAL_PORT_MONITOR.print("R-Cmd ");
+
+  // getKey() returns the ASCII translation of OEM key
+  // combined with modifiers.
+  SERIAL_PORT_MONITOR.write(keyboard.getKey());
+  SERIAL_PORT_MONITOR.println();
+}
+
+void setup()
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("Keyboard Controller Program started");
+
+  if (usb.Init() == -1)
+	  SERIAL_PORT_MONITOR.println("OSC did not start.");
+  
+  delay( 20 );
+}
+
+void loop()
+{
+  // Process USB tasks
+  usb.Task();
+}
diff --git a/libraries/USBHost/examples/MouseController/MouseController.ino b/libraries/USBHost/examples/MouseController/MouseController.ino
new file mode 100644
index 0000000000000000000000000000000000000000..5f90d59a713414edab8d390083d876dce2b9f541
--- /dev/null
+++ b/libraries/USBHost/examples/MouseController/MouseController.ino
@@ -0,0 +1,97 @@
+/*
+ Mouse Controller Example
+
+ Shows the output of a USB Mouse connected to
+ the Native USB port on an Arduino Due Board.
+
+ created 8 Oct 2012
+ by Cristian Maglie
+
+ http://arduino.cc/en/Tutorial/MouseController
+
+ This sample code is part of the public domain.
+ */
+
+// Require mouse control library
+#include <MouseController.h>
+
+// Initialize USB Controller
+USBHost usb;
+
+// Attach mouse controller to USB
+MouseController mouse(usb);
+
+// variables for mouse button states
+boolean leftButton = false;
+boolean middleButton = false;
+boolean rightButton = false;
+
+// This function intercepts mouse movements
+void mouseMoved() {
+  SERIAL_PORT_MONITOR.print("Move: ");
+  SERIAL_PORT_MONITOR.print(mouse.getXChange());
+  SERIAL_PORT_MONITOR.print(", ");
+  SERIAL_PORT_MONITOR.println(mouse.getYChange());
+}
+
+// This function intercepts mouse movements while a button is pressed
+void mouseDragged() {
+  SERIAL_PORT_MONITOR.print("DRAG: ");
+  SERIAL_PORT_MONITOR.print(mouse.getXChange());
+  SERIAL_PORT_MONITOR.print(", ");
+  SERIAL_PORT_MONITOR.println(mouse.getYChange());
+}
+
+// This function intercepts mouse button press
+void mousePressed() {
+  SERIAL_PORT_MONITOR.print("Pressed: ");
+  if (mouse.getButton(LEFT_BUTTON)) {
+    SERIAL_PORT_MONITOR.print("L");
+    leftButton = true;
+  }
+  if (mouse.getButton(MIDDLE_BUTTON)) {
+    SERIAL_PORT_MONITOR.print("M");
+    middleButton = true;
+  }
+  if (mouse.getButton(RIGHT_BUTTON)) {
+    SERIAL_PORT_MONITOR.print("R");
+    SERIAL_PORT_MONITOR.println();
+    rightButton = true;
+  }
+}
+
+// This function intercepts mouse button release
+void mouseReleased() {
+  SERIAL_PORT_MONITOR.print("Released: ");
+  if (!mouse.getButton(LEFT_BUTTON) && leftButton == true) {
+    SERIAL_PORT_MONITOR.print("L");
+    leftButton = false;
+  }
+  if (!mouse.getButton(MIDDLE_BUTTON) && middleButton == true) {
+    SERIAL_PORT_MONITOR.print("M");
+    middleButton = false;
+  }
+  if (!mouse.getButton(RIGHT_BUTTON) && rightButton == true) {
+    SERIAL_PORT_MONITOR.print("R");
+    rightButton = false;
+  }
+  SERIAL_PORT_MONITOR.println();
+}
+
+void setup()
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("Mouse Controller Program started");
+
+  if (usb.Init() == -1)
+      SERIAL_PORT_MONITOR.println("OSC did not start.");
+
+  delay( 20 );
+}
+
+void loop()
+{
+  // Process USB tasks
+  usb.Task();
+}
diff --git a/libraries/USBHost/examples/USB_desc/USB_desc.ino b/libraries/USBHost/examples/USB_desc/USB_desc.ino
new file mode 100644
index 0000000000000000000000000000000000000000..0bc039b58e6499412f0f8788531266d171b6ab6b
--- /dev/null
+++ b/libraries/USBHost/examples/USB_desc/USB_desc.ino
@@ -0,0 +1,387 @@
+
+
+#include "Arduino.h"
+#include <usbhub.h>
+#include "wiring_constants.h"
+#include "pgmstrings.h"
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#endif
+
+USBHost     usb;
+//USBHub  Hub1(&Usb);
+//USBHub  Hub2(&Usb);
+//USBHub  Hub3(&Usb);
+//USBHub  Hub4(&Usb);
+//USBHub  Hub5(&Usb);
+//USBHub  Hub6(&Usb);
+//USBHub  Hub7(&Usb);
+
+uint32_t next_time;
+
+void print_hex(int v, int num_places);
+void printintfdescr( uint8_t* descr_ptr );
+byte getconfdescr( byte addr, byte conf );
+void printconfdescr( uint8_t* descr_ptr );
+void printunkdescr( uint8_t* descr_ptr );
+void printepdescr( uint8_t* descr_ptr );
+void printProgStr(const prog_char str[]);
+void printHIDdescr( uint8_t* descr_ptr );
+
+void PrintAllAddresses(UsbDeviceDefinition *pdev)
+{
+    UsbDeviceAddress adr;
+    adr.devAddress = pdev->address.devAddress;
+    SERIAL_PORT_MONITOR.print("\r\nAddr:");
+    SERIAL_PORT_MONITOR.print(adr.devAddress, HEX);
+    SERIAL_PORT_MONITOR.print("(");
+    SERIAL_PORT_MONITOR.print(adr.bmHub, HEX);
+    SERIAL_PORT_MONITOR.print(".");
+    SERIAL_PORT_MONITOR.print(adr.bmParent, HEX);
+    SERIAL_PORT_MONITOR.print(".");
+    SERIAL_PORT_MONITOR.print(adr.bmAddress, HEX);
+    SERIAL_PORT_MONITOR.println(")");
+}
+
+void PrintAddress(uint8_t addr)
+{
+    UsbDeviceAddress adr;
+    adr.devAddress = addr;
+    SERIAL_PORT_MONITOR.print("\r\nADDR:\t");
+    SERIAL_PORT_MONITOR.println(adr.devAddress,HEX);
+    SERIAL_PORT_MONITOR.print("DEV:\t");
+    SERIAL_PORT_MONITOR.println(adr.bmAddress,HEX);
+    SERIAL_PORT_MONITOR.print("PRNT:\t");
+    SERIAL_PORT_MONITOR.println(adr.bmParent,HEX);
+    SERIAL_PORT_MONITOR.print("HUB:\t");
+    SERIAL_PORT_MONITOR.println(adr.bmHub,HEX);
+}
+
+void setup()
+{
+  SERIAL_PORT_MONITOR.begin( 115200 );
+  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+  SERIAL_PORT_MONITOR.println("Start USB Desc");
+
+  if (usb.Init() == -1)
+      SERIAL_PORT_MONITOR.println("OSC did not start.");
+
+  delay( 20 );
+
+  next_time = millis() + 10000;
+}
+
+byte getdevdescr( byte addr, byte &num_conf );
+
+void PrintDescriptors(uint8_t addr)
+{
+    uint8_t rcode = 0;
+    byte num_conf = 0;
+
+    rcode = getdevdescr( (byte)addr, num_conf );
+    if( rcode )
+    {
+      printProgStr(Gen_Error_str);
+      print_hex( rcode, 8 );
+    }
+    SERIAL_PORT_MONITOR.print("\r\n");
+
+    for (int i=0; i<num_conf; i++)
+    {
+        rcode = getconfdescr( addr, i );                 // get configuration descriptor
+        if( rcode )
+        {
+          printProgStr(Gen_Error_str);
+          print_hex(rcode, 8);
+        }
+        SERIAL_PORT_MONITOR.println("\r\n");
+    }
+}
+
+void PrintAllDescriptors(UsbDeviceDefinition *pdev)
+{
+    SERIAL_PORT_MONITOR.println("\r\n");
+    print_hex(pdev->address.devAddress, 8);
+    SERIAL_PORT_MONITOR.println("\r\n--");
+    PrintDescriptors( pdev->address.devAddress );
+}
+
+void loop()
+{
+  usb.Task();
+
+  if( usb.getUsbTaskState() == USB_STATE_RUNNING )
+  {
+    //if (millis() >= next_time)
+    {
+        usb.ForEachUsbDevice(&PrintAllDescriptors);
+        usb.ForEachUsbDevice(&PrintAllAddresses);
+
+        while( 1 );                           //stop
+    }
+  }
+}
+
+byte getdevdescr( byte addr, byte &num_conf )
+{
+  USB_DEVICE_DESCRIPTOR buf;
+  byte rcode;
+  rcode = usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );
+  if( rcode ) {
+    return( rcode );
+  }
+  printProgStr(Dev_Header_str);
+  printProgStr(Dev_Length_str);
+  print_hex( buf.bLength, 8 );
+  printProgStr(Dev_Type_str);
+  print_hex( buf.bDescriptorType, 8 );
+  printProgStr(Dev_Version_str);
+  print_hex( buf.bcdUSB, 16 );
+  printProgStr(Dev_Class_str);
+  print_hex( buf.bDeviceClass, 8 );
+  printProgStr(Dev_Subclass_str);
+  print_hex( buf.bDeviceSubClass, 8 );
+  printProgStr(Dev_Protocol_str);
+  print_hex( buf.bDeviceProtocol, 8 );
+  printProgStr(Dev_Pktsize_str);
+  print_hex( buf.bMaxPacketSize0, 8 );
+  printProgStr(Dev_Vendor_str);
+  print_hex( buf.idVendor, 16 );
+  printProgStr(Dev_Product_str);
+  print_hex( buf.idProduct, 16 );
+  printProgStr(Dev_Revision_str);
+  print_hex( buf.bcdDevice, 16 );
+  printProgStr(Dev_Mfg_str);
+  print_hex( buf.iManufacturer, 8 );
+  printProgStr(Dev_Prod_str);
+  print_hex( buf.iProduct, 8 );
+  printProgStr(Dev_Serial_str);
+  print_hex( buf.iSerialNumber, 8 );
+  printProgStr(Dev_Nconf_str);
+  print_hex( buf.bNumConfigurations, 8 );
+  num_conf = buf.bNumConfigurations;
+  return( 0 );
+}
+
+void printhubdescr(uint8_t *descrptr, uint8_t addr)
+{
+    HubDescriptor  *pHub = (HubDescriptor*) descrptr;
+    uint8_t        len = *((uint8_t*)descrptr);
+
+    printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
+    printProgStr(PSTR("bDescLength:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bDescLength, HEX);
+
+    printProgStr(PSTR("bDescriptorType:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bDescriptorType, HEX);
+
+    printProgStr(PSTR("bNbrPorts:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bNbrPorts, HEX);
+
+    printProgStr(PSTR("LogPwrSwitchMode:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->LogPwrSwitchMode, BIN);
+
+    printProgStr(PSTR("CompoundDevice:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->CompoundDevice, BIN);
+
+    printProgStr(PSTR("OverCurrentProtectMode:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->OverCurrentProtectMode, BIN);
+
+    printProgStr(PSTR("TTThinkTime:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->TTThinkTime, BIN);
+
+    printProgStr(PSTR("PortIndicatorsSupported:"));
+    SERIAL_PORT_MONITOR.println(pHub->PortIndicatorsSupported, BIN);
+
+    printProgStr(PSTR("Reserved:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->Reserved, HEX);
+
+    printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bPwrOn2PwrGood, HEX);
+
+    printProgStr(PSTR("bHubContrCurrent:\t"));
+    SERIAL_PORT_MONITOR.println(pHub->bHubContrCurrent, HEX);
+
+    for (uint8_t i=7; i<len; i++)
+        print_hex(descrptr[i], 8);
+
+    //for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
+    //    PrintHubPortStatus(&Usb, addr, i, 1);
+}
+
+byte getconfdescr( byte addr, byte conf )
+{
+  uint8_t buf[ BUFSIZE ];
+  uint8_t* buf_ptr = buf;
+  byte rcode;
+  byte descr_length;
+  byte descr_type;
+  unsigned int total_length;
+  rcode = usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length
+  LOBYTE( total_length ) = buf[ 2 ];
+  HIBYTE( total_length ) = buf[ 3 ];
+  if( total_length > 256 ) {    //check if total length is larger than buffer
+    printProgStr(Conf_Trunc_str);
+    total_length = 256;
+  }
+  rcode = usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
+  while( buf_ptr < buf + total_length ) {  //parsing descriptors
+    descr_length = *( buf_ptr );
+    descr_type = *( buf_ptr + 1 );
+    switch( descr_type ) {
+      case( USB_DESCRIPTOR_CONFIGURATION ):
+        printconfdescr( buf_ptr );
+        break;
+      case( USB_DESCRIPTOR_INTERFACE ):
+        printintfdescr( buf_ptr );
+        break;
+      case( USB_DESCRIPTOR_ENDPOINT ):
+        printepdescr( buf_ptr );
+        break;
+      case 0x21:  // HID Descriptor
+        printHIDdescr( buf_ptr );
+        break;
+      case 0x29:
+        printhubdescr( buf_ptr, addr );
+        break;
+      default:
+        printunkdescr( buf_ptr );
+        break;
+        }//switch( descr_type
+    buf_ptr = ( buf_ptr + descr_length );    //advance buffer pointer
+  }//while( buf_ptr <=...
+  return( 0 );
+}
+/* prints hex numbers with leading zeroes */
+// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
+// source: http://www.phanderson.com/arduino/arduino_display.html
+void print_hex(int v, int num_places)
+{
+  int mask=0, n, num_nibbles, digit;
+
+  for (n=1; n<=num_places; n++) {
+    mask = (mask << 1) | 0x0001;
+  }
+  v = v & mask; // truncate v to specified number of places
+
+  num_nibbles = num_places / 4;
+  if ((num_places % 4) != 0) {
+    ++num_nibbles;
+  }
+  do {
+    digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
+    SERIAL_PORT_MONITOR.print(digit, HEX);
+  }
+  while(--num_nibbles);
+}
+/* function to print configuration descriptor */
+void printconfdescr( uint8_t* descr_ptr )
+{
+ USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
+  printProgStr(Conf_Header_str);
+  printProgStr(Conf_Totlen_str);
+  print_hex( conf_ptr->wTotalLength, 16 );
+  printProgStr(Conf_Nint_str);
+  print_hex( conf_ptr->bNumInterfaces, 8 );
+  printProgStr(Conf_Value_str);
+  print_hex( conf_ptr->bConfigurationValue, 8 );
+  printProgStr(Conf_String_str);
+  print_hex( conf_ptr->iConfiguration, 8 );
+  printProgStr(Conf_Attr_str);
+  print_hex( conf_ptr->bmAttributes, 8 );
+  printProgStr(Conf_Pwr_str);
+  print_hex( conf_ptr->bMaxPower, 8 );
+  return;
+}
+/* function to print interface descriptor */
+void printintfdescr( uint8_t* descr_ptr )
+{
+ USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
+  printProgStr(Int_Header_str);
+  printProgStr(Int_Number_str);
+  print_hex( intf_ptr->bInterfaceNumber, 8 );
+  printProgStr(Int_Alt_str);
+  print_hex( intf_ptr->bAlternateSetting, 8 );
+  printProgStr(Int_Endpoints_str);
+  print_hex( intf_ptr->bNumEndpoints, 8 );
+  printProgStr(Int_Class_str);
+  print_hex( intf_ptr->bInterfaceClass, 8 );
+  printProgStr(Int_Subclass_str);
+  print_hex( intf_ptr->bInterfaceSubClass, 8 );
+  printProgStr(Int_Protocol_str);
+  print_hex( intf_ptr->bInterfaceProtocol, 8 );
+  printProgStr(Int_String_str);
+  print_hex( intf_ptr->iInterface, 8 );
+  return;
+}
+
+/* function to print HID descriptor */
+void printHIDdescr( uint8_t* descr_ptr )
+{
+	USB_HID_DESCRIPTOR* ep_ptr = ( USB_HID_DESCRIPTOR* )descr_ptr;
+
+    printProgStr(PSTR("\r\n\r\nHID Descriptor:\r\n"));
+    printProgStr(PSTR("HID Class Release:\t"));
+	print_hex( ep_ptr->bcdHID, 16 );
+    printProgStr(PSTR("\r\nCountry Code:\t\t"));
+	print_hex( ep_ptr->bCountryCode, 8 );
+    printProgStr(PSTR("\r\nNumb Class Descriptor:\t"));
+	print_hex( ep_ptr->bNumDescriptors, 8 );
+    printProgStr(PSTR("\r\nDescriptor Type:\t"));
+	if( ep_ptr->bDescrType == 0x22 ) 
+		printProgStr(PSTR("REPORT DESCRIPTOR"));
+	else
+		print_hex( ep_ptr->bDescrType, 8 );
+    printProgStr(PSTR("\r\nCSize Report Descr:\t"));
+	print_hex( ep_ptr->wDescriptorLength, 16 );
+}
+
+/* function to print endpoint descriptor */
+void printepdescr( uint8_t* descr_ptr )
+{
+ USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
+  printProgStr(End_Header_str);
+  printProgStr(End_Address_str);
+  if( 0x80 & ep_ptr->bEndpointAddress ) printProgStr(PSTR("IN\t\t"));
+  else printProgStr(PSTR("OUT\t\t"));
+  print_hex( (ep_ptr->bEndpointAddress & 0xF), 8 );
+  printProgStr(End_Attr_str);
+  if( 0x03 & ep_ptr->bmAttributes ) printProgStr(PSTR("INTERRUPT\t"));
+  else if( 0x02 & ep_ptr->bmAttributes ) printProgStr(PSTR("BULK\t"));
+  else if( 0x01 & ep_ptr->bmAttributes ) printProgStr(PSTR("ISO\t"));
+  print_hex( ep_ptr->bmAttributes, 8 );
+  printProgStr(End_Pktsize_str);
+  print_hex( ep_ptr->wMaxPacketSize, 16 );
+  printProgStr(End_Interval_str);
+  print_hex( ep_ptr->bInterval, 8 );
+
+  return;
+}
+/*function to print unknown descriptor */
+void printunkdescr( uint8_t* descr_ptr )
+{
+  byte length = *descr_ptr;
+  byte i;
+  printProgStr(Unk_Header_str);
+  printProgStr(Unk_Length_str);
+  print_hex( *descr_ptr, 8 );
+  printProgStr(Unk_Type_str);
+  print_hex( *(descr_ptr + 1 ), 8 );
+  printProgStr(Unk_Contents_str);
+  descr_ptr += 2;
+  for( i = 0; i < length; i++ ) {
+    print_hex( *descr_ptr, 8 );
+    descr_ptr++;
+  }
+}
+
+
+/* Print a string from Program Memory directly to save RAM */
+void printProgStr(const prog_char str[])
+{
+  char c;
+  if(!str) return;
+  while((c = pgm_read_byte(str++)))
+    SERIAL_PORT_MONITOR.print(c);
+}
diff --git a/libraries/USBHost/examples/USB_desc/pgmstrings.h b/libraries/USBHost/examples/USB_desc/pgmstrings.h
new file mode 100644
index 0000000000000000000000000000000000000000..bdb0077eccf2e30b4091595b5159c1da1789553d
--- /dev/null
+++ b/libraries/USBHost/examples/USB_desc/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256    //buffer size
+ 
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; 
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor  ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+ 
+#endif // __PGMSTRINGS_H__
\ No newline at end of file
diff --git a/libraries/USBHost/keywords.txt b/libraries/USBHost/keywords.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dded4dcf7295c212c17ed3b928dc07a9fc095812
--- /dev/null
+++ b/libraries/USBHost/keywords.txt
@@ -0,0 +1,35 @@
+#######################################
+# Syntax Coloring Map For USBHost
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+MouseController	KEYWORD1
+USBHost	KEYWORD1
+KeyboardController	KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+Task	KEYWORD2
+mouseMoved	KEYWORD2
+mouseDragged	KEYWORD2
+mousePressed	KEYWORD2
+mouseReleased	KEYWORD2
+getXChange	KEYWORD2
+getYChange	KEYWORD2
+getButton	KEYWORD2
+keyPressed	KEYWORD2
+keyReleased	KEYWORD2
+getModifiers	KEYWORD2
+getKey	KEYWORD2
+getOemKey	KEYWORD2
+
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
diff --git a/libraries/USBHost/library.properties b/libraries/USBHost/library.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cfd5eb9bdadd08c1273ffe465ff5687b8d17a3cb
--- /dev/null
+++ b/libraries/USBHost/library.properties
@@ -0,0 +1,8 @@
+name=USBHost
+version=1.0
+author=Arduino
+maintainer=Arduino <info@arduino.cc>
+sentence=Allows the communication with USB peripherals like mice, keyboards, and thumbdrives. For Arduino DUE only.
+paragraph=The USBHost library allows an Arduino Due board to appear as a USB host, enabling it to communicate with peripherals like USB mice and keyboards. USBHost does not support devices that are connected through USB hubs. This includes some keyboards that have an internal hub.
+url=http://arduino.cc/en/Reference/USBHost
+architectures=sam
diff --git a/libraries/USBHost/src/KeyboardController.cpp b/libraries/USBHost/src/KeyboardController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..70c769f64e05113a4ae9b96ddfee28b02f979c06
--- /dev/null
+++ b/libraries/USBHost/src/KeyboardController.cpp
@@ -0,0 +1,40 @@
+/*
+ Copyright (c) 2012 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 <KeyboardController.h>
+
+extern "C" {
+void __keyboardControllerEmptyCallback() { }
+}
+
+void keyPressed()  __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
+void keyReleased() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
+
+void KeyboardController::OnKeyDown(uint8_t _mod, uint8_t _oemKey) {
+	modifiers = _mod;
+	keyOem = _oemKey;
+	key = OemToAscii(_mod, _oemKey);
+	keyPressed();
+}
+
+void KeyboardController::OnKeyUp(uint8_t _mod, uint8_t _oemKey) {
+	modifiers = _mod;
+	keyOem = _oemKey;
+	key = OemToAscii(_mod, _oemKey);
+	keyReleased();
+}
diff --git a/libraries/USBHost/src/KeyboardController.h b/libraries/USBHost/src/KeyboardController.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1b891bff8a870bb02ae14fc19c663973c9f21d6
--- /dev/null
+++ b/libraries/USBHost/src/KeyboardController.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 2012 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 KEYBOARD_CONTROLLER_H
+#define KEYBOARD_CONTROLLER_H
+
+#include <hidboot.h>
+
+enum KeyboardModifiers {
+	LeftCtrl = 1,
+	LeftShift = 2,
+	Alt = 4,
+	LeftCmd = 8,
+	RightCtrl = 16,
+	RightShift = 32,
+	AltGr = 64,
+	RightCmd = 128
+};
+
+class KeyboardController : public KeyboardReportParser {
+public:
+  KeyboardController(USBHost &usb) : hostKeyboard(&usb), key(0), keyOem(0), modifiers(0) {
+    hostKeyboard.SetReportParser(0, this);
+  };
+
+  uint8_t getKey()       { return key; };
+  uint8_t getModifiers() { return modifiers; };
+  uint8_t getOemKey()    { return keyOem; };
+
+protected:
+  virtual void OnKeyDown(uint8_t mod, uint8_t key);
+  virtual void OnKeyUp(uint8_t mod, uint8_t key);
+
+private:
+  HIDBoot<HID_PROTOCOL_KEYBOARD> hostKeyboard;
+  uint8_t key, keyOem, modifiers;
+};
+
+#endif
diff --git a/libraries/USBHost/src/MouseController.cpp b/libraries/USBHost/src/MouseController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3d528bc3785b845390378d82107e3607de733fff
--- /dev/null
+++ b/libraries/USBHost/src/MouseController.cpp
@@ -0,0 +1,83 @@
+/*
+ Copyright (c) 2012 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 <MouseController.h>
+
+extern "C" {
+void __mouseControllerEmptyCallback() { }
+}
+
+void mouseClicked()  __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
+void mouseDragged()  __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
+void mouseMoved()    __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
+void mousePressed()  __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
+void mouseReleased() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
+
+int MouseController::getXChange() {
+	int r = dx;
+	dx = 0;
+	return r;
+}
+
+int MouseController::getYChange() {
+	int r = dy;
+	dy = 0;
+	return r;
+}
+
+void MouseController::OnMouseMove(MOUSEINFO *mi) {
+	dx += mi->dX;
+	dy += mi->dY;
+	if (buttons != 0)
+		mouseDragged();
+	else
+		mouseMoved();
+}
+
+void MouseController::OnLeftButtonUp(MOUSEINFO *mi) {
+	buttons &= ~LEFT_BUTTON;
+	mouseReleased();
+	mouseClicked();
+}
+
+void MouseController::OnLeftButtonDown(MOUSEINFO *mi) {
+	buttons |= LEFT_BUTTON;
+	mousePressed();
+}
+
+void MouseController::OnMiddleButtonUp(MOUSEINFO *mi) {
+	buttons &= ~MIDDLE_BUTTON;
+	mouseReleased();
+	mouseClicked();
+}
+
+void MouseController::OnMiddleButtonDown(MOUSEINFO *mi) {
+	buttons |= MIDDLE_BUTTON;
+	mousePressed();
+}
+
+void MouseController::OnRightButtonUp(MOUSEINFO *mi) {
+	buttons &= ~RIGHT_BUTTON;
+	mouseReleased();
+	mouseClicked();
+}
+
+void MouseController::OnRightButtonDown(MOUSEINFO *mi) {
+	buttons |= RIGHT_BUTTON;
+	mousePressed();
+}
diff --git a/libraries/USBHost/src/MouseController.h b/libraries/USBHost/src/MouseController.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c8c65e9ce97e838c172c4a41565c9ca548ed4ff
--- /dev/null
+++ b/libraries/USBHost/src/MouseController.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (c) 2012 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 MOUSE_CONTROLLER_H
+#define MOUSE_CONTROLLER_H
+
+#include <hidboot.h>
+
+enum MouseButton {
+	LEFT_BUTTON   = 0x01,
+	MIDDLE_BUTTON = 0x02,
+	RIGHT_BUTTON  = 0x04
+};
+
+class MouseController : public MouseReportParser
+{
+public:
+  MouseController(USBHost &usb) : hostMouse(&usb), dx(0), dy(0), buttons(0) {
+    hostMouse.SetReportParser(0, this);
+  };
+
+  bool getButton(MouseButton button) { return (buttons & button) == button; };
+  int getXChange();
+  int getYChange();
+  // int getWheelChange(); // Not implemented
+
+protected:
+  virtual void OnMouseMove(MOUSEINFO *mi);
+  virtual void OnLeftButtonUp(MOUSEINFO *mi);
+  virtual void OnLeftButtonDown(MOUSEINFO *mi);
+  virtual void OnMiddleButtonUp(MOUSEINFO *mi);
+  virtual void OnMiddleButtonDown(MOUSEINFO *mi);
+  virtual void OnRightButtonUp(MOUSEINFO *mi);
+  virtual void OnRightButtonDown(MOUSEINFO *mi);
+
+private:
+  HIDBoot<HID_PROTOCOL_MOUSE> hostMouse;
+  int dx, dy;
+  int buttons;
+};
+
+#endif
diff --git a/libraries/USBHost/src/Usb.cpp b/libraries/USBHost/src/Usb.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea2b8c46ceab3e62a5a80425c3cca0a40335eca6
--- /dev/null
+++ b/libraries/USBHost/src/Usb.cpp
@@ -0,0 +1,857 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+/* USB functions */
+
+#include <stdio.h>
+#include "Arduino.h"
+#include "Usb.h"
+
+
+#ifdef ARDUINO_SAM_ZERO
+
+static uint32_t usb_error = 0;
+static uint32_t usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
+
+/* constructor */
+USBHost::USBHost() : bmHubPre(0) {
+	// Set up state machine
+	usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
+}
+
+/* Initialize data structures */
+uint32_t USBHost::Init() {
+	//devConfigIndex	= 0;
+	// Init host stack
+	init();
+	bmHubPre		= 0;
+	UHD_Init();
+	return 0;
+}
+
+uint32_t USBHost::getUsbTaskState(void) {
+    return (usb_task_state);
+}
+
+void USBHost::setUsbTaskState(uint32_t state) {
+    usb_task_state = state;
+}
+
+EpInfo* USBHost::getEpInfoEntry(uint32_t addr, uint32_t ep) {
+	UsbDeviceDefinition *p = addrPool.GetUsbDevicePtr(addr);
+
+	if(!p || !p->epinfo)
+		return NULL;
+
+	EpInfo *pep = p->epinfo;
+
+	for (uint32_t i = 0; i < p->epcount; i++) {
+		if(pep->epAddr == ep)
+			return pep;
+
+		pep++;
+	}
+	return NULL;
+}
+
+/* set device table entry */
+
+/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
+uint32_t USBHost::setEpInfoEntry(uint32_t addr, uint32_t epcount, EpInfo* eprecord_ptr) {
+	if (!eprecord_ptr)
+		return USB_ERROR_INVALID_ARGUMENT;
+
+	UsbDeviceDefinition *p = addrPool.GetUsbDevicePtr(addr);
+
+	if(!p)
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+        p->address.devAddress = addr;
+	p->epinfo	= eprecord_ptr;
+	p->epcount	= epcount;
+
+	return 0;
+}
+
+uint32_t USBHost::SetPipeAddress(uint32_t addr, uint32_t ep, EpInfo **ppep, uint32_t &nak_limit) {
+	UsbDeviceDefinition *p = addrPool.GetUsbDevicePtr(addr);
+
+	if(!p)
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ 	if(!p->epinfo)
+		return USB_ERROR_EPINFO_IS_NULL;
+
+	*ppep = getEpInfoEntry(addr, ep);
+
+	if(!*ppep)
+		return USB_ERROR_EP_NOT_FOUND_IN_TBL;
+
+	nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
+	nak_limit--;
+	TRACE_USBHOST(printf("     => SetPipeAddress deviceEP=%lu configued as hostPIPE=%lu sending to address=%lu\r\n", ep, (*ppep)->epAddr, addr);)
+	/*
+          USBTRACE2("\r\nAddress: ", addr);
+          USBTRACE2(" EP: ", ep);
+          USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
+          USBTRACE2(" NAK Limit: ", nak_limit);
+          USBTRACE("\r\n");
+         */
+
+	// CTRL_PIPE.PDADDR: usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR = addr
+	uhd_configure_address((*ppep)->epAddr, addr); 	// Set peripheral address
+
+	return 0;
+}
+
+/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer,   */
+/* depending on request. Actual requests are defined as inlines                                                                                      */
+/* return codes:                */
+/* 00       =   success         */
+/* 01-0f    =   non-zero HRSLT  */
+uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
+                          uint16_t wInd, uint16_t total, uint32_t nbytes, uint8_t* dataptr, USBReadParser *p) {
+	
+	uint32_t direction = 0; // Request direction, IN or OUT
+	uint32_t rcode;
+	SETUP_PKT setup_pkt;
+
+	EpInfo *pep = NULL;
+	uint32_t nak_limit = 0;
+
+	TRACE_USBHOST(printf("    => ctrlReq\r\n");)
+
+	rcode = SetPipeAddress(addr, ep, &pep, nak_limit);
+	if(rcode)
+		return rcode;
+
+	// Allocate Pipe0 with default 64 bytes size if not already initialized
+	rcode = UHD_Pipe0_Alloc(0, 64);
+	if (rcode)
+	{
+		TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : EP0 allocation error: %lu\r\n", rcode);)
+		//USBTRACE2("\n\rUSBHost::ctrlReq : EP0 allocation error: ", rcode");
+		return rcode;
+	}
+
+	// Determine request direction
+	direction = ((bmReqType & 0x80 ) > 0);
+
+	/* fill in setup packet */
+    setup_pkt.ReqType_u.bmRequestType	= bmReqType;
+    setup_pkt.bRequest					= bRequest;
+    setup_pkt.wVal_u.wValueLo			= wValLo;
+    setup_pkt.wVal_u.wValueHi			= wValHi;
+    setup_pkt.wIndex					= wInd;
+    setup_pkt.wLength					= total;
+
+	UHD_Pipe_Write(pep->epAddr, sizeof(setup_pkt), (uint8_t *)&setup_pkt); //transfer to setup packet FIFO
+
+	rcode = dispatchPkt(tokSETUP, ep, nak_limit); // Dispatch packet
+
+	if (rcode) //return HRSLT if not zero
+		return ( rcode);
+
+	if (dataptr != NULL) //data stage, if present
+	{
+		if (direction) // IN transfer
+		{
+			uint32_t left = total;
+			TRACE_USBHOST(printf("    => ctrlData IN\r\n");)
+
+			pep->bmRcvToggle = 1; //bmRCVTOG1;
+
+			// Bytes read into buffer
+			uint32_t read = nbytes;
+
+			rcode = InTransfer(pep, nak_limit, (uint8_t*)&read, dataptr);
+
+			if((rcode&USB_ERROR_DATATOGGLE) == USB_ERROR_DATATOGGLE) {
+						// yes, we flip it wrong here so that next time it is actually correct!
+						//pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
+						pep->bmRcvToggle = USB_HOST_DTGL(pep->epAddr);
+						//continue;
+			}
+
+			if(rcode) {
+				//USBTRACE2("\n\rUSBHost::ctrlReq : in transfer: ", rcode");
+				return rcode;
+			}
+			// Invoke callback function if inTransfer completed successfully and callback function pointer is specified
+			if(!rcode && p)
+				((USBReadParser*)p)->Parse(read, dataptr, total - left);
+		}
+		else // OUT transfer
+		{			
+			pep->bmSndToggle = 1; //bmSNDTOG1;
+			rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
+		}
+		if(rcode) //return error
+			return (rcode);
+	}
+	
+	// Status stage
+	UHD_Pipe_CountZero(pep->epAddr);
+	USB->HOST.HostPipe[pep->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL;
+	return dispatchPkt((direction) ? tokOUTHS : tokINHS, pep->epAddr, nak_limit); //GET if direction
+}
+
+/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
+/* Keep sending INs and writes data to memory area pointed by 'data'                                                           */
+
+/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
+            fe USB xfer timeout */
+uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint8_t *nbytesptr, uint8_t* data) {
+	EpInfo *pep = NULL;
+	uint32_t nak_limit = 0;
+
+	uint32_t rcode = SetPipeAddress(addr, ep, &pep, nak_limit);
+
+        if(rcode) {
+                USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
+                USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
+                USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
+                return rcode;
+        }
+	return InTransfer(pep, nak_limit, nbytesptr, data);
+}
+
+uint32_t USBHost::InTransfer(EpInfo *pep, uint32_t nak_limit, uint8_t *nbytesptr, uint8_t* data) {
+	uint32_t rcode = 0;
+	uint32_t pktsize = 0;
+
+	uint32_t nbytes = *nbytesptr;
+	uint32_t maxpktsize = pep->maxPktSize;
+
+	*nbytesptr = 0;
+	//set toggle value
+	if(pep->bmRcvToggle)
+		USB->HOST.HostPipe[pep->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL;
+	else
+		USB->HOST.HostPipe[pep->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL;
+
+	usb_pipe_table[pep->epAddr].HostDescBank[0].ADDR.reg = (uint32_t)data;
+
+	// use a 'break' to exit this loop
+	while (1) {
+   		/* get pipe config from setting register */
+ 		usb_pipe_table[pep->epAddr].HostDescBank[0].ADDR.reg += pktsize;
+
+		rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
+		if(rcode == USB_ERROR_DATATOGGLE) {
+            // yes, we flip it wrong here so that next time it is actually correct!
+            //pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
+			pep->bmRcvToggle = USB_HOST_DTGL(pep->epAddr);
+            //set toggle value
+			if(pep->bmRcvToggle)
+				USB->HOST.HostPipe[pep->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL;
+			else
+				USB->HOST.HostPipe[pep->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL;
+            continue;
+		}
+        if(rcode) {
+                //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
+                return(rcode);// break; //should be 0, indicating ACK. Else return error code.
+        }
+        /* check for RCVDAVIRQ and generate error if not present */
+        /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
+				
+		pktsize = uhd_byte_count(pep->epAddr); // Number of received bytes
+		
+		USB->HOST.HostPipe[pep->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
+        
+		//printf("Got %i bytes \r\n", pktsize);
+		// This would be OK, but...
+		//assert(pktsize <= nbytes);
+		if(pktsize > nbytes) {
+			// This can happen. Use of assert on Arduino locks up the Arduino.
+			// So I will trim the value, and hope for the best.
+			//printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
+			pktsize = nbytes;
+		}
+
+		int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
+
+		if(mem_left < 0)
+			mem_left = 0;
+
+        //data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
+
+        //regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
+        *nbytesptr += pktsize;// add this packet's byte count to total transfer length
+
+        /* The transfer is complete under two conditions:           */
+        /* 1. The device sent a short packet (L.T. maxPacketSize)   */
+        /* 2. 'nbytes' have been transferred.                       */
+        if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
+		{					 
+            // Save toggle value
+            pep->bmRcvToggle = USB_HOST_DTGL(pep->epAddr);
+            //printf("\r\n");
+            rcode = 0;
+            break;
+		} // if
+	} //while( 1 )
+	return ( rcode);
+}
+
+/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
+/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer   */
+
+/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL                       */
+uint32_t USBHost::outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data) {
+	EpInfo *pep = NULL;
+	uint32_t nak_limit = 0;
+
+	uint32_t rcode = SetPipeAddress(addr, ep, &pep, nak_limit);
+
+	if(rcode)
+		return rcode;
+
+	return OutTransfer(pep, nak_limit, nbytes, data);
+}
+
+uint32_t USBHost::OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data) {
+	uint32_t rcode = 0, retry_count;
+	uint8_t *data_p = data; //local copy of the data pointer
+	uint32_t bytes_tosend, nak_count;
+	uint32_t bytes_left = nbytes;
+	uint8_t buf[64];
+	uint8_t i;
+
+	uint32_t maxpktsize = pep->maxPktSize;
+
+    if(maxpktsize < 1 || maxpktsize > 64)
+		return USB_ERROR_INVALID_MAX_PKT_SIZE;
+
+	for( i=0; i<nbytes; i++) {
+		buf[i] = data[i];
+	}
+	unsigned long timeout = millis() + USB_XFER_TIMEOUT;
+
+	//set toggle value
+	if(pep->bmSndToggle)
+		USB->HOST.HostPipe[pep->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL;
+	else
+		USB->HOST.HostPipe[pep->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL;
+
+	while(bytes_left) {
+		retry_count = 0;
+		nak_count = 0;
+		bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
+		UHD_Pipe_Write(pep->epAddr, bytes_tosend, buf); //filling output FIFO
+
+		//set number of bytes
+		//dispatch packet
+		//wait for the completion IRQ
+		//clear IRQ
+
+		rcode = dispatchPkt(tokOUT, pep->epAddr, nak_limit);
+		if (rcode)
+		{
+			switch(rcode) {
+				case USB_ERRORFLOW:
+					nak_count++;
+					if(nak_limit && (nak_count == nak_limit))
+							goto breakout;
+					return ( rcode);
+					break;
+				case USB_ERRORTIMEOUT:
+					retry_count++;
+					if(retry_count == USB_RETRY_LIMIT)
+							goto breakout;
+					return ( rcode);
+					break;
+				case USB_ERROR_DATATOGGLE:
+					// yes, we flip it wrong here so that next time it is actually correct!
+					pep->bmSndToggle = USB_HOST_DTGL(pep->epAddr);
+					//set toggle value
+					if(pep->bmSndToggle)
+						USB->HOST.HostPipe[pep->epAddr].PSTATUSSET.reg = USB_HOST_PSTATUSSET_DTGL;
+					else
+						USB->HOST.HostPipe[pep->epAddr].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL;
+					break;
+				default:
+						goto breakout;
+			}//switch( rcode
+		}
+
+		bytes_left -= bytes_tosend;
+		data_p += bytes_tosend;
+    }//while( bytes_left...
+breakout:
+
+    pep->bmSndToggle = USB_HOST_DTGL(pep->epAddr);
+    return ( rcode); //should be 0 in all cases
+}
+
+/* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty       */
+/* If NAK, tries to re-send up to nak_limit times                                                   */
+/* If nak_limit == 0, do not count NAKs, exit after timeout                                         */
+/* If bus timeout, re-sends up to USB_RETRY_LIMIT times                                             */
+
+/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */
+uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t epAddr, uint32_t nak_limit) {
+	uint32_t timeout = millis() + USB_XFER_TIMEOUT;
+	uint32_t nak_count = 0, retry_count=0;
+	uint32_t rcode = USB_ERROR_TRANSFER_TIMEOUT;
+
+	TRACE_USBHOST(printf("     => dispatchPkt token=%lu pipe=%lu nak_limit=%lu\r\n", token, epAddr, nak_limit);)
+
+	UHD_Pipe_Send(epAddr, token); //launch the transfer
+
+	// Check timeout but don't hold timeout if VBUS is lost
+	while ((timeout > millis()) && (UHD_GetVBUSState() == UHD_STATE_CONNECTED))
+	{
+		// Wait for transfer completion
+		if (UHD_Pipe_Is_Transfer_Complete(epAddr, token))
+		{
+			return 0;
+		}
+
+		//case hrNAK:
+		if( (usb_pipe_table[epAddr].HostDescBank[0].STATUS_BK.reg & USB_ERRORFLOW ) ) {
+			nak_count++;
+			if(nak_limit && (nak_count == nak_limit)) {
+				rcode = USB_ERRORFLOW;
+				return (rcode);
+			}
+		}
+
+		//case hrTIMEOUT:
+		if(usb_pipe_table[epAddr].HostDescBank[0].STATUS_PIPE.reg & USB_ERRORTIMEOUT) {
+			retry_count++;
+			if(retry_count == USB_RETRY_LIMIT)	{
+				rcode = USB_ERRORTIMEOUT;
+				return (rcode);
+			}
+		}
+
+		if( (usb_pipe_table[epAddr].HostDescBank[0].STATUS_PIPE.reg & USB_ERROR_DATATOGGLE ) ) {
+			rcode = USB_ERROR_DATATOGGLE;
+			return (rcode);
+		}
+	}
+
+	return rcode;
+}
+
+/* USB main task. Performs enumeration/cleanup */
+void USBHost::Task(void) //USB state machine
+{
+	uint32_t rcode = 0;
+	volatile uint32_t tmpdata = 0;
+	static uint32_t delay = 0;
+	//USB_DEVICE_DESCRIPTOR buf;
+	uint32_t lowspeed = 0;
+
+	// Update USB task state on Vbus change
+	tmpdata = UHD_GetVBUSState();
+
+	/* modify USB task state if Vbus changed */
+	switch (tmpdata)
+	{
+		case UHD_STATE_ERROR: //illegal state
+			usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
+			lowspeed = 0;
+			break;
+
+		case UHD_STATE_DISCONNECTED: // Disconnected state
+			if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
+				usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
+			lowspeed = 0;
+			break;
+
+		case UHD_STATE_CONNECTED: // Attached state
+			if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
+				delay = millis() + USB_SETTLE_DELAY;
+				usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
+			}
+			break;
+	}// switch( tmpdata
+
+	// Poll connected devices (if required)
+	for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
+		if (devConfig[i])
+			rcode = devConfig[i]->Poll();
+
+	// Perform USB enumeration stage and clean up
+	switch (usb_task_state) {
+		case USB_DETACHED_SUBSTATE_INITIALIZE:
+			TRACE_USBHOST(printf(" + USB_DETACHED_SUBSTATE_INITIALIZE\r\n");)
+
+			// Init USB stack and driver
+			UHD_Init();
+			init();
+
+			// Free all USB resources
+			for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
+			if (devConfig[i])
+				rcode = devConfig[i]->Release();
+
+			usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
+			break;
+		case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:  //just sit here
+			// Nothing to do
+			break;
+		case USB_DETACHED_SUBSTATE_ILLEGAL:  //just sit here
+			// Nothing to do
+			break;
+		case USB_ATTACHED_SUBSTATE_SETTLE: // Settle time for just attached device
+			if((long)(millis() - delay) >= 0L)
+				usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
+			break;
+		case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
+			TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_RESET_DEVICE\r\n");)
+			UHD_BusReset();  //issue bus reset
+			usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
+			break;
+		case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
+			if (Is_uhd_reset_sent())
+			{
+				TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE\r\n");)
+
+				// Clear Bus Reset flag
+				uhd_ack_reset_sent();
+
+				// Enable Start Of Frame generation
+				uhd_enable_sof();
+
+				usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
+
+				// Wait 20ms after Bus Reset (USB spec)
+				delay = millis() + 20;
+			}
+			break;
+		case USB_ATTACHED_SUBSTATE_WAIT_SOF:
+			// Wait for SOF received first
+			if (Is_uhd_sof())
+			{
+				if (delay < millis())
+				{
+					TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_SOF\r\n");)
+
+					// 20ms waiting elapsed
+					usb_task_state = USB_STATE_CONFIGURING;
+				}
+			}
+			break;
+		case USB_STATE_CONFIGURING:
+			TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING\r\n");)
+			rcode = Configuring(0, 0, lowspeed);
+
+			if (rcode) {
+				TRACE_USBHOST(printf("/!\\ USBHost::Task : USB_STATE_CONFIGURING failed with code: %lu\r\n", rcode);)
+				if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
+					usb_error = rcode;
+					usb_task_state = USB_STATE_ERROR;
+				}
+			}
+			else {
+				usb_task_state = USB_STATE_RUNNING;
+				TRACE_USBHOST(printf(" + USB_STATE_RUNNING\r\n");)
+			}
+			break;
+		case USB_STATE_RUNNING:
+			break;
+		case USB_STATE_ERROR:
+			break;
+	} // switch( usb_task_state )
+}
+
+uint32_t USBHost::DefaultAddressing(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+        //uint8_t		buf[12];
+	uint32_t rcode = 0;
+	UsbDeviceDefinition *p0 = NULL, *p = NULL;
+
+	// Get pointer to pseudo device with address 0 assigned
+	p0 = addrPool.GetUsbDevicePtr(0);
+
+	if(!p0)
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+	if(!p0->epinfo)
+		return USB_ERROR_EPINFO_IS_NULL;
+
+	p0->lowspeed = (lowspeed) ? 1 : 0;
+
+	// Allocate new address according to device class
+	uint32_t bAddress = addrPool.AllocAddress(parent, 0, port);
+
+	if(!bAddress)
+		return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+	p = addrPool.GetUsbDevicePtr(bAddress);
+
+	if(!p)
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+	p->lowspeed = lowspeed;
+
+	// Assign new address to the device
+	rcode = setAddr(0, 0, bAddress);
+
+	if(rcode) {
+		TRACE_USBHOST(printf("/!\\ USBHost::DefaultAddressing : Set address failed with code: %lu\r\n", rcode);)
+		addrPool.FreeAddress(bAddress);
+		bAddress = 0;
+		return rcode;
+	}
+	return 0;
+}
+
+uint32_t USBHost::AttemptConfig(uint32_t driver, uint32_t parent, uint32_t port, uint32_t lowspeed) {
+        //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
+        uint8_t retries = 0;
+
+again:
+        uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
+        if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {
+                if(parent == 0) {
+                        // Send a bus reset on the root interface.
+                        //regWr(rHCTL, bmBUSRST); //issue bus reset
+                        UHD_BusReset();
+                        delay(102); // delay 102ms, compensate for clock inaccuracy.
+                } else {
+                        // reset parent port
+                        devConfig[parent]->ResetHubPort(port);
+                }
+        } else if(rcode != 0x00/*hrJERR*/ && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
+                delay(100);
+                retries++;
+                goto again;
+        } else if(rcode)
+                return rcode;
+
+        rcode = devConfig[driver]->Init(parent, port, lowspeed);
+        if(rcode != 0x00/*hrJERR*/ && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
+                delay(100);
+                retries++;
+                goto again;
+        }
+        if(rcode) {
+                // Issue a bus reset, because the device may be in a limbo state
+                if(parent == 0) {
+                        // Send a bus reset on the root interface.
+                        //regWr(rHCTL, bmBUSRST); //issue bus reset
+                        UHD_BusReset();
+                        delay(102); // delay 102ms, compensate for clock inaccuracy.
+                } else {
+                        // reset parent port
+                        devConfig[parent]->ResetHubPort(port);
+                }
+        }
+        return rcode;
+}
+
+/*
+ * This is broken. We need to enumerate differently.
+ * It causes major problems with several devices if detected in an unexpected order.
+ *
+ *
+ * Oleg - I wouldn't do anything before the newly connected device is considered sane.
+ * i.e.(delays are not indicated for brevity):
+ * 1. reset
+ * 2. GetDevDescr();
+ * 3a. If ACK, continue with allocating address, addressing, etc.
+ * 3b. Else reset again, count resets, stop at some number (5?).
+ * 4. When max.number of resets is reached, toggle power/fail
+ * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
+ * it doesn't need to be reset again
+ * New steps proposal:
+ * 1: get address pool instance. exit on fail
+ * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
+ * 3: bus reset, 100ms delay
+ * 4: set address
+ * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
+ * 6: while (configurations) {
+ *              for(each configuration) {
+ *                      for (each driver) {
+ *                              6a: Ask device if it likes configuration. Returns 0 on OK.
+ *                                      If successful, the driver configured device.
+ *                                      The driver now owns the endpoints, and takes over managing them.
+ *                                      The following will need codes:
+ *                                          Everything went well, instance consumed, exit with success.
+ *                                          Instance already in use, ignore it, try next driver.
+ *                                          Not a supported device, ignore it, try next driver.
+ *                                          Not a supported configuration for this device, ignore it, try next driver.
+ *                                          Could not configure device, fatal, exit with fail.
+ *                      }
+ *              }
+ *    }
+ * 7: for(each driver) {
+ *      7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
+ * 8: if we get here, no driver likes the device plugged in, so exit failure.
+ *
+ */
+uint32_t USBHost::Configuring(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+       //uint32_t bAddress = 0;
+        //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
+        uint32_t devConfigIndex;
+        uint32_t rcode = 0;
+        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+        USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
+        UsbDeviceDefinition *p = NULL;
+        EpInfo *oldep_ptr = NULL;
+        EpInfo epInfo;
+
+        epInfo.epAddr = 0;
+        epInfo.maxPktSize = 8;
+        epInfo.epAttribs = 0;
+        epInfo.bmNakPower = USB_NAK_MAX_POWER;
+
+        //delay(2000);
+        AddressPool &addrPool = GetAddressPool();
+        // Get pointer to pseudo device with address 0 assigned
+        p = addrPool.GetUsbDevicePtr(0);
+        if(!p) {
+                //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
+                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+        }
+
+        // Save old pointer to EP_RECORD of address 0
+        oldep_ptr = p->epinfo;
+
+        // Temporary assign new pointer to epInfo to p->epinfo in order to
+        // avoid toggle inconsistence
+
+        p->epinfo = &epInfo;
+
+        p->lowspeed = lowspeed;
+        // Get device descriptor
+        rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+        // The first GetDescriptor give us the endpoint 0 max packet size.
+        epInfo.maxPktSize = buf[7];
+        // Restore p->epinfo
+        p->epinfo = oldep_ptr;
+
+        if(rcode) {
+                //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
+                return rcode;
+        }
+
+        // to-do?
+        // Allocate new address according to device class
+        //bAddress = addrPool.AllocAddress(parent, false, port);
+
+        //if (!bAddress)
+        //        return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+        uint16_t vid = udd->idVendor;
+        uint16_t pid = udd->idProduct;
+        uint8_t klass = udd->bDeviceClass;
+
+        // Attempt to configure if VID/PID or device class matches with a driver
+        for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
+                if(!devConfig[devConfigIndex]) continue; // no driver
+                if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
+                if(devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) {
+                        rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
+                        if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
+                                break;
+                }
+        }
+
+        if(devConfigIndex < USB_NUMDEVICES) {
+                return rcode;
+        }
+
+
+        // blindly attempt to configure
+        for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
+                if(!devConfig[devConfigIndex]) continue;
+                if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
+                if(devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
+                rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
+
+                //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
+                if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
+                        // in case of an error dev_index should be reset to 0
+                        //		in order to start from the very beginning the
+                        //		next time the program gets here
+                        //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
+                        //        devConfigIndex = 0;
+                        return rcode;
+                }
+	}
+        // if we get here that means that the device class is not supported by any of registered classes
+	rcode = DefaultAddressing(parent, port, lowspeed);
+
+	return rcode;
+}
+
+uint32_t USBHost::ReleaseDevice(uint32_t addr) {
+	if(!addr)
+		return 0;
+
+	for(uint32_t i = 0; i < USB_NUMDEVICES; i++) {
+                if(!devConfig[i]) continue;
+		if(devConfig[i]->GetAddress() == addr)
+			return devConfig[i]->Release();
+	}
+	return 0;
+}
+
+//get device descriptor
+
+uint32_t USBHost::getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr) {
+    return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, 0));
+}
+//get configuration descriptor
+
+uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t conf, uint8_t* dataptr) {
+	return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, 0));
+}
+
+/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
+ total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
+uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t conf, USBReadParser *p) {
+	const uint32_t bufSize = 64;
+	uint8_t buf[bufSize];
+	USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
+
+	uint32_t ret = getConfDescr(addr, ep, 9, conf, buf);
+
+	if(ret)
+		return ret;
+
+        uint32_t total = ucd->wTotalLength;
+
+        //USBTRACE2("\r\ntotal conf.size:", total);
+
+        return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
+}
+
+//get string descriptor
+
+uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t index, uint32_t langid, uint8_t* dataptr) {
+    return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, nbytes, dataptr, 0));
+}
+//set address
+
+uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr) {
+        uint32_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
+        //delay(2); //per USB 2.0 sect.9.2.6.3
+        delay(300); // Older spec says you should wait at least 200ms
+        return rcode;
+        //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
+}
+//set configuration
+
+uint32_t USBHost::setConf(uint32_t addr, uint32_t ep, uint32_t conf_value) {
+        return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
+}
+
+#endif //ARDUINO_SAM_ZERO
diff --git a/libraries/USBHost/src/Usb.h b/libraries/USBHost/src/Usb.h
new file mode 100644
index 0000000000000000000000000000000000000000..40bed77ed4b8e1cfb0f6e06adbdf667c327fd282
--- /dev/null
+++ b/libraries/USBHost/src/Usb.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+/* USB functions */
+
+#ifndef USB_H_INCLUDED
+#define USB_H_INCLUDED
+#define _usb_h_
+
+#include <stdint.h>
+
+#define ARDUINO   101
+
+//#include "Arduino.h"
+#include "macros.h"
+// None of these should ever be included by a driver, or a user's sketch.
+
+#include "variant.h"
+#define USB_HOST_SERIAL SERIAL_PORT_MONITOR
+#include "Print.h"
+#include "printhex.h"
+#include "message.h"
+#include "hexdump.h"
+#include "sink_parser.h"
+
+#include "address.h"
+
+#include "usb_ch9.h"
+//#include "usbhost.h"
+#include "UsbCore.h"
+#include "parsetools.h"
+
+#include "confdescparser.h"
+
+#endif /* USB_H_INCLUDED */
diff --git a/libraries/USBHost/src/UsbCore.h b/libraries/USBHost/src/UsbCore.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdb14c1c14a02941c30f72421367551fe705501a
--- /dev/null
+++ b/libraries/USBHost/src/UsbCore.h
@@ -0,0 +1,291 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(USBCORE_H)
+#error "Never include UsbCore.h directly; include Usb.h instead"
+#else
+#define	USBCORE_H
+
+// Not used anymore? If anyone uses this, please let us know so that this may be
+// moved to the proper place, settings.h.
+//#define USB_METHODS_INLINE
+
+/* shield pins. First parameter - SS pin, second parameter - INT pin */
+#ifdef BOARD_BLACK_WIDDOW
+typedef MAX3421e<P6, P3> MAX3421E; // Black Widow
+#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
+#if EXT_RAM
+typedef MAX3421e<P20, P7> MAX3421E; // Teensy++ 2.0 with XMEM2
+#else
+typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 1.0 and 2.0
+#endif
+#elif defined(BOARD_MEGA_ADK)
+typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK
+#elif defined(ARDUINO_AVR_BALANDUINO)
+typedef MAX3421e<P20, P19> MAX3421E; // Balanduino
+#else
+//typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.) or Teensy 2.0 and 3.0
+#endif
+
+/* Common setup data constant combinations  */
+#define bmREQ_GET_DESCR     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE     //get descriptor request type
+#define bmREQ_SET           USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE     //set request type for all but 'set feature' and 'set interface'
+#define bmREQ_CL_GET_INTF   USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE     //get interface request type
+
+// D7		data transfer direction (0 - host-to-device, 1 - device-to-host)
+// D6-5		Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
+// D4-0		Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
+
+// USB Device Classes
+#define USB_CLASS_USE_CLASS_INFO	0x00	// Use Class Info in the Interface Descriptors
+#define USB_CLASS_AUDIO			0x01	// Audio
+#define USB_CLASS_COM_AND_CDC_CTRL	0x02	// Communications and CDC Control
+#define USB_CLASS_HID			0x03	// HID
+#define USB_CLASS_PHYSICAL		0x05	// Physical
+#define USB_CLASS_IMAGE			0x06	// Image
+#define USB_CLASS_PRINTER		0x07	// Printer
+#define USB_CLASS_MASS_STORAGE		0x08	// Mass Storage
+#define USB_CLASS_HUB			0x09	// Hub
+#define USB_CLASS_CDC_DATA		0x0a	// CDC-Data
+#define USB_CLASS_SMART_CARD		0x0b	// Smart-Card
+#define USB_CLASS_CONTENT_SECURITY	0x0d	// Content Security
+#define USB_CLASS_VIDEO			0x0e	// Video
+#define USB_CLASS_PERSONAL_HEALTH	0x0f	// Personal Healthcare
+#define USB_CLASS_DIAGNOSTIC_DEVICE	0xdc	// Diagnostic Device
+#define USB_CLASS_WIRELESS_CTRL		0xe0	// Wireless Controller
+#define USB_CLASS_MISC			0xef	// Miscellaneous
+#define USB_CLASS_APP_SPECIFIC		0xfe	// Application Specific
+#define USB_CLASS_VENDOR_SPECIFIC	0xff	// Vendor Specific
+
+// Additional Error Codes
+#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED	0xD1
+#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE	0xD2
+#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS	0xD3
+#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL		0xD4
+#define USB_ERROR_HUB_ADDRESS_OVERFLOW			0xD5
+#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL		0xD6
+#define USB_ERROR_EPINFO_IS_NULL			0xD7
+#define USB_ERROR_INVALID_ARGUMENT			0xD8
+#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE		0xD9
+#define USB_ERROR_INVALID_MAX_PKT_SIZE			0xDA
+#define USB_ERROR_EP_NOT_FOUND_IN_TBL			0xDB
+#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET      0xE0
+#define USB_ERROR_FailGetDevDescr                       0xE1
+#define USB_ERROR_FailSetDevTblEntry                    0xE2
+#define USB_ERROR_FailGetConfDescr                      0xE3
+#define USB_ERROR_TRANSFER_TIMEOUT			0xFF
+
+#define USB_XFER_TIMEOUT        10000 //30000    // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
+//#define USB_NAK_LIMIT		32000   //NAK limit for a transfer. 0 means NAKs are not counted
+#define USB_RETRY_LIMIT		3       // 3 retry limit for a transfer
+#define USB_SETTLE_DELAY	200     //settle delay in milliseconds
+
+#define USB_NUMDEVICES		16	//number of USB devices
+//#define HUB_MAX_HUBS		7	// maximum number of hubs that can be attached to the host controller
+#define HUB_PORT_RESET_DELAY	20	// hub port reset delay 10 ms recomended, can be up to 20 ms
+
+/* USB state machine states */
+#define USB_STATE_MASK                                      0xf0
+
+#define USB_STATE_DETACHED                                  0x10
+#define USB_DETACHED_SUBSTATE_INITIALIZE                    0x11
+#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE               0x12
+#define USB_DETACHED_SUBSTATE_ILLEGAL                       0x13
+#define USB_ATTACHED_SUBSTATE_SETTLE                        0x20
+#define USB_ATTACHED_SUBSTATE_RESET_DEVICE                  0x30
+#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE           0x40
+#define USB_ATTACHED_SUBSTATE_WAIT_SOF                      0x50
+#define USB_ATTACHED_SUBSTATE_WAIT_RESET                    0x51
+#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE    0x60
+#define USB_STATE_ADDRESSING                                0x70
+#define USB_STATE_CONFIGURING                               0x80
+#define USB_STATE_RUNNING                                   0x90
+#define USB_STATE_ERROR                                     0xa0
+
+class USBDeviceConfig {
+public:
+
+        virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+                return 0;
+        }
+
+        virtual uint32_t ConfigureDevice(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+                return 0;
+        }
+
+        virtual uint32_t Release() {
+                return 0;
+        }
+
+        virtual uint32_t Poll() {
+                return 0;
+        }
+
+        virtual uint32_t GetAddress() {
+                return 0;
+        }
+
+        virtual void ResetHubPort(uint32_t port) {
+                return;
+        } // Note used for hubs only!
+
+        virtual uint32_t VIDPIDOK(uint32_t vid, uint32_t pid) {
+                return false;
+        }
+
+        virtual uint32_t DEVCLASSOK(uint32_t klass) {
+                return false;
+        }
+};
+
+/* USB Setup Packet Structure   */
+typedef struct {
+
+        union { // offset   description
+                uint8_t bmRequestType; //   0      Bit-map of request type
+
+                struct {
+                        uint8_t recipient : 5; //          Recipient of the request
+                        uint8_t type : 2; //          Type of request
+                        uint8_t direction : 1; //          Direction of data X-fer
+                };
+        } ReqType_u;
+        uint8_t bRequest; //   1      Request
+
+        union {
+                uint16_t wValue; //   2      Depends on bRequest
+
+                struct {
+                        uint8_t wValueLo;
+                        uint8_t wValueHi;
+                };
+        } wVal_u;
+        uint16_t wIndex; //   4      Depends on bRequest
+        uint16_t wLength; //   6      Depends on bRequest
+} SETUP_PKT, *PSETUP_PKT;
+
+
+
+// Base class for incoming data parser
+
+class USBReadParser {
+public:
+        virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) = 0;
+};
+
+class USBHost {
+        AddressPoolImpl<USB_NUMDEVICES> addrPool;
+        USBDeviceConfig* devConfig[USB_NUMDEVICES];
+        uint8_t bmHubPre;
+
+public:
+        USBHost(void);
+
+        void SetHubPreMask() {
+                //bmHubPre |= bmHUBPRE;
+        };
+
+        void ResetHubPreMask() {
+                //bmHubPre &= (~bmHUBPRE);
+        };
+
+        AddressPool& GetAddressPool() {
+                return (AddressPool&)addrPool;
+        };
+
+        uint32_t RegisterDeviceClass(USBDeviceConfig *pdev) {
+                for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
+                        if(!devConfig[i]) {
+                                devConfig[i] = pdev;
+                                return 0;
+                        }
+                }
+                return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
+        };
+
+        void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
+                addrPool.ForEachUsbDevice(pfunc);
+        };
+        uint32_t getUsbTaskState(void);
+        void setUsbTaskState(uint32_t state);
+
+        EpInfo* getEpInfoEntry(uint32_t addr, uint32_t ep);
+        uint32_t setEpInfoEntry(uint32_t addr, uint32_t epcount, EpInfo* eprecord_ptr);
+
+        /* Control requests */
+        uint32_t getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr);
+        uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t conf, uint8_t* dataptr);
+
+        uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t conf, USBReadParser *p);
+
+        uint32_t getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t index, uint32_t langid, uint8_t* dataptr);
+        uint32_t setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr);
+        uint32_t setConf(uint32_t addr, uint32_t ep, uint32_t conf_value);
+        /**/
+        uint32_t ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t direction);
+        uint32_t ctrlStatus(uint32_t ep, uint32_t direction, uint32_t nak_limit);
+        uint32_t inTransfer(uint32_t addr, uint32_t ep, uint8_t *nbytesptr, uint8_t* data);
+        uint32_t outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data);
+        uint32_t dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit);
+
+        void Task(void);
+
+        uint32_t DefaultAddressing(uint32_t parent, uint32_t port, uint32_t lowspeed);
+        uint32_t Configuring(uint32_t parent, uint32_t port, uint32_t lowspeed);
+        uint32_t ReleaseDevice(uint32_t addr);
+
+        uint32_t ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
+                uint16_t wInd, uint16_t total, uint32_t nbytes, uint8_t* dataptr, USBReadParser *p);
+
+        uint32_t Init();
+private:
+        uint32_t SetPipeAddress(uint32_t addr, uint32_t ep, EpInfo **ppep, uint32_t &nak_limit);
+        uint32_t OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data);
+        uint32_t InTransfer(EpInfo *pep, uint32_t nak_limit, uint8_t *nbytesptr, uint8_t *data);
+        uint32_t AttemptConfig(uint32_t driver, uint32_t parent, uint32_t port, uint32_t lowspeed);
+};
+
+#if 0 //defined(USB_METHODS_INLINE)
+//get device descriptor
+
+inline uint8_t USBHost::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
+        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
+}
+//get configuration descriptor
+
+inline uint8_t USBHost::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
+        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
+}
+//get string descriptor
+
+inline uint8_t USBHost::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {
+        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
+}
+//set address
+
+inline uint8_t USBHost::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
+        return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
+}
+//set configuration
+
+inline uint8_t USBHost::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
+        return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
+}
+
+#endif // defined(USB_METHODS_INLINE)
+
+#endif	/* USBCORE_H */
diff --git a/libraries/USBHost/src/address.h b/libraries/USBHost/src/address.h
new file mode 100644
index 0000000000000000000000000000000000000000..a96108224f837b6a6a50d5a0f094f1a135344812
--- /dev/null
+++ b/libraries/USBHost/src/address.h
@@ -0,0 +1,280 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+#if !defined(_usb_h_) || defined(ADDRESS_H_INCLUDED)
+#error "Never include address.h directly; include Usb.h instead"
+#else
+#define ADDRESS_H_INCLUDED
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
+/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
+#define USB_NAK_MAX_POWER		15		//NAK binary order maximum value
+#define USB_NAK_DEFAULT			14		//default 32K-1 NAKs before giving up
+#define USB_NAK_NOWAIT			1		//Single NAK stops transfer
+#define USB_NAK_NONAK			0		//Do not count NAKs, stop retrying after USB Timeout
+
+struct EpInfo {
+	uint32_t epAddr; // Endpoint address
+	uint32_t maxPktSize; // Maximum packet size
+	union {
+		uint8_t		epAttribs;
+
+		struct {
+			uint8_t		bmSndToggle	:	1;		// Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
+			uint8_t		bmRcvToggle	:	1;		// Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
+			uint8_t		bmNakPower	:	6;		// Binary order for NAK_LIMIT value
+                };
+	};
+};
+
+//	  7   6   5   4   3   2   1   0
+//  ---------------------------------
+//  |   | H | P | P | P | A | A | A |
+//  ---------------------------------
+//
+// H - if 1 the address is a hub address
+// P - parent hub address
+// A - device address / port number in case of hub
+//
+
+struct UsbDeviceAddress {
+	union {
+		struct {
+			uint32_t		bmAddress	: 3;	// device address/port number
+			uint32_t		bmParent	: 3;	// parent hub address
+			uint32_t		bmHub		: 1;	// hub flag
+			uint32_t		bmReserved	: 25;	// reserved, must be zerro
+		};
+		uint32_t devAddress;
+	};
+};
+
+#define bmUSB_DEV_ADDR_ADDRESS		0x07
+#define bmUSB_DEV_ADDR_PARENT		0x38
+#define bmUSB_DEV_ADDR_HUB		0x40
+
+struct UsbDeviceDefinition {
+	EpInfo			*epinfo;		// endpoint info pointer
+	UsbDeviceAddress	address;
+	uint32_t		epcount;		// number of endpoints
+	uint32_t		lowspeed;		// indicates if a device is the low speed one
+	//	uint8_t			devclass;		// device class
+};
+
+class AddressPool {
+public:
+	virtual UsbDeviceDefinition* GetUsbDevicePtr(uint32_t addr) = 0;
+	virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) = 0;
+	virtual void FreeAddress(uint32_t addr) = 0;
+};
+
+typedef void (*UsbDeviceHandleFunc)(UsbDeviceDefinition *pdev);
+
+#define ADDR_ERROR_INVALID_INDEX		0xFF
+#define ADDR_ERROR_INVALID_ADDRESS		0xFF
+
+template <const uint32_t MAX_DEVICES_ALLOWED>
+class AddressPoolImpl : public AddressPool {
+	EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
+
+	uint32_t hubCounter; // hub counter is kept
+	// in order to avoid hub address duplication
+
+	UsbDeviceDefinition thePool[MAX_DEVICES_ALLOWED];
+
+	// Initializes address pool entry
+
+	void InitEntry(uint32_t index) {
+		thePool[index].address.devAddress = 0;
+		thePool[index].epcount = 1;
+		thePool[index].lowspeed = 0;
+		thePool[index].epinfo = &dev0ep;
+	};
+
+	// Returns thePool index for a given address
+
+	uint32_t FindAddressIndex(uint32_t address = 0) {
+		for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
+			if(thePool[i].address.devAddress == address)
+				return i;
+		}
+		return 0;
+	};
+
+	// Returns thePool child index for a given parent
+
+	uint32_t FindChildIndex(UsbDeviceAddress addr, uint32_t start = 1) {
+		for (uint32_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
+			if(thePool[i].address.bmParent == addr.bmAddress)
+				return i;
+	}
+	return 0;
+	};
+
+	// Frees address entry specified by index parameter
+
+	void FreeAddressByIndex(uint32_t index) {
+		// Zero field is reserved and should not be affected
+		if(index == 0)
+			return;
+
+		UsbDeviceAddress uda = thePool[index].address;
+		// If a hub was switched off all port addresses should be freed
+		if(uda.bmHub == 1) {
+			for (uint32_t i = 1; (i = FindChildIndex(uda, i));)
+				FreeAddressByIndex(i);
+
+			// If the hub had the last allocated address, hubCounter should be decremented
+			if(hubCounter == uda.bmAddress)
+				hubCounter--;
+		}
+		InitEntry(index);
+	}
+
+	// Initializes the whole address pool at once
+
+	void InitAllAddresses() {
+		for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
+			InitEntry(i);
+
+		hubCounter = 0;
+	};
+
+public:
+
+	AddressPoolImpl() : hubCounter(0) {
+		// Zero address is reserved
+		InitEntry(0);
+
+		thePool[0].address.devAddress = 0;
+		thePool[0].epinfo = &dev0ep;
+		dev0ep.epAddr = 0;
+		dev0ep.maxPktSize = 8;
+		dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
+		dev0ep.bmNakPower = USB_NAK_MAX_POWER;
+
+		InitAllAddresses();
+	};
+
+	// Returns a pointer to a specified address entry
+
+	virtual UsbDeviceDefinition* GetUsbDevicePtr(uint32_t addr) {
+		if(!addr)
+			return thePool;
+
+		uint32_t index = FindAddressIndex(addr);
+
+		return (!index) ? NULL : thePool + index;
+	};
+
+        // Performs an operation specified by pfunc for each addressed device
+
+	void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
+		if(!pfunc)
+			return;
+
+		for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
+			if(thePool[i].address.devAddress)
+				pfunc(thePool + i);
+	};
+
+	// Allocates new address
+
+	virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) {
+		/* if (parent != 0 && port == 0)
+				USB_HOST_SERIAL.println("PRT:0"); */
+		UsbDeviceAddress _parent;
+		_parent.devAddress = parent;
+		if(_parent.bmReserved || port > 7)
+			//if(parent > 127 || port > 7)
+			return 0;
+
+		if(is_hub && hubCounter == 7)
+			return 0;
+
+		// finds first empty address entry starting from one
+		uint32_t index = FindAddressIndex(0);
+
+		if(!index) // if empty entry is not found
+			return 0;
+
+		if(_parent.devAddress == 0) {
+			if(is_hub) {
+				thePool[index].address.devAddress = 0x41;
+				hubCounter++;
+			} else
+				thePool[index].address.devAddress = 1;
+
+			return thePool[index].address.devAddress;
+		}
+
+		UsbDeviceAddress addr;
+		addr.devAddress = 0; // Ensure all bits are zero
+		addr.bmParent = _parent.bmAddress;
+		if(is_hub) {
+			addr.bmHub = 1;
+			addr.bmAddress = ++hubCounter;
+		} else {
+			addr.bmHub = 0;
+			addr.bmAddress = port;
+		}
+		thePool[index].address = addr;
+		/*
+		USB_HOST_SERIAL.print("Addr:");
+		USB_HOST_SERIAL.print(addr.bmHub, HEX);
+		USB_HOST_SERIAL.print(".");
+		USB_HOST_SERIAL.print(addr.bmParent, HEX);
+		USB_HOST_SERIAL.print(".");
+		USB_HOST_SERIAL.println(addr.bmAddress, HEX);
+		*/
+		return thePool[index].address.devAddress;
+	};
+
+    // Empties pool entry
+
+	virtual void FreeAddress(uint32_t addr) {
+		// if the root hub is disconnected all the addresses should be initialized
+		if(addr == 0x41) {
+			InitAllAddresses();
+			return;
+		}
+		uint32_t index = FindAddressIndex(addr);
+		FreeAddressByIndex(index);
+	};
+
+	// Returns number of hubs attached
+	// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
+	//uint32_t GetNumHubs()
+	//{
+	//	return hubCounter;
+	//};
+	//uint32_t GetNumDevices()
+	//{
+	//	uint32_t counter = 0;
+
+	//	for (uint32_t i=1; i<MAX_DEVICES_ALLOWED; i++)
+	//		if (thePool[i].address != 0);
+	//			counter++;
+
+	//	return counter;
+	//};
+};
+
+#endif /* ADDRESS_H_INCLUDED */
diff --git a/libraries/USBHost/src/adk.cpp b/libraries/USBHost/src/adk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e271cb4a4b654205092adabe1f2fc53b12b12622
--- /dev/null
+++ b/libraries/USBHost/src/adk.cpp
@@ -0,0 +1,410 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+/* Google ADK interface */
+
+#include "adk.h"
+
+const uint32_t ADK::epDataInIndex  = 1;
+const uint32_t ADK::epDataOutIndex = 2;
+
+ADK::ADK(USBHost *p, const char* manufacturer,
+        const char* model,
+        const char* description,
+        const char* version,
+        const char* uri,
+        const char* serial) :
+
+/* ADK ID Strings */
+manufacturer(manufacturer),
+model(model),
+description(description),
+version(version),
+uri(uri),
+serial(serial),
+pUsb(p), //pointer to USB class instance - mandatory
+bAddress(0), //device address - mandatory
+bConfNum(0), //configuration number
+bNumEP(1), //if config descriptor needs to be parsed
+ready(false) {
+        // initialize endpoint data structures
+	for (uint32_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
+		epInfo[i].epAddr	= 0;
+		epInfo[i].maxPktSize	= (i) ? 0 : 8;
+		epInfo[i].epAttribs		= 0;
+		epInfo[i].bmNakPower  	= (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+        }//for(uint32_t i=0; i<ADK_MAX_ENDPOINTS; i++...
+
+        // register in USB subsystem
+        if(pUsb) {
+                pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+        }
+}
+
+uint32_t ADK::ConfigureDevice(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+        return Init(parent, port, lowspeed); // Just call Init. Yes, really!
+}
+
+/* Connection initialization of an Android phone */
+uint32_t ADK::Init(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+        uint32_t rcode;
+        uint32_t num_of_conf; // number of configurations
+        UsbDeviceDefinition *p = NULL;
+        EpInfo *oldep_ptr = NULL;
+
+        // get memory address of USB device address pool
+        AddressPool &addrPool = pUsb->GetAddressPool();
+
+        USBTRACE("\r\nADK Init");
+
+        // check if address has already been assigned to an instance
+        if(bAddress) {
+                USBTRACE("\r\nAddress in use");
+                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+        }
+
+        // Get pointer to pseudo device with address 0 assigned
+        p = addrPool.GetUsbDevicePtr(0);
+
+        if(!p) {
+                USBTRACE("\r\nAddress not found");
+                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+        }
+
+        if(!p->epinfo) {
+                USBTRACE("epinfo is null\r\n");
+                return USB_ERROR_EPINFO_IS_NULL;
+        }
+
+	// Save old pointer to EP_RECORD of address 0
+	oldep_ptr = p->epinfo;
+
+	// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+	p->epinfo = epInfo;
+
+	p->lowspeed = lowspeed;
+
+	// Get device descriptor  GET_DESCRIPTOR
+	rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+
+	// Restore p->epinfo
+	p->epinfo = oldep_ptr;
+
+	if(rcode) {
+        USBTRACE("\r\nGetDevDesc1 Error ");
+		goto FailGetDevDescr;
+	}
+
+	// Reset
+	UHD_BusReset();
+	while( Is_uhd_starting_reset() ) {}
+
+	// Allocate new address according to device class
+	bAddress = addrPool.AllocAddress(parent, false, port);
+	if (!bAddress)
+		return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+
+	// Extract Max Packet Size from device descriptor
+	epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+	// Assign new address to the device  SET_ADDRESS
+	rcode = pUsb->setAddr(0, 0, bAddress);
+	if(rcode) {
+        USBTRACE("\r\nsetAddr Error ");
+		p->lowspeed = false;
+		addrPool.FreeAddress(bAddress);
+		bAddress = 0;
+		TRACE_USBHOST(printf("ADK::Init : setAddr failed with rcode %lu\r\n", rcode);)
+		return rcode;
+    }//if (rcode...
+
+    USBTRACE2("\r\nAddr:", bAddress);
+    // Spec says you should wait at least 200ms.
+    //delay(300);
+
+ 	// Save old pointer to EP_RECORD of address 0
+	oldep_ptr = p->epinfo;
+	// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+	p->epinfo = epInfo;
+	// Get device descriptor  GET_DESCRIPTOR
+	rcode = pUsb->getDevDescr(bAddress, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+	// Restore p->epinfo
+	p->epinfo = oldep_ptr;
+	if (rcode)
+	{
+        USBTRACE("\r\nGetDevDesc2 Error ");
+		goto FailGetDevDescr;
+	}
+
+	TRACE_USBHOST(printf("ADK::Init : device address is now %lu\r\n", bAddress);)
+
+	p->lowspeed = false;
+
+	//get pointer to assigned address record
+	p = addrPool.GetUsbDevicePtr(bAddress);
+	if(!p) {
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+	}
+
+	p->lowspeed = lowspeed;
+
+	// Assign epInfo to epinfo pointer - only EP0 is known
+	rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+	if(rcode) {
+		goto FailSetDevTblEntry;
+	}
+
+	//check if ADK device is already in accessory mode; if yes, configure and exit
+	if(udd->idVendor == ADK_VID &&
+			(udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) {
+		USBTRACE("\r\nAcc.mode device detected");
+		/* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
+		num_of_conf = udd->bNumConfigurations;
+
+		USBTRACE2("\r\nNC:",num_of_conf);
+		for (uint32_t i = 0; i < num_of_conf; i++) {
+			ConfigDescParser<0, 0, 0, 0> confDescrParser(this);
+
+			delay(1);
+			rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+
+#if defined(XOOM)
+			//added by Jaylen Scott Vanorden
+			if(rcode) {
+				TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
+
+				// Try once more
+				rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+			}
+#endif
+			if(rcode) {
+				goto FailGetConfDescr;
+			}
+			if(bNumEP > 2) {
+				break;
+			}
+		} // for (uint32_t i=0; i<num_of_conf; i++...
+
+ 		if(bNumEP == 3) {
+			// Assign epInfo to epinfo pointer - this time all 3 endpoins
+			rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
+			if(rcode) {
+				goto FailSetDevTblEntry;
+			}
+		}
+
+		// Set Configuration Value
+		rcode = pUsb->setConf(bAddress, 0, bConfNum);
+		if(rcode) {
+			goto FailSetConfDescr;
+		}
+		/* print endpoint structure */
+		
+		USBTRACE("\r\nEndpoint Structure:");
+		USBTRACE("\r\nEP0:");
+		USBTRACE2("\r\nAddr: ", epInfo[0].epAddr);
+		USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize);
+		USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs);
+		USBTRACE("\r\nEpout:");
+		USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr);
+		USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize);
+		USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs);
+		USBTRACE("\r\nEpin:");
+		USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr);
+		USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize);
+		USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs);
+	
+
+		USBTRACE("\r\nConfiguration successful");
+		ready = true;
+		return 0; //successful configuration
+    }//if( buf->idVendor == ADK_VID...
+
+	//probe device - get accessory protocol revision
+	{
+        uint32_t adkproto = 0;
+        delay(1);
+        //rcode = getProto((uint8_t*) & adkproto);  // ADK_GETPROTO  0x33
+		rcode = getProto((uint8_t*)buf);
+				
+#if defined(XOOM)
+        //added by Jaylen Scott Vanorden
+        if(rcode) {
+            USBTRACE2("\r\nGot 1st bad code for proto: ", rcode);
+            // Try once more
+            rcode = getProto((uint8_t*) & adkproto);
+        }
+#endif
+        if(rcode) {
+            goto FailGetProto; //init fails
+        }
+		adkproto = buf[0] | (buf[1]<<8);
+        USBTRACE2("\r\nADK protocol rev. ", adkproto);
+    }
+
+    delay(100);
+
+    //sending ID strings
+	// ADK_SENDSTR 0x34
+    if( sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer) ) {
+		USBTRACE("\r\nPb ACCESSORY_STRING_MANUFACTURER"); }
+    delay(10);
+    if( sendStr(ACCESSORY_STRING_MODEL, model) ) {
+		USBTRACE("\r\nPb ACCESSORY_STRING_MODEL"); }
+    delay(10);
+    if( sendStr(ACCESSORY_STRING_DESCRIPTION, description) ) {
+		USBTRACE("\r\nPb ACCESSORY_STRING_DESCRIPTION"); }
+    delay(10);
+    if( sendStr(ACCESSORY_STRING_VERSION, version) ) {
+		USBTRACE("\r\nPb ACCESSORY_STRING_VERSION"); }
+    delay(10);
+    if( sendStr(ACCESSORY_STRING_URI, uri) ) {
+		USBTRACE("\r\nPb ACCESSORY_STRING_URI"); }
+    delay(10);
+    if( sendStr(ACCESSORY_STRING_SERIAL, serial) ) {
+		USBTRACE("\r\nPb ACCESSORY_STRING_SERIAL"); }
+
+    delay(100);
+
+    USBTRACE("\r\nSwitch to accessory mode");
+    //switch to accessory mode
+    //the Android phone will reset
+    rcode = switchAcc();
+    if(rcode) {
+            goto FailSwAcc; //init fails
+    }
+    rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
+    delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower.
+    goto SwAttempt; //switch to accessory mode attempted
+
+    /* diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+	NotifyFailGetDevDescr(rcode);
+	goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+	NotifyFailSetDevTblEntry(rcode);
+	goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+    NotifyFailGetConfDescr(rcode);
+    goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+    NotifyFailSetConfDescr(rcode);
+    goto Fail;
+#endif
+
+FailGetProto:
+#ifdef DEBUG_USB_HOST
+    USBTRACE("\r\ngetProto:");
+    goto Fail;
+#endif
+
+FailSwAcc:
+#ifdef DEBUG_USB_HOST
+    USBTRACE("\r\nswAcc:");
+    goto Fail;
+#endif
+
+    //FailOnInit:
+    //	USBTRACE("OnInit:");
+    //	goto Fail;
+    //
+SwAttempt:
+#ifdef DEBUG_USB_HOST
+    USBTRACE("\r\nAccessory mode switch attempt");
+Fail:
+#endif
+	USBTRACE2("\r\nADK Init Failed, error code: ", rcode);
+	//NotifyFail(rcode);
+	Release();
+	return rcode;
+}
+
+/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */
+void ADK::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+        //ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
+        //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
+        //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
+
+        //added by Yuuichi Akagawa
+        if(bNumEP == 3) {
+		return;
+	}
+
+	bConfNum = conf;
+
+        if((pep->bmAttributes & 0x02) == 2) {
+                uint32_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
+                // Fill in the endpoint info structure
+                epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+                epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+
+                bNumEP++;
+
+                //PrintEndpointDescriptor(pep);
+        }
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint32_t ADK::Release() {
+	pUsb->GetAddressPool().FreeAddress(bAddress);
+
+        bNumEP = 1; //must have to be reset to 1
+
+	bAddress = 0;
+	ready = false;
+	return 0;
+}
+
+uint32_t ADK::RcvData(uint8_t *bytes_rcvd, uint8_t *dataptr) {
+        USBTRACE2("\r\nAddr: ", bAddress );
+        USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr);
+        return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
+}
+
+uint32_t ADK::SndData(uint32_t nbytes, uint8_t *dataptr) {
+        return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
+}
+
+void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+        Notify(PSTR("Endpoint descriptor:"), 0x80);
+        Notify(PSTR("\r\nLength:\t\t"), 0x80);
+        PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+        Notify(PSTR("\r\nType:\t\t"), 0x80);
+        PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+        Notify(PSTR("\r\nAddress:\t"), 0x80);
+        PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+        Notify(PSTR("\r\nAttributes:\t"), 0x80);
+        PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+        Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+        PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+        Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+        PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+        Notify(PSTR("\r\n"), 0x80);
+}
diff --git a/libraries/USBHost/src/adk.h b/libraries/USBHost/src/adk.h
new file mode 100644
index 0000000000000000000000000000000000000000..ffd22cf3e1f215e965fb416d5546ac82a9536a61
--- /dev/null
+++ b/libraries/USBHost/src/adk.h
@@ -0,0 +1,148 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+/* Google ADK interface support header */
+
+#ifndef ADK_H_INCLUDED
+#define ADK_H_INCLUDED
+
+#include <stdint.h>
+#include "Usb.h"
+#include "hid.h"
+#include "Arduino.h"
+
+// #define ADK_VID   0x18D1
+// #define ADK_PID   0x2D00
+// #define ADB_PID   0x2D01
+
+// JCB
+#define ADK_VID   0x04E8
+#define ADK_PID   0x685C
+#define ADB_PID   0x685D
+
+#define XOOM  //enables repeating getProto() and getConf() attempts
+              //necessary for slow devices such as Motorola XOOM
+              //defined by default, can be commented out to save memory
+
+/* requests */
+
+#define ADK_GETPROTO      51  //check USB accessory protocol version  0x33
+#define ADK_SENDSTR       52  //send identifying string               0x34
+#define ADK_ACCSTART      53  //start device in accessory mode        0x35
+
+#define bmREQ_ADK_GET     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_ADK_SEND    USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
+
+#define ACCESSORY_STRING_MANUFACTURER   0
+#define ACCESSORY_STRING_MODEL          1
+#define ACCESSORY_STRING_DESCRIPTION    2
+#define ACCESSORY_STRING_VERSION        3
+#define ACCESSORY_STRING_URI            4
+#define ACCESSORY_STRING_SERIAL         5
+
+#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT
+
+class ADK;
+
+class ADK : public USBDeviceConfig, public UsbConfigXtracter {
+private:
+	/* ID strings */
+	const char* manufacturer;
+	const char* model;
+	const char* description;
+	const char* version;
+	const char* uri;
+	const char* serial;
+
+	/* ADK proprietary requests */
+	uint32_t getProto(uint8_t* adkproto);
+	uint32_t sendStr(uint32_t index, const char* str);
+	uint32_t switchAcc(void);
+
+protected:
+	static const uint32_t epDataInIndex;			// DataIn endpoint index
+	static const uint32_t epDataOutIndex;			// DataOUT endpoint index
+
+	/* Mandatory members */
+	USBHost		*pUsb;
+	uint32_t	bAddress;							// Device USB address
+	uint32_t	bConfNum;							// configuration number
+
+	uint32_t	bNumEP;								// total number of EP in the configuration
+	uint32_t	ready;
+
+        /* Endpoint data structure */
+	EpInfo		epInfo[ADK_MAX_ENDPOINTS];
+
+        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+
+public:
+        ADK(USBHost *pUsb, const char* manufacturer,
+                const char* model,
+                const char* description,
+                const char* version,
+                const char* uri,
+                const char* serial);
+
+	// Methods for receiving and sending data
+	uint32_t RcvData(uint8_t *nbytesptr, uint8_t *dataptr);
+	uint32_t SndData(uint32_t nbytes, uint8_t *dataptr);
+
+
+	// USBDeviceConfig implementation
+        virtual uint32_t ConfigureDevice(uint32_t parent, uint32_t port, uint32_t lowspeed);
+        virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
+        virtual uint32_t Release();
+
+        virtual uint32_t Poll() {
+                return 0;
+        };
+
+	virtual uint32_t GetAddress() {
+              return bAddress;
+        };
+
+	virtual uint32_t isReady() {
+              return ready;
+        };
+
+        virtual uint32_t VIDPIDOK(uint32_t vid, uint32_t pid) {
+                return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID));
+        };
+
+	//UsbConfigXtracter implementation
+	virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+}; //class ADK : public USBDeviceConfig ...
+
+/* get ADK protocol version */
+
+/* returns 2 bytes in *adkproto */
+inline uint32_t ADK::getProto(uint8_t* adkproto) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
+}
+
+/* send ADK string */
+inline uint32_t ADK::sendStr(uint32_t index, const char* str) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));
+}
+
+/* switch to accessory mode */
+inline uint32_t ADK::switchAcc(void) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
+}
+
+#endif /* ADK_H_INCLUDED */
diff --git a/libraries/USBHost/src/confdescparser.h b/libraries/USBHost/src/confdescparser.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ee6a1eef2bf732d3aaa39ba71a6da1806bd0880
--- /dev/null
+++ b/libraries/USBHost/src/confdescparser.h
@@ -0,0 +1,223 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
+#error "Never include confdescparser.h directly; include Usb.h instead"
+#else
+
+#define __CONFDESCPARSER_H__
+
+#include <stdint.h>
+
+//#define TRACE_USBHOST(x)	x
+#define TRACE_USBHOST(x)  
+
+class UsbConfigXtracter {
+public:
+        //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
+        //virtual void InterfaceXtract(uint32_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
+	virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0;
+};
+
+#define CP_MASK_COMPARE_CLASS			1
+#define CP_MASK_COMPARE_SUBCLASS		2
+#define CP_MASK_COMPARE_PROTOCOL		4
+#define CP_MASK_COMPARE_ALL			7
+
+// Configuration Descriptor Parser Class Template
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+class ConfigDescParser : public USBReadParser {
+	UsbConfigXtracter		*theXtractor;
+    MultiValueBuffer		theBuffer;
+	MultiByteValueParser	valParser;
+	ByteSkipper				theSkipper;
+	uint8_t					varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
+
+	uint32_t				stateParseDescr;	// ParseDescriptor state
+
+	uint32_t				dscrLen;			// Descriptor length
+	uint32_t				dscrType;			// Descriptor type
+
+	bool					isGoodInterface;	// Apropriate interface flag
+	uint32_t				confValue;			// Configuration value
+	uint32_t				protoValue;			// Protocol value
+	uint32_t				ifaceNumber;		// Interface number
+	uint32_t				ifaceAltSet;		// Interface alternate settings
+
+        bool UseOr;
+	bool ParseDescriptor(uint8_t **pp, uint32_t *pcntdn);
+	void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
+
+public:
+
+        void SetOR(void) {
+                UseOr = true;
+        }
+	ConfigDescParser(UsbConfigXtracter *xtractor);
+	virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset);
+};
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
+	theXtractor(xtractor),
+	stateParseDescr(0),
+	dscrLen(0),
+	dscrType(0),
+UseOr(false) {
+	theBuffer.pValue = varBuffer;
+	valParser.Initialize(&theBuffer);
+	theSkipper.Initialize(&theBuffer);
+};
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) {
+	uint32_t	cntdn = len;
+	uint8_t		*p = (uint8_t*)pbuf;
+
+	while (cntdn)
+		if(!ParseDescriptor(&p, &cntdn))
+			return;
+}
+
+/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
+  compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint32_t *pcntdn) {
+        USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
+        USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
+	switch(stateParseDescr) {
+		case 0:
+			theBuffer.valueSize = 2;
+			valParser.Initialize(&theBuffer);
+			stateParseDescr		= 1;
+		case 1:
+			if(!valParser.Parse(pp, pcntdn))
+				return false;
+			dscrLen			= *((uint8_t*)theBuffer.pValue);
+			dscrType		= *((uint8_t*)theBuffer.pValue + 1);
+			stateParseDescr	= 2;
+		case 2:
+                        // This is a sort of hack. Assuming that two bytes are all ready in the buffer
+			//	the pointer is positioned two bytes ahead in order for the rest of descriptor
+			//	to be read right after the size and the type fields.
+			// This should be used carefully. varBuffer should be used directly to handle data
+			//	in the buffer.
+			theBuffer.pValue	= varBuffer + 2;
+			stateParseDescr		= 3;
+		case 3:
+                        switch(dscrType) {
+                                case USB_DESCRIPTOR_INTERFACE:
+                                        isGoodInterface = false;
+                                case USB_DESCRIPTOR_CONFIGURATION:
+                                        theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
+                                        break;
+                                case USB_DESCRIPTOR_ENDPOINT:
+                                        theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
+					break;
+				case HID_DESCRIPTOR_HID:
+					theBuffer.valueSize = dscrLen - 2;
+					break;
+			}
+			valParser.Initialize(&theBuffer);
+			stateParseDescr		= 4;
+		case 4:
+                        switch(dscrType) {
+				case USB_DESCRIPTOR_CONFIGURATION:
+                                        if(!valParser.Parse(pp, pcntdn))
+                                                return false;
+                                        confValue = ucd->bConfigurationValue;
+					break;
+				case USB_DESCRIPTOR_INTERFACE:
+                                        if(!valParser.Parse(pp, pcntdn))
+                                                return false;
+                                        if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
+                                                break;
+                                        if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
+                                                break;
+                                        if(UseOr) {
+                                                if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
+                                                        break;
+                                        } else {
+                                                if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
+                                                        break;
+                                        }
+                                        isGoodInterface = true;
+                                        ifaceNumber = uid->bInterfaceNumber;
+                                        ifaceAltSet = uid->bAlternateSetting;
+                                        protoValue = uid->bInterfaceProtocol;
+                                        break;
+                                case USB_DESCRIPTOR_ENDPOINT:
+                                        if(!valParser.Parse(pp, pcntdn))
+                                                return false;
+                                        if(isGoodInterface)
+                                                if(theXtractor)
+							theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
+					break;
+				//case HID_DESCRIPTOR_HID:
+				//	if (!valParser.Parse(pp, pcntdn))
+				//		return false;
+				//	PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
+				//	break;
+				default:
+					if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
+						return false;
+			}
+			theBuffer.pValue = varBuffer;
+			stateParseDescr = 0;
+	}
+	return true;
+}
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
+        Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
+        Notify(PSTR("bDescLength:\t\t"), 0x80);
+        PrintHex<uint8_t > (pDesc->bLength, 0x80);
+
+        Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
+        PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
+
+        Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
+        PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
+
+        Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
+        PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
+
+        Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
+        PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
+
+        //Notify(PSTR("\r\nbDescrType:\t\t"));
+        //PrintHex<uint8_t>(pDesc->bDescrType);
+        //
+        //Notify(PSTR("\r\nwDescriptorLength:\t"));
+        //PrintHex<uint16_t>(pDesc->wDescriptorLength);
+
+	for (uint32_t i = 0; i < pDesc->bNumDescriptors; i++) {
+		HID_CLASS_DESCRIPTOR_LEN_AND_TYPE	*pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
+
+                Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
+                PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
+
+                Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
+                PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
+        }
+        Notify(PSTR("\r\n"), 0x80);
+}
+
+
+#endif // __CONFDESCPARSER_H__
diff --git a/libraries/USBHost/src/hexdump.h b/libraries/USBHost/src/hexdump.h
new file mode 100644
index 0000000000000000000000000000000000000000..3818d850b7116228786f281a80afb4a7be0211d2
--- /dev/null
+++ b/libraries/USBHost/src/hexdump.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__HEXDUMP_H__)
+#error "Never include hexdump.h directly; include Usb.h instead"
+#else
+#define __HEXDUMP_H__
+
+extern int UsbDEBUGlvl;
+
+template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
+class HexDumper : public BASE_CLASS {
+        uint8_t byteCount;
+        OFFSET_TYPE byteTotal;
+
+public:
+
+        HexDumper() : byteCount(0), byteTotal(0) {
+        };
+
+        void Initialize() {
+                byteCount = 0;
+                byteTotal = 0;
+        };
+
+        virtual void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);
+};
+
+template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
+void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
+        if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.
+                for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
+                        if(!byteCount) {
+                                PrintHex<OFFSET_TYPE > (byteTotal, 0x80);
+                                E_Notify(PSTR(": "), 0x80);
+                        }
+                        PrintHex<uint8_t > (pbuf[j], 0x80);
+                        E_Notify(PSTR(" "), 0x80);
+
+                        if(byteCount == 15) {
+                                E_Notify(PSTR("\r\n"), 0x80);
+                                byteCount = 0xFF;
+                        }
+                }
+        }
+}
+
+#endif // __HEXDUMP_H__
diff --git a/libraries/USBHost/src/hid.cpp b/libraries/USBHost/src/hid.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b53d521820884e95cb57f7803b58f2e1be47c12c
--- /dev/null
+++ b/libraries/USBHost/src/hid.cpp
@@ -0,0 +1,112 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#include "hid.h"
+
+//get HID report descriptor
+
+/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here!
+uint32_t HID::GetReportDescr(uint32_t ep, USBReadParser *parser) {
+        const uint8_t constBufLen = 64;
+        uint8_t buf[constBufLen];
+
+        uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
+                HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser);
+
+        //return ((rcode != hrSTALL) ? rcode : 0);
+        return rcode;
+}
+ */
+uint32_t HID::GetReportDescr(uint32_t wIndex, USBReadParser *parser) {
+        const uint8_t constBufLen = 64;
+        uint8_t buf[constBufLen];
+
+        uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
+                HID_DESCRIPTOR_REPORT, wIndex, 128, constBufLen, buf, (USBReadParser*)parser);
+
+        //return ((rcode != hrSTALL) ? rcode : 0);
+        return rcode;
+}
+
+//uint32_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr )
+//{
+//    return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr ));
+//}
+
+uint32_t HID::SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
+}
+
+uint32_t HID::GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
+}
+
+uint32_t HID::GetIdle(uint32_t iface, uint32_t reportID, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));
+}
+
+uint32_t HID::SetIdle(uint32_t iface, uint32_t reportID, uint32_t duration) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));
+}
+
+uint32_t HID::SetProtocol(uint32_t iface, uint32_t protocol) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
+}
+
+uint32_t HID::GetProtocol(uint32_t iface, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
+}
+
+void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+        Notify(PSTR("Endpoint descriptor:"), 0x80);
+        Notify(PSTR("\r\nLength:\t\t"), 0x80);
+        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+        Notify(PSTR("\r\nType:\t\t"), 0x80);
+        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+        Notify(PSTR("\r\nAddress:\t"), 0x80);
+        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+        Notify(PSTR("\r\nAttributes:\t"), 0x80);
+        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+        Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+        Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+}
+
+void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
+        Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
+        Notify(PSTR("bDescLength:\t\t"), 0x80);
+        D_PrintHex<uint8_t > (pDesc->bLength, 0x80);
+
+        Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
+        D_PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
+
+        Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
+        D_PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
+
+        Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
+        D_PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
+
+        Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
+        D_PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
+
+        Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
+        D_PrintHex<uint8_t > (pDesc->bDescrType, 0x80);
+
+        Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
+        D_PrintHex<uint16_t > (pDesc->wDescriptorLength, 0x80);
+}
diff --git a/libraries/USBHost/src/hid.h b/libraries/USBHost/src/hid.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca697a568291e6b23a6323f62f02da406709de0e
--- /dev/null
+++ b/libraries/USBHost/src/hid.h
@@ -0,0 +1,183 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+#if !defined(__HID_H__)
+#define __HID_H__
+
+#include "Usb.h"
+#include "hidusagestr.h"
+
+#define MAX_REPORT_PARSERS			2
+#define HID_MAX_HID_CLASS_DESCRIPTORS		5
+
+#define DATA_SIZE_MASK           0x03
+#define TYPE_MASK                0x0C
+#define TAG_MASK                 0xF0
+
+#define DATA_SIZE_0              0x00
+#define DATA_SIZE_1              0x01
+#define DATA_SIZE_2              0x02
+#define DATA_SIZE_4              0x03
+
+#define TYPE_MAIN                0x00
+#define TYPE_GLOBAL              0x04
+#define TYPE_LOCAL               0x08
+
+#define TAG_MAIN_INPUT           0x80
+#define TAG_MAIN_OUTPUT          0x90
+#define TAG_MAIN_COLLECTION      0xA0
+#define TAG_MAIN_FEATURE         0xB0
+#define TAG_MAIN_ENDCOLLECTION   0xC0
+
+#define TAG_GLOBAL_USAGEPAGE     0x00
+#define TAG_GLOBAL_LOGICALMIN    0x10
+#define TAG_GLOBAL_LOGICALMAX    0x20
+#define TAG_GLOBAL_PHYSMIN       0x30
+#define TAG_GLOBAL_PHYSMAX       0x40
+#define TAG_GLOBAL_UNITEXP       0x50
+#define TAG_GLOBAL_UNIT          0x60
+#define TAG_GLOBAL_REPORTSIZE    0x70
+#define TAG_GLOBAL_REPORTID      0x80
+#define TAG_GLOBAL_REPORTCOUNT   0x90
+#define TAG_GLOBAL_PUSH          0xA0
+#define TAG_GLOBAL_POP           0xB0
+
+#define TAG_LOCAL_USAGE          0x00
+#define TAG_LOCAL_USAGEMIN       0x10
+#define TAG_LOCAL_USAGEMAX       0x20
+
+/* HID requests */
+#define bmREQ_HIDOUT        USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+#define bmREQ_HIDIN         USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+#define bmREQ_HIDREPORT     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
+
+/* HID constants. Not part of chapter 9 */
+/* Class-Specific Requests */
+#define HID_REQUEST_GET_REPORT      0x01
+#define HID_REQUEST_GET_IDLE        0x02
+#define HID_REQUEST_GET_PROTOCOL    0x03
+#define HID_REQUEST_SET_REPORT      0x09
+#define HID_REQUEST_SET_IDLE        0x0A
+#define HID_REQUEST_SET_PROTOCOL    0x0B
+
+/* Class Descriptor Types */
+#define HID_DESCRIPTOR_HID			0x21
+#define HID_DESCRIPTOR_REPORT		0x22
+#define HID_DESRIPTOR_PHY			0x23
+
+/* Protocol Selection */
+#define HID_BOOT_PROTOCOL			0x00
+#define HID_RPT_PROTOCOL			0x01
+
+/* HID Interface Class Code */
+#define HID_INTF                    0x03
+
+/* HID Interface Class SubClass Codes */
+#define HID_BOOT_INTF_SUBCLASS      0x01
+
+/* HID Interface Class Protocol Codes */
+#define HID_PROTOCOL_NONE           0x00
+#define HID_PROTOCOL_KEYBOARD       0x01
+#define HID_PROTOCOL_MOUSE          0x02
+
+#define HID_ITEM_TYPE_MAIN							0
+#define HID_ITEM_TYPE_GLOBAL						1
+#define HID_ITEM_TYPE_LOCAL							2
+#define HID_ITEM_TYPE_RESERVED						3
+
+#define HID_LONG_ITEM_PREFIX						0xfe		// Long item prefix value
+
+#define bmHID_MAIN_ITEM_TAG							0xfc		// Main item tag mask
+
+#define bmHID_MAIN_ITEM_INPUT						0x80		// Main item Input tag value
+#define bmHID_MAIN_ITEM_OUTPUT						0x90		// Main item Output tag value
+#define bmHID_MAIN_ITEM_FEATURE						0xb0		// Main item Feature tag value
+#define bmHID_MAIN_ITEM_COLLECTION					0xa0		// Main item Collection tag value
+#define bmHID_MAIN_ITEM_END_COLLECTION				0xce		// Main item End Collection tag value
+
+#define HID_MAIN_ITEM_COLLECTION_PHYSICAL			0
+#define HID_MAIN_ITEM_COLLECTION_APPLICATION		1
+#define HID_MAIN_ITEM_COLLECTION_LOGICAL			2
+#define HID_MAIN_ITEM_COLLECTION_REPORT				3
+#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY		4
+#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH		5
+#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER		6
+
+struct HidItemPrefix {
+	uint8_t		bSize : 2;
+	uint8_t		bType : 2;
+	uint8_t		bTag  : 4;
+};
+
+struct MainItemIOFeature {
+	uint8_t		bmIsConstantOrData			: 1;
+	uint8_t		bmIsArrayOrVariable			: 1;
+	uint8_t		bmIsRelativeOrAbsolute		: 1;
+	uint8_t		bmIsWrapOrNoWrap			: 1;
+	uint8_t		bmIsNonLonearOrLinear		: 1;
+	uint8_t		bmIsNoPreferedOrPrefered	: 1;
+	uint8_t		bmIsNullOrNoNull			: 1;
+	uint8_t		bmIsVolatileOrNonVolatile	: 1;
+};
+
+class HID;
+
+class HIDReportParser {
+public:
+	virtual void Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf)= 0;
+};
+
+class HID : public USBDeviceConfig, public UsbConfigXtracter {
+protected:
+	USBHost		*pUsb;					// USB class instance pointer
+	uint32_t	bAddress;				// address
+
+protected:
+	static const uint32_t	epInterruptInIndex	= 1;	// InterruptIN  endpoint index
+	static const uint32_t	epInterruptOutIndex	= 2;	// InterruptOUT endpoint index
+
+	static const uint32_t	maxHidInterfaces	= 3;
+	static const uint32_t	maxEpPerInterface	= 2;
+	static const uint32_t	totalEndpoints		= (maxHidInterfaces * maxEpPerInterface + 1);
+
+	void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+	void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
+
+	virtual HIDReportParser* GetReportParser(uint32_t id);
+
+public:
+
+	HID(USBHost *pusb) : pUsb(pusb) {
+	};
+
+	const USBHost* GetUsb() {
+		return pUsb; 
+	};
+	virtual uint32_t SetReportParser(uint32_t id, HIDReportParser *prs);
+
+	uint32_t SetProtocol(uint32_t iface, uint32_t protocol);
+	uint32_t GetProtocol(uint32_t iface, uint8_t* dataptr);
+	uint32_t GetIdle(uint32_t iface, uint32_t reportID, uint8_t* dataptr);
+	uint32_t SetIdle(uint32_t iface, uint32_t reportID, uint32_t duration);
+
+	uint32_t GetReportDescr(uint32_t ep, USBReadParser *parser = NULL);
+
+	uint32_t GetHidDescr(uint32_t ep, uint32_t nbytes, uint8_t* dataptr);
+	uint32_t GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr);
+	uint32_t SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr);
+};
+
+#endif // __HID_H__
diff --git a/libraries/USBHost/src/hidboot.cpp b/libraries/USBHost/src/hidboot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9f6b8743ae9356d8d89ef31ecc5dc63c854634c6
--- /dev/null
+++ b/libraries/USBHost/src/hidboot.cpp
@@ -0,0 +1,223 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+#include "hidboot.h"
+
+void MouseReportParser::Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf) {
+	MOUSEINFO *pmi = (MOUSEINFO*)buf;
+        // Future:
+        // bool event;
+
+#if 0
+	if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)
+		OnLeftButtonDown(pmi);
+
+	if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0)
+		OnLeftButtonUp(pmi);
+
+	if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1)
+		OnRightButtonDown(pmi);
+
+	if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0)
+		OnRightButtonUp(pmi);
+
+	if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1)
+		OnMiddleButtonDown(pmi);
+
+	if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0)
+		OnMiddleButtonUp(pmi);
+
+	if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY)
+		OnMouseMove(pmi);
+
+        if (len > sizeof (MOUSEINFO))
+                for (uint32_t i = 0; i<sizeof (MOUSEINFO); i++)
+                        prevState.bInfo[i] = buf[i];
+#else
+        //
+        // Optimization idea:
+        //
+        // 1: Don't pass the structure on every event. Buttons would not need it.
+        // 2: Only pass x/y values in the movement routine.
+        //
+        // These two changes (with the ones I have made) will save extra flash.
+        // The only "bad" thing is that it could break old code.
+        //
+        // Future thoughts:
+        //
+        // The extra space gained can be used for a generic mouse event that can be called
+        // when there are _ANY_ changes. This one you _MAY_ want to pass everything, however the
+        // sketch could already have noted these facts to support drag/drop scroll wheel stuff, etc.
+        //
+
+        // Why do we need to pass the structure for buttons?
+        // The function call not enough of a hint for what is happening?
+        if(prevState.mouseInfo.bmLeftButton != pmi->bmLeftButton ) {
+                if(pmi->bmLeftButton) {
+                        OnLeftButtonDown(pmi);
+                } else {
+                        OnLeftButtonUp(pmi);
+                }
+                // Future:
+                // event = true;
+        }
+
+        if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) {
+                if(pmi->bmRightButton) {
+                        OnRightButtonDown(pmi);
+                } else {
+                        OnRightButtonUp(pmi);
+                }
+                // Future:
+                // event = true;
+        }
+
+        if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) {
+                if(pmi->bmMiddleButton) {
+                        OnMiddleButtonDown(pmi);
+                } else {
+                        OnMiddleButtonUp(pmi);
+                }
+                // Future:
+                // event = true;
+        }
+
+        //
+        // Scroll wheel(s), are not part of the spec, but we could support it.
+        // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4
+        // We wouldn't even need to save this information.
+        //if(len > 3) {
+        //}
+        //
+
+        // Mice only report motion when they actually move!
+        // Why not just pass the x/y values to simplify things??
+        if(pmi->dX || pmi->dY) {
+                OnMouseMove(pmi);
+                // Future:
+                // event = true;
+        }
+
+        //
+        // Future:
+        // Provide a callback that operates on the gathered events from above.
+        //
+        // if(event) OnMouse();
+        //
+
+        // Only the first byte matters (buttons). We do NOT need to save position info.
+        prevState.bInfo[0] = buf[0];
+#endif
+
+};
+
+void KeyboardReportParser::Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf) {
+	// On error - return
+	if (buf[2] == 1)
+		return;
+
+	//KBDINFO	*pki = (KBDINFO*)buf;
+
+	// provide event for changed control key state
+	if (prevState.bInfo[0x00] != buf[0x00]) {
+		OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]);
+	}
+
+	for (uint32_t i = 2; i < 8; i++) {
+		bool down = false;
+		bool up	  = false;
+
+		for (uint8_t j = 2; j < 8; j++) {
+			if (buf[i] == prevState.bInfo[j] && buf[i] != 1)
+				down = true;
+			if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)
+				up = true;
+		}
+		if (!down) {
+			HandleLockingKeys(hid, buf[i]);
+			OnKeyDown(*buf, buf[i]);
+		}
+		if (!up)
+			OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]);
+	}
+	for(uint32_t i = 0; i < 8; i++)
+		prevState.bInfo[i] = buf[i];
+};
+
+uint8_t KeyboardReportParser::HandleLockingKeys(HID *hid, uint8_t key) {
+	uint8_t old_keys = kbdLockingKeys.bLeds;
+
+	switch (key) {
+                case UHS_HID_BOOT_KEY_NUM_LOCK:
+                        kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
+                        break;
+                case UHS_HID_BOOT_KEY_CAPS_LOCK:
+                        kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;
+                        break;
+                case UHS_HID_BOOT_KEY_SCROLL_LOCK:
+                        kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;
+			break;
+	}
+
+	if (old_keys != kbdLockingKeys.bLeds && hid)
+		return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds));
+
+	return 0;
+}
+
+const uint8_t KeyboardReportParser::numKeys[10] = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')'};
+const uint8_t KeyboardReportParser::symKeysUp[12] = { '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'};
+const uint8_t KeyboardReportParser::symKeysLo[12] = { '-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'};
+const uint8_t KeyboardReportParser::padKeys[5] = { '/', '*', '-', '+', 0x13};
+#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h)))
+uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) {
+	uint8_t shift = (mod & 0x22);
+
+	// [a-z]
+        if (VALUE_WITHIN(key, 0x04, 0x1d)) {
+                // Upper case letters
+                if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) ||
+                        (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0))
+                        return (key - 4 + 'A');
+
+                        // Lower case letters
+                else
+                        return (key - 4 + 'a');
+        }// Numbers
+        else if (VALUE_WITHIN(key, 0x1e, 0x27)) {
+		if (shift)
+                        return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e]));
+                else
+                        return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
+        }// Keypad Numbers
+        else if(VALUE_WITHIN(key, 0x59, 0x61)) {
+                if(kbdLockingKeys.kbdLeds.bmNumLock == 1)
+                        return (key - 0x59 + '1');
+        } else if(VALUE_WITHIN(key, 0x2d, 0x38))
+                return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d]));
+        else if(VALUE_WITHIN(key, 0x54, 0x58))
+                return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]);
+        else {
+                switch(key) {
+                        case UHS_HID_BOOT_KEY_SPACE: return (0x20);
+                        case UHS_HID_BOOT_KEY_ENTER: return (0x13);
+                        case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0);
+                        case UHS_HID_BOOT_KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0);
+                }
+        }
+        return ( 0);
+}
+
diff --git a/libraries/USBHost/src/hidboot.h b/libraries/USBHost/src/hidboot.h
new file mode 100644
index 0000000000000000000000000000000000000000..621ce57ac2f2d32aaf7d15e0258a7b68482b5402
--- /dev/null
+++ b/libraries/USBHost/src/hidboot.h
@@ -0,0 +1,609 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+#ifndef HIDBOOT_H_INCLUDED
+#define HIDBOOT_H_INCLUDED
+
+#include <stdint.h>
+#include "Usb.h"
+#include "hid.h"
+#include "Arduino.h"
+
+#define UHS_HID_BOOT_KEY_ZERO           0x27
+#define UHS_HID_BOOT_KEY_ENTER          0x28
+#define UHS_HID_BOOT_KEY_SPACE          0x2c
+#define UHS_HID_BOOT_KEY_CAPS_LOCK      0x39
+#define UHS_HID_BOOT_KEY_SCROLL_LOCK    0x47
+#define UHS_HID_BOOT_KEY_NUM_LOCK       0x53
+#define UHS_HID_BOOT_KEY_ZERO2          0x62
+#define UHS_HID_BOOT_KEY_PERIOD         0x63
+
+// Don't worry, GCC will optimize the result to a final value.
+#define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0))
+#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2)
+#define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0))
+
+// Already defined in hid.h
+// #define HID_MAX_HID_CLASS_DESCRIPTORS 5
+
+struct MOUSEINFO {
+
+        struct {
+                uint8_t bmLeftButton : 1;
+                uint8_t bmRightButton : 1;
+                uint8_t bmMiddleButton : 1;
+                uint8_t bmDummy : 5;
+	};
+	int8_t			dX;
+	int8_t			dY;
+};
+
+class MouseReportParser : public HIDReportParser {
+
+        union {
+                MOUSEINFO mouseInfo;
+                uint8_t bInfo[sizeof (MOUSEINFO)];
+        } prevState;
+
+public:
+	virtual void Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf);
+
+protected:
+
+        virtual void OnMouseMove(MOUSEINFO *mi) {
+        };
+
+        virtual void OnLeftButtonUp(MOUSEINFO *mi) {
+        };
+
+        virtual void OnLeftButtonDown(MOUSEINFO *mi) {
+        };
+
+        virtual void OnRightButtonUp(MOUSEINFO *mi) {
+        };
+
+        virtual void OnRightButtonDown(MOUSEINFO *mi) {
+        };
+
+        virtual void OnMiddleButtonUp(MOUSEINFO *mi) {
+        };
+
+        virtual void OnMiddleButtonDown(MOUSEINFO *mi) {
+        };
+};
+
+struct MODIFIERKEYS {
+	uint8_t		bmLeftCtrl		: 1;
+	uint8_t		bmLeftShift		: 1;
+	uint8_t		bmLeftAlt		: 1;
+	uint8_t		bmLeftGUI		: 1;
+	uint8_t		bmRightCtrl		: 1;
+	uint8_t		bmRightShift	: 1;
+	uint8_t		bmRightAlt		: 1;
+	uint8_t		bmRightGUI		: 1;
+};
+
+struct KBDINFO {
+
+        struct {
+		uint8_t		bmLeftCtrl		: 1;
+		uint8_t		bmLeftShift		: 1;
+		uint8_t		bmLeftAlt		: 1;
+		uint8_t		bmLeftGUI		: 1;
+		uint8_t		bmRightCtrl		: 1;
+		uint8_t		bmRightShift	: 1;
+		uint8_t		bmRightAlt		: 1;
+		uint8_t		bmRightGUI		: 1;
+	};
+	uint8_t			bReserved;
+	uint8_t			Keys[6];
+};
+
+struct KBDLEDS {
+	uint8_t		bmNumLock		: 1;
+	uint8_t		bmCapsLock		: 1;
+	uint8_t		bmScrollLock	: 1;
+	uint8_t		bmCompose		: 1;
+	uint8_t		bmKana			: 1;
+	uint8_t		bmReserved		: 3;
+};
+
+class KeyboardReportParser : public HIDReportParser {
+        static const uint8_t numKeys[10];
+        static const uint8_t symKeysUp[12];
+        static const uint8_t symKeysLo[12];
+        static const uint8_t padKeys[5];
+
+protected:
+
+        union {
+                KBDINFO kbdInfo;
+                uint8_t bInfo[sizeof (KBDINFO)];
+        } prevState;
+
+        union {
+		KBDLEDS		kbdLeds;
+		uint8_t		bLeds;
+	}	kbdLockingKeys;
+
+	uint8_t OemToAscii(uint8_t mod, uint8_t key);
+
+public:
+
+        KeyboardReportParser() {
+                kbdLockingKeys.bLeds = 0;
+        };
+
+	virtual void Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf);
+
+protected:
+	virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key);
+
+        virtual void OnControlKeysChanged(uint8_t before, uint8_t after) {
+        };
+
+        virtual void OnKeyDown(uint8_t mod, uint8_t key) {
+        };
+
+        virtual void OnKeyUp(uint8_t mod, uint8_t key) {
+        };
+
+        virtual const uint8_t *getNumKeys() {
+                return numKeys;
+        };
+
+        virtual const uint8_t *getSymKeysUp() {
+                return symKeysUp;
+        };
+
+        virtual const uint8_t *getSymKeysLo() {
+                return symKeysLo;
+        };
+
+        virtual const uint8_t *getPadKeys() {
+                return padKeys;
+        };
+};
+
+template <const uint8_t BOOT_PROTOCOL>
+class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
+{
+        EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)];
+        HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)];
+
+        uint32_t bConfNum; // configuration number
+        uint32_t bIfaceNum; // Interface Number
+        uint32_t bNumIface; // number of interfaces in the configuration
+        uint32_t bNumEP; // total number of EP in the configuration
+
+        uint32_t qNextPollTime;			// next poll time
+        uint32_t bPollEnable;			// poll enable flag
+        uint32_t bInterval; // largest interval
+
+	void Initialize();
+
+	virtual HIDReportParser* GetReportParser(uint32_t id) { 
+                return pRptParser[id];
+        };
+
+public:
+	HIDBoot(USBHost *p);
+
+	virtual uint32_t SetReportParser(uint32_t id, HIDReportParser *prs) {
+                pRptParser[id] = prs;
+                return true;
+        };
+
+	// USBDeviceConfig implementation
+	virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
+	virtual uint32_t Release();
+	virtual uint32_t Poll();
+
+	virtual uint32_t GetAddress() {
+                return bAddress;
+        };
+
+	// UsbConfigXtracter implementation
+	virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+};
+
+template <const uint8_t BOOT_PROTOCOL>
+HIDBoot<BOOT_PROTOCOL>::HIDBoot(USBHost *p) :
+		HID(p),
+		qNextPollTime(0),
+		bPollEnable(false) {
+	Initialize();
+
+        for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
+                pRptParser[i] = NULL;
+        }
+	if(pUsb)
+		pUsb->RegisterDeviceClass(this);
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+void HIDBoot<BOOT_PROTOCOL>::Initialize() {
+        for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); i++) {
+                epInfo[i].epAddr = 0;
+		epInfo[i].maxPktSize	= (i) ? 0 : 8;
+		epInfo[i].epAttribs		= 0;
+		epInfo[i].bmNakPower	= (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+	}
+	bNumEP		= 1;
+	bNumIface	= 0;
+	bConfNum	= 0;
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+uint32_t HIDBoot<BOOT_PROTOCOL>::Init(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+	uint8_t		buf[constBufSize];
+	uint32_t	rcode;
+	UsbDeviceDefinition	*p = NULL;
+	EpInfo		*oldep_ptr = NULL;
+	uint32_t	len = 0;
+    //uint16_t cd_len = 0;
+
+	uint32_t num_of_conf; // number of configurations
+    //uint32_t num_of_intf; // number of interfaces
+
+	// Get memory address of USB device address pool
+	AddressPool	&addrPool = pUsb->GetAddressPool();
+
+	USBTRACE("BM Init\r\n");
+	//USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL)));
+	//USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL));
+
+    // Check if address has already been assigned to an instance
+	if(bAddress)
+		return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+    bInterval = 0;
+	// Get pointer to pseudo device with address 0 assigned
+	p = addrPool.GetUsbDevicePtr(0);
+
+	if(!p)
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+	if(!p->epinfo) {
+                USBTRACE("epinfo\r\n");
+		return USB_ERROR_EPINFO_IS_NULL;
+	}
+
+	// Save old pointer to EP_RECORD of address 0
+	oldep_ptr = p->epinfo;
+
+	// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+	p->epinfo = epInfo;
+
+	p->lowspeed = lowspeed;
+	// Get device descriptor  GET_DESCRIPTOR
+	rcode = pUsb->getDevDescr(0, 0, /*8*/sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+
+	if(!rcode)
+		len = (buf[0] > constBufSize) ? constBufSize : buf[0];
+
+    if(rcode) {
+		// Restore p->epinfo
+		p->epinfo = oldep_ptr;
+
+		goto FailGetDevDescr;
+    }
+
+
+	// Reset
+	UHD_BusReset();
+	while( Is_uhd_starting_reset() ) {}
+
+	// Restore p->epinfo
+	p->epinfo = oldep_ptr;
+
+
+	// Allocate new address according to device class
+	bAddress = addrPool.AllocAddress(parent, false, port);
+	if(!bAddress)
+		return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+	// Extract Max Packet Size from the device descriptor
+	epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
+
+	// Assign new address to the device  SET_ADDRESS
+
+	rcode = pUsb->setAddr(0, 0, bAddress);
+	if(rcode) {
+		p->lowspeed = false;
+		addrPool.FreeAddress(bAddress);
+		bAddress = 0;
+		USBTRACE2("setAddr:", rcode);
+		return rcode;
+	}
+    //delay(2); //per USB 2.0 sect.9.2.6.3
+
+	// Save old pointer to EP_RECORD of address 0
+	oldep_ptr = p->epinfo;
+	// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+	p->epinfo = epInfo;
+	// Get device descriptor  GET_DESCRIPTOR
+	rcode = pUsb->getDevDescr(bAddress, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+	// Restore p->epinfo
+	p->epinfo = oldep_ptr;
+	if (rcode)
+	{
+		goto FailGetDevDescr;
+	}
+
+	TRACE_USBHOST(printf("HIDBoot::Init : device address is now %lu\r\n", bAddress);)
+
+	p->lowspeed = false;
+
+	//get pointer to assigned address record
+	p = addrPool.GetUsbDevicePtr(bAddress);
+
+	if(!p)
+		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+	p->lowspeed = lowspeed;
+
+	if(len)
+		rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
+
+	if(rcode)
+		goto FailGetDevDescr;
+
+	num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
+
+        USBTRACE2("NC:", num_of_conf);
+
+        // GCC will optimize unused stuff away.
+        if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) {
+                USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n");
+                ConfigDescParser<
+                        USB_CLASS_HID,
+                        HID_BOOT_INTF_SUBCLASS,
+                        HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE,
+                        CP_MASK_COMPARE_ALL > confDescrParser(this);
+                confDescrParser.SetOR(); // Use the OR variant.
+                for(uint32_t i = 0; i < num_of_conf; i++) {
+                        pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+                        if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))
+                                break;
+                }
+        } else {
+                // GCC will optimize unused stuff away.
+                if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
+                        USBTRACE("HID_PROTOCOL_KEYBOARD\r\n");
+                        for(uint32_t i = 0; i < num_of_conf; i++) {
+                                ConfigDescParser<
+                                        USB_CLASS_HID,
+                                        HID_BOOT_INTF_SUBCLASS,
+                                        HID_PROTOCOL_KEYBOARD,
+                                        CP_MASK_COMPARE_ALL> confDescrParserA(this);
+
+                                pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);
+                                if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))
+                                        break;
+                        }
+                }
+
+                // GCC will optimize unused stuff away.
+                if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) {
+                        USBTRACE("HID_PROTOCOL_MOUSE\r\n");
+                        for(uint32_t i = 0; i < num_of_conf; i++) {
+                                ConfigDescParser<
+                                        USB_CLASS_HID,
+                                        HID_BOOT_INTF_SUBCLASS,
+                                        HID_PROTOCOL_MOUSE,
+                                        CP_MASK_COMPARE_ALL> confDescrParserB(this);
+
+                                pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB);
+                                if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL))))
+                                        break;
+
+                        }
+                }
+        }
+        USBTRACE2("bNumEP:", bNumEP);
+
+        if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) {
+                rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+                goto Fail;
+        }
+
+	// Assign epInfo to epinfo pointer
+	rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+        //USBTRACE2("setEpInfoEntry returned ", rcode);
+        USBTRACE2("Cnf:", bConfNum);
+
+        delay(1000);
+
+	// Set Configuration Value
+	rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+	if(rcode)
+		goto FailSetConfDescr;
+
+        delay(1000);
+
+        USBTRACE2("bIfaceNum:", bIfaceNum);
+        USBTRACE2("bNumIface:", bNumIface);
+
+        // Yes, mouse wants SetProtocol and SetIdle too!
+        for(uint32_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
+                USBTRACE2("\r\nInterface:", i);
+                rcode = SetProtocol(i, HID_BOOT_PROTOCOL);
+                if(rcode) goto FailSetProtocol;
+                USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode);
+                rcode = SetIdle(i, 0, 0);
+                USBTRACE2("SET_IDLE rcode:", rcode);
+                // if(rcode) goto FailSetIdle; This can fail.
+                // Get the RPIPE and just throw it away.
+                SinkParser <USBReadParser, uint32_t, uint32_t> sink;
+                rcode = GetReportDescr(i, (USBReadParser *)&sink);
+                USBTRACE2("RPIPE rcode:", rcode);
+        }
+
+        // Get RPIPE and throw it away.
+
+        if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
+                // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec.
+                // kana, compose, scroll, caps, num
+                rcode = 0x20; // Reuse rcode.
+                while(rcode) {
+                        rcode >>= 1;
+                        // Ignore any error returned, we don't care if LED is not supported
+                        SetReport(0, 0, 2, 0, 1, (uint8_t*)&rcode); // Eventually becomes zero (All off)
+                        delay(25);
+                }
+        }
+        USBTRACE("BM configured\r\n");
+
+	bPollEnable = true;
+	return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+        NotifyFailGetDevDescr();
+        goto Fail;
+#endif
+
+        //FailSetDevTblEntry:
+        //#ifdef DEBUG_USB_HOST
+        //        NotifyFailSetDevTblEntry();
+        //        goto Fail;
+        //#endif
+
+        //FailGetConfDescr:
+        //#ifdef DEBUG_USB_HOST
+        //        NotifyFailGetConfDescr();
+        //        goto Fail;
+        //#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+        NotifyFailSetConfDescr();
+        goto Fail;
+#endif
+
+FailSetProtocol:
+#ifdef DEBUG_USB_HOST
+        USBTRACE("SetProto:");
+        goto Fail;
+#endif
+
+        //FailSetIdle:
+        //#ifdef DEBUG_USB_HOST
+        //        USBTRACE("SetIdle:");
+        //#endif
+
+Fail:
+#ifdef DEBUG_USB_HOST
+        NotifyFail(rcode);
+#endif
+        Release();
+
+        return rcode;
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+	// If the first configuration satisfies, the others are not considered.
+        //if(bNumEP > 1 && conf != bConfNum)
+        if(bNumEP == totalEndpoints(BOOT_PROTOCOL))
+		return;
+
+	bConfNum = conf;
+	bIfaceNum = iface;
+
+	if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
+                if(pep->bInterval > bInterval) bInterval = pep->bInterval;
+
+		// Fill in the endpoint info structure
+		epInfo[bNumEP].epAddr		= (pep->bEndpointAddress & 0x0F);
+		epInfo[bNumEP].maxPktSize	= (uint8_t)pep->wMaxPacketSize;
+		epInfo[bNumEP].epAttribs		= 0;
+                epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
+		bNumEP++;
+
+	}
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+uint32_t HIDBoot<BOOT_PROTOCOL>::Release() {
+	pUsb->GetAddressPool().FreeAddress(bAddress);
+
+	bConfNum			= 0;
+	bIfaceNum			= 0;
+	bNumEP				= 1;
+	bAddress			= 0;
+	qNextPollTime		= 0;
+	bPollEnable			= false;
+
+	return 0;
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+uint32_t HIDBoot<BOOT_PROTOCOL>::Poll() {
+	uint32_t rcode = 0;
+
+        if(bPollEnable && ((long)(millis() - qNextPollTime) >= 0L)) {
+
+                // To-do: optimize manually, using the for loop only if needed.
+                for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
+                        const uint16_t const_buff_len = 16;
+                        uint8_t buf[const_buff_len];
+
+                        USBTRACE3("(hidboot.h) i=", i, 0x81);
+                        USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81);
+                        USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81);
+                        uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize;
+                        UHD_Pipe_Alloc(bAddress, epInfo[epInterruptInIndex + i].epAddr, USB_HOST_PTYPE_BULK, USB_EP_DIR_IN, epInfo[epInterruptInIndex + i].maxPktSize, 0, USB_HOST_NB_BK_1);
+                        rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, (uint8_t*)&read, buf);
+                        // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint.
+                        // Since keyboard and mice must report at least 3 bytes, we ignore the extra data.
+                        if(!rcode && read > 2) {
+                                if(pRptParser[i])
+                                        pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf);
+#ifdef DEBUG_USB_HOST
+                                // We really don't care about errors and anomalies unless we are debugging.
+                        } else {
+                                if(rcode != USB_ERRORFLOW) {
+                                        USBTRACE3("(hidboot.h) Poll:", rcode, 0x81);
+                                }
+                                if(!rcode && read) {
+                                        USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80);
+                                        USBTRACE3("(hidboot.h) Interface:", i, 0x80);
+                                }
+                        }
+
+                        if(!rcode && read && (UsbDEBUGlvl > 0x7f)) {
+                                for(uint8_t i = 0; i < read; i++) {
+                                        PrintHex<uint8_t > (buf[i], 0x80);
+                                        USBTRACE1(" ", 0x80);
+                                }
+                                if(read)
+                                        USBTRACE1("\r\n", 0x80);
+#endif
+                        }
+
+                }
+                qNextPollTime = millis() + bInterval;
+        }
+        return rcode;
+}
+
+#endif /* HIDBOOT_H_INCLUDED */
diff --git a/libraries/USBHost/src/hidescriptorparser.cpp b/libraries/USBHost/src/hidescriptorparser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1e30d08eb288712b33f022603dad98e8b70f9faa
--- /dev/null
+++ b/libraries/USBHost/src/hidescriptorparser.cpp
@@ -0,0 +1,1599 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#include "hidescriptorparser.h"
+
+const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = {
+        pstrUsagePageGenericDesktopControls,
+        pstrUsagePageSimulationControls,
+        pstrUsagePageVRControls,
+        pstrUsagePageSportControls,
+        pstrUsagePageGameControls,
+        pstrUsagePageGenericDeviceControls,
+        pstrUsagePageKeyboardKeypad,
+        pstrUsagePageLEDs,
+        pstrUsagePageButton,
+        pstrUsagePageOrdinal,
+        pstrUsagePageTelephone,
+        pstrUsagePageConsumer,
+        pstrUsagePageDigitizer,
+        pstrUsagePagePID,
+        pstrUsagePageUnicode
+};
+
+const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = {
+        pstrUsagePageBarCodeScanner,
+        pstrUsagePageScale,
+        pstrUsagePageMSRDevices,
+        pstrUsagePagePointOfSale,
+        pstrUsagePageCameraControl,
+        pstrUsagePageArcade
+};
+const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = {
+        pstrUsagePointer,
+        pstrUsageMouse,
+        pstrUsageJoystick,
+        pstrUsageGamePad,
+        pstrUsageKeyboard,
+        pstrUsageKeypad,
+        pstrUsageMultiAxisController,
+        pstrUsageTabletPCSystemControls
+
+};
+const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = {
+        pstrUsageX,
+        pstrUsageY,
+        pstrUsageZ,
+        pstrUsageRx,
+        pstrUsageRy,
+        pstrUsageRz,
+        pstrUsageSlider,
+        pstrUsageDial,
+        pstrUsageWheel,
+        pstrUsageHatSwitch,
+        pstrUsageCountedBuffer,
+        pstrUsageByteCount,
+        pstrUsageMotionWakeup,
+        pstrUsageStart,
+        pstrUsageSelect,
+        pstrUsagePageReserved,
+        pstrUsageVx,
+        pstrUsageVy,
+        pstrUsageVz,
+        pstrUsageVbrx,
+        pstrUsageVbry,
+        pstrUsageVbrz,
+        pstrUsageVno,
+        pstrUsageFeatureNotification,
+        pstrUsageResolutionMultiplier
+};
+const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = {
+        pstrUsageSystemControl,
+        pstrUsageSystemPowerDown,
+        pstrUsageSystemSleep,
+        pstrUsageSystemWakeup,
+        pstrUsageSystemContextMenu,
+        pstrUsageSystemMainMenu,
+        pstrUsageSystemAppMenu,
+        pstrUsageSystemMenuHelp,
+        pstrUsageSystemMenuExit,
+        pstrUsageSystemMenuSelect,
+        pstrUsageSystemMenuRight,
+        pstrUsageSystemMenuLeft,
+        pstrUsageSystemMenuUp,
+        pstrUsageSystemMenuDown,
+        pstrUsageSystemColdRestart,
+        pstrUsageSystemWarmRestart,
+        pstrUsageDPadUp,
+        pstrUsageDPadDown,
+        pstrUsageDPadRight,
+        pstrUsageDPadLeft
+};
+const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = {
+        pstrUsageSystemDock,
+        pstrUsageSystemUndock,
+        pstrUsageSystemSetup,
+        pstrUsageSystemBreak,
+        pstrUsageSystemDebuggerBreak,
+        pstrUsageApplicationBreak,
+        pstrUsageApplicationDebuggerBreak,
+        pstrUsageSystemSpeakerMute,
+        pstrUsageSystemHibernate
+};
+const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = {
+        pstrUsageSystemDisplayInvert,
+        pstrUsageSystemDisplayInternal,
+        pstrUsageSystemDisplayExternal,
+        pstrUsageSystemDisplayBoth,
+        pstrUsageSystemDisplayDual,
+        pstrUsageSystemDisplayToggleIntExt,
+        pstrUsageSystemDisplaySwapPriSec,
+        pstrUsageSystemDisplayLCDAutoscale
+};
+const char * const ReportDescParserBase::simuTitles0[] PROGMEM = {
+        pstrUsageFlightSimulationDevice,
+        pstrUsageAutomobileSimulationDevice,
+        pstrUsageTankSimulationDevice,
+        pstrUsageSpaceshipSimulationDevice,
+        pstrUsageSubmarineSimulationDevice,
+        pstrUsageSailingSimulationDevice,
+        pstrUsageMotocicleSimulationDevice,
+        pstrUsageSportsSimulationDevice,
+        pstrUsageAirplaneSimulationDevice,
+        pstrUsageHelicopterSimulationDevice,
+        pstrUsageMagicCarpetSimulationDevice,
+        pstrUsageBicycleSimulationDevice
+};
+const char * const ReportDescParserBase::simuTitles1[] PROGMEM = {
+        pstrUsageFlightControlStick,
+        pstrUsageFlightStick,
+        pstrUsageCyclicControl,
+        pstrUsageCyclicTrim,
+        pstrUsageFlightYoke,
+        pstrUsageTrackControl
+};
+const char * const ReportDescParserBase::simuTitles2[] PROGMEM = {
+        pstrUsageAileron,
+        pstrUsageAileronTrim,
+        pstrUsageAntiTorqueControl,
+        pstrUsageAutopilotEnable,
+        pstrUsageChaffRelease,
+        pstrUsageCollectiveControl,
+        pstrUsageDiveBrake,
+        pstrUsageElectronicCountermeasures,
+        pstrUsageElevator,
+        pstrUsageElevatorTrim,
+        pstrUsageRudder,
+        pstrUsageThrottle,
+        pstrUsageFlightCommunications,
+        pstrUsageFlareRelease,
+        pstrUsageLandingGear,
+        pstrUsageToeBrake,
+        pstrUsageTrigger,
+        pstrUsageWeaponsArm,
+        pstrUsageWeaponsSelect,
+        pstrUsageWingFlaps,
+        pstrUsageAccelerator,
+        pstrUsageBrake,
+        pstrUsageClutch,
+        pstrUsageShifter,
+        pstrUsageSteering,
+        pstrUsageTurretDirection,
+        pstrUsageBarrelElevation,
+        pstrUsageDivePlane,
+        pstrUsageBallast,
+        pstrUsageBicycleCrank,
+        pstrUsageHandleBars,
+        pstrUsageFrontBrake,
+        pstrUsageRearBrake
+};
+const char * const ReportDescParserBase::vrTitles0[] PROGMEM = {
+        pstrUsageBelt,
+        pstrUsageBodySuit,
+        pstrUsageFlexor,
+        pstrUsageGlove,
+        pstrUsageHeadTracker,
+        pstrUsageHeadMountedDisplay,
+        pstrUsageHandTracker,
+        pstrUsageOculometer,
+        pstrUsageVest,
+        pstrUsageAnimatronicDevice
+};
+const char * const ReportDescParserBase::vrTitles1[] PROGMEM = {
+        pstrUsageStereoEnable,
+        pstrUsageDisplayEnable
+};
+const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = {
+        pstrUsageBaseballBat,
+        pstrUsageGolfClub,
+        pstrUsageRowingMachine,
+        pstrUsageTreadmill
+};
+const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = {
+        pstrUsageOar,
+        pstrUsageSlope,
+        pstrUsageRate,
+        pstrUsageStickSpeed,
+        pstrUsageStickFaceAngle,
+        pstrUsageStickHeelToe,
+        pstrUsageStickFollowThough,
+        pstrUsageStickTempo,
+        pstrUsageStickType,
+        pstrUsageStickHeight
+};
+const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = {
+        pstrUsagePutter,
+        pstrUsage1Iron,
+        pstrUsage2Iron,
+        pstrUsage3Iron,
+        pstrUsage4Iron,
+        pstrUsage5Iron,
+        pstrUsage6Iron,
+        pstrUsage7Iron,
+        pstrUsage8Iron,
+        pstrUsage9Iron,
+        pstrUsage10Iron,
+        pstrUsage11Iron,
+        pstrUsageSandWedge,
+        pstrUsageLoftWedge,
+        pstrUsagePowerWedge,
+        pstrUsage1Wood,
+        pstrUsage3Wood,
+        pstrUsage5Wood,
+        pstrUsage7Wood,
+        pstrUsage9Wood
+};
+const char * const ReportDescParserBase::gameTitles0[] PROGMEM = {
+        pstrUsage3DGameController,
+        pstrUsagePinballDevice,
+        pstrUsageGunDevice
+};
+const char * const ReportDescParserBase::gameTitles1[] PROGMEM = {
+        pstrUsagePointOfView,
+        pstrUsageTurnRightLeft,
+        pstrUsagePitchForwardBackward,
+        pstrUsageRollRightLeft,
+        pstrUsageMoveRightLeft,
+        pstrUsageMoveForwardBackward,
+        pstrUsageMoveUpDown,
+        pstrUsageLeanRightLeft,
+        pstrUsageLeanForwardBackward,
+        pstrUsageHeightOfPOV,
+        pstrUsageFlipper,
+        pstrUsageSecondaryFlipper,
+        pstrUsageBump,
+        pstrUsageNewGame,
+        pstrUsageShootBall,
+        pstrUsagePlayer,
+        pstrUsageGunBolt,
+        pstrUsageGunClip,
+        pstrUsageGunSelector,
+        pstrUsageGunSingleShot,
+        pstrUsageGunBurst,
+        pstrUsageGunAutomatic,
+        pstrUsageGunSafety,
+        pstrUsageGamepadFireJump,
+        pstrUsageGamepadTrigger
+};
+const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = {
+        pstrUsageBatteryStrength,
+        pstrUsageWirelessChannel,
+        pstrUsageWirelessID,
+        pstrUsageDiscoverWirelessControl,
+        pstrUsageSecurityCodeCharEntered,
+        pstrUsageSecurityCodeCharErased,
+        pstrUsageSecurityCodeCleared
+};
+const char * const ReportDescParserBase::ledTitles[] PROGMEM = {
+        pstrUsageNumLock,
+        pstrUsageCapsLock,
+        pstrUsageScrollLock,
+        pstrUsageCompose,
+        pstrUsageKana,
+        pstrUsagePower,
+        pstrUsageShift,
+        pstrUsageDoNotDisturb,
+        pstrUsageMute,
+        pstrUsageToneEnable,
+        pstrUsageHighCutFilter,
+        pstrUsageLowCutFilter,
+        pstrUsageEqualizerEnable,
+        pstrUsageSoundFieldOn,
+        pstrUsageSurroundOn,
+        pstrUsageRepeat,
+        pstrUsageStereo,
+        pstrUsageSamplingRateDetect,
+        pstrUsageSpinning,
+        pstrUsageCAV,
+        pstrUsageCLV,
+        pstrUsageRecordingFormatDetect,
+        pstrUsageOffHook,
+        pstrUsageRing,
+        pstrUsageMessageWaiting,
+        pstrUsageDataMode,
+        pstrUsageBatteryOperation,
+        pstrUsageBatteryOK,
+        pstrUsageBatteryLow,
+        pstrUsageSpeaker,
+        pstrUsageHeadSet,
+        pstrUsageHold,
+        pstrUsageMicrophone,
+        pstrUsageCoverage,
+        pstrUsageNightMode,
+        pstrUsageSendCalls,
+        pstrUsageCallPickup,
+        pstrUsageConference,
+        pstrUsageStandBy,
+        pstrUsageCameraOn,
+        pstrUsageCameraOff,
+        pstrUsageOnLine,
+        pstrUsageOffLine,
+        pstrUsageBusy,
+        pstrUsageReady,
+        pstrUsagePaperOut,
+        pstrUsagePaperJam,
+        pstrUsageRemote,
+        pstrUsageForward,
+        pstrUsageReverse,
+        pstrUsageStop,
+        pstrUsageRewind,
+        pstrUsageFastForward,
+        pstrUsagePlay,
+        pstrUsagePause,
+        pstrUsageRecord,
+        pstrUsageError,
+        pstrUsageSelectedIndicator,
+        pstrUsageInUseIndicator,
+        pstrUsageMultiModeIndicator,
+        pstrUsageIndicatorOn,
+        pstrUsageIndicatorFlash,
+        pstrUsageIndicatorSlowBlink,
+        pstrUsageIndicatorFastBlink,
+        pstrUsageIndicatorOff,
+        pstrUsageFlashOnTime,
+        pstrUsageSlowBlinkOnTime,
+        pstrUsageSlowBlinkOffTime,
+        pstrUsageFastBlinkOnTime,
+        pstrUsageFastBlinkOffTime,
+        pstrUsageIndicatorColor,
+        pstrUsageIndicatorRed,
+        pstrUsageIndicatorGreen,
+        pstrUsageIndicatorAmber,
+        pstrUsageGenericIndicator,
+        pstrUsageSystemSuspend,
+        pstrUsageExternalPowerConnected
+};
+const char * const ReportDescParserBase::telTitles0 [] PROGMEM = {
+        pstrUsagePhone,
+        pstrUsageAnsweringMachine,
+        pstrUsageMessageControls,
+        pstrUsageHandset,
+        pstrUsageHeadset,
+        pstrUsageTelephonyKeyPad,
+        pstrUsageProgrammableButton
+};
+const char * const ReportDescParserBase::telTitles1 [] PROGMEM = {
+        pstrUsageHookSwitch,
+        pstrUsageFlash,
+        pstrUsageFeature,
+        pstrUsageHold,
+        pstrUsageRedial,
+        pstrUsageTransfer,
+        pstrUsageDrop,
+        pstrUsagePark,
+        pstrUsageForwardCalls,
+        pstrUsageAlternateFunction,
+        pstrUsageLine,
+        pstrUsageSpeakerPhone,
+        pstrUsageConference,
+        pstrUsageRingEnable,
+        pstrUsageRingSelect,
+        pstrUsagePhoneMute,
+        pstrUsageCallerID,
+        pstrUsageSend
+};
+const char * const ReportDescParserBase::telTitles2 [] PROGMEM = {
+        pstrUsageSpeedDial,
+        pstrUsageStoreNumber,
+        pstrUsageRecallNumber,
+        pstrUsagePhoneDirectory
+};
+const char * const ReportDescParserBase::telTitles3 [] PROGMEM = {
+        pstrUsageVoiceMail,
+        pstrUsageScreenCalls,
+        pstrUsageDoNotDisturb,
+        pstrUsageMessage,
+        pstrUsageAnswerOnOff
+};
+const char * const ReportDescParserBase::telTitles4 [] PROGMEM = {
+        pstrUsageInsideDialTone,
+        pstrUsageOutsideDialTone,
+        pstrUsageInsideRingTone,
+        pstrUsageOutsideRingTone,
+        pstrUsagePriorityRingTone,
+        pstrUsageInsideRingback,
+        pstrUsagePriorityRingback,
+        pstrUsageLineBusyTone,
+        pstrUsageReorderTone,
+        pstrUsageCallWaitingTone,
+        pstrUsageConfirmationTone1,
+        pstrUsageConfirmationTone2,
+        pstrUsageTonesOff,
+        pstrUsageOutsideRingback,
+        pstrUsageRinger
+};
+const char * const ReportDescParserBase::telTitles5 [] PROGMEM = {
+        pstrUsagePhoneKey0,
+        pstrUsagePhoneKey1,
+        pstrUsagePhoneKey2,
+        pstrUsagePhoneKey3,
+        pstrUsagePhoneKey4,
+        pstrUsagePhoneKey5,
+        pstrUsagePhoneKey6,
+        pstrUsagePhoneKey7,
+        pstrUsagePhoneKey8,
+        pstrUsagePhoneKey9,
+        pstrUsagePhoneKeyStar,
+        pstrUsagePhoneKeyPound,
+        pstrUsagePhoneKeyA,
+        pstrUsagePhoneKeyB,
+        pstrUsagePhoneKeyC,
+        pstrUsagePhoneKeyD
+};
+const char * const ReportDescParserBase::consTitles0[] PROGMEM = {
+        pstrUsageConsumerControl,
+        pstrUsageNumericKeyPad,
+        pstrUsageProgrammableButton,
+        pstrUsageMicrophone,
+        pstrUsageHeadphone,
+        pstrUsageGraphicEqualizer
+};
+const char * const ReportDescParserBase::consTitles1[] PROGMEM = {
+        pstrUsagePlus10,
+        pstrUsagePlus100,
+        pstrUsageAMPM
+};
+const char * const ReportDescParserBase::consTitles2[] PROGMEM = {
+        pstrUsagePower,
+        pstrUsageReset,
+        pstrUsageSleep,
+        pstrUsageSleepAfter,
+        pstrUsageSleepMode,
+        pstrUsageIllumination,
+        pstrUsageFunctionButtons
+
+};
+const char * const ReportDescParserBase::consTitles3[] PROGMEM = {
+        pstrUsageMenu,
+        pstrUsageMenuPick,
+        pstrUsageMenuUp,
+        pstrUsageMenuDown,
+        pstrUsageMenuLeft,
+        pstrUsageMenuRight,
+        pstrUsageMenuEscape,
+        pstrUsageMenuValueIncrease,
+        pstrUsageMenuValueDecrease
+};
+const char * const ReportDescParserBase::consTitles4[] PROGMEM = {
+        pstrUsageDataOnScreen,
+        pstrUsageClosedCaption,
+        pstrUsageClosedCaptionSelect,
+        pstrUsageVCRTV,
+        pstrUsageBroadcastMode,
+        pstrUsageSnapshot,
+        pstrUsageStill
+};
+const char * const ReportDescParserBase::consTitles5[] PROGMEM = {
+        pstrUsageSelection,
+        pstrUsageAssignSelection,
+        pstrUsageModeStep,
+        pstrUsageRecallLast,
+        pstrUsageEnterChannel,
+        pstrUsageOrderMovie,
+        pstrUsageChannel,
+        pstrUsageMediaSelection,
+        pstrUsageMediaSelectComputer,
+        pstrUsageMediaSelectTV,
+        pstrUsageMediaSelectWWW,
+        pstrUsageMediaSelectDVD,
+        pstrUsageMediaSelectTelephone,
+        pstrUsageMediaSelectProgramGuide,
+        pstrUsageMediaSelectVideoPhone,
+        pstrUsageMediaSelectGames,
+        pstrUsageMediaSelectMessages,
+        pstrUsageMediaSelectCD,
+        pstrUsageMediaSelectVCR,
+        pstrUsageMediaSelectTuner,
+        pstrUsageQuit,
+        pstrUsageHelp,
+        pstrUsageMediaSelectTape,
+        pstrUsageMediaSelectCable,
+        pstrUsageMediaSelectSatellite,
+        pstrUsageMediaSelectSecurity,
+        pstrUsageMediaSelectHome,
+        pstrUsageMediaSelectCall,
+        pstrUsageChannelIncrement,
+        pstrUsageChannelDecrement,
+        pstrUsageMediaSelectSAP,
+        pstrUsagePageReserved,
+        pstrUsageVCRPlus,
+        pstrUsageOnce,
+        pstrUsageDaily,
+        pstrUsageWeekly,
+        pstrUsageMonthly
+};
+const char * const ReportDescParserBase::consTitles6[] PROGMEM = {
+        pstrUsagePlay,
+        pstrUsagePause,
+        pstrUsageRecord,
+        pstrUsageFastForward,
+        pstrUsageRewind,
+        pstrUsageScanNextTrack,
+        pstrUsageScanPreviousTrack,
+        pstrUsageStop,
+        pstrUsageEject,
+        pstrUsageRandomPlay,
+        pstrUsageSelectDisk,
+        pstrUsageEnterDisk,
+        pstrUsageRepeat,
+        pstrUsageTracking,
+        pstrUsageTrackNormal,
+        pstrUsageSlowTracking,
+        pstrUsageFrameForward,
+        pstrUsageFrameBackwards,
+        pstrUsageMark,
+        pstrUsageClearMark,
+        pstrUsageRepeatFromMark,
+        pstrUsageReturnToMark,
+        pstrUsageSearchMarkForward,
+        pstrUsageSearchMarkBackwards,
+        pstrUsageCounterReset,
+        pstrUsageShowCounter,
+        pstrUsageTrackingIncrement,
+        pstrUsageTrackingDecrement,
+        pstrUsageStopEject,
+        pstrUsagePlayPause,
+        pstrUsagePlaySkip
+};
+const char * const ReportDescParserBase::consTitles7[] PROGMEM = {
+        pstrUsageVolume,
+        pstrUsageBalance,
+        pstrUsageMute,
+        pstrUsageBass,
+        pstrUsageTreble,
+        pstrUsageBassBoost,
+        pstrUsageSurroundMode,
+        pstrUsageLoudness,
+        pstrUsageMPX,
+        pstrUsageVolumeIncrement,
+        pstrUsageVolumeDecrement
+};
+const char * const ReportDescParserBase::consTitles8[] PROGMEM = {
+        pstrUsageSpeedSelect,
+        pstrUsagePlaybackSpeed,
+        pstrUsageStandardPlay,
+        pstrUsageLongPlay,
+        pstrUsageExtendedPlay,
+        pstrUsageSlow
+};
+const char * const ReportDescParserBase::consTitles9[] PROGMEM = {
+        pstrUsageFanEnable,
+        pstrUsageFanSpeed,
+        pstrUsageLightEnable,
+        pstrUsageLightIlluminationLevel,
+        pstrUsageClimateControlEnable,
+        pstrUsageRoomTemperature,
+        pstrUsageSecurityEnable,
+        pstrUsageFireAlarm,
+        pstrUsagePoliceAlarm,
+        pstrUsageProximity,
+        pstrUsageMotion,
+        pstrUsageDuresAlarm,
+        pstrUsageHoldupAlarm,
+        pstrUsageMedicalAlarm
+};
+const char * const ReportDescParserBase::consTitlesA[] PROGMEM = {
+        pstrUsageBalanceRight,
+        pstrUsageBalanceLeft,
+        pstrUsageBassIncrement,
+        pstrUsageBassDecrement,
+        pstrUsageTrebleIncrement,
+        pstrUsageTrebleDecrement
+};
+const char * const ReportDescParserBase::consTitlesB[] PROGMEM = {
+        pstrUsageSpeakerSystem,
+        pstrUsageChannelLeft,
+        pstrUsageChannelRight,
+        pstrUsageChannelCenter,
+        pstrUsageChannelFront,
+        pstrUsageChannelCenterFront,
+        pstrUsageChannelSide,
+        pstrUsageChannelSurround,
+        pstrUsageChannelLowFreqEnhancement,
+        pstrUsageChannelTop,
+        pstrUsageChannelUnknown
+};
+const char * const ReportDescParserBase::consTitlesC[] PROGMEM = {
+        pstrUsageSubChannel,
+        pstrUsageSubChannelIncrement,
+        pstrUsageSubChannelDecrement,
+        pstrUsageAlternateAudioIncrement,
+        pstrUsageAlternateAudioDecrement
+};
+const char * const ReportDescParserBase::consTitlesD[] PROGMEM = {
+        pstrUsageApplicationLaunchButtons,
+        pstrUsageALLaunchButtonConfigTool,
+        pstrUsageALProgrammableButton,
+        pstrUsageALConsumerControlConfig,
+        pstrUsageALWordProcessor,
+        pstrUsageALTextEditor,
+        pstrUsageALSpreadsheet,
+        pstrUsageALGraphicsEditor,
+        pstrUsageALPresentationApp,
+        pstrUsageALDatabaseApp,
+        pstrUsageALEmailReader,
+        pstrUsageALNewsreader,
+        pstrUsageALVoicemail,
+        pstrUsageALContactsAddressBook,
+        pstrUsageALCalendarSchedule,
+        pstrUsageALTaskProjectManager,
+        pstrUsageALLogJournalTimecard,
+        pstrUsageALCheckbookFinance,
+        pstrUsageALCalculator,
+        pstrUsageALAVCapturePlayback,
+        pstrUsageALLocalMachineBrowser,
+        pstrUsageALLANWANBrow,
+        pstrUsageALInternetBrowser,
+        pstrUsageALRemoteNetISPConnect,
+        pstrUsageALNetworkConference,
+        pstrUsageALNetworkChat,
+        pstrUsageALTelephonyDialer,
+        pstrUsageALLogon,
+        pstrUsageALLogoff,
+        pstrUsageALLogonLogoff,
+        pstrUsageALTermLockScrSav,
+        pstrUsageALControlPannel,
+        pstrUsageALCommandLineProcessorRun,
+        pstrUsageALProcessTaskManager,
+        pstrUsageALSelectTaskApplication,
+        pstrUsageALNextTaskApplication,
+        pstrUsageALPreviousTaskApplication,
+        pstrUsageALPreemptiveHaltTaskApp,
+        pstrUsageALIntegratedHelpCenter,
+        pstrUsageALDocuments,
+        pstrUsageALThesaurus,
+        pstrUsageALDictionary,
+        pstrUsageALDesktop,
+        pstrUsageALSpellCheck,
+        pstrUsageALGrammarCheck,
+        pstrUsageALWirelessStatus,
+        pstrUsageALKeyboardLayout,
+        pstrUsageALVirusProtection,
+        pstrUsageALEncryption,
+        pstrUsageALScreenSaver,
+        pstrUsageALAlarms,
+        pstrUsageALClock,
+        pstrUsageALFileBrowser,
+        pstrUsageALPowerStatus,
+        pstrUsageALImageBrowser,
+        pstrUsageALAudioBrowser,
+        pstrUsageALMovieBrowser,
+        pstrUsageALDigitalRightsManager,
+        pstrUsageALDigitalWallet,
+        pstrUsagePageReserved,
+        pstrUsageALInstantMessaging,
+        pstrUsageALOEMFeaturesBrowser,
+        pstrUsageALOEMHelp,
+        pstrUsageALOnlineCommunity,
+        pstrUsageALEntertainmentContentBrow,
+        pstrUsageALOnlineShoppingBrowser,
+        pstrUsageALSmartCardInfoHelp,
+        pstrUsageALMarketMonitorFinBrowser,
+        pstrUsageALCustomCorpNewsBrowser,
+        pstrUsageALOnlineActivityBrowser,
+        pstrUsageALResearchSearchBrowser,
+        pstrUsageALAudioPlayer
+};
+const char * const ReportDescParserBase::consTitlesE[] PROGMEM = {
+        pstrUsageGenericGUIAppControls,
+        pstrUsageACNew,
+        pstrUsageACOpen,
+        pstrUsageACClose,
+        pstrUsageACExit,
+        pstrUsageACMaximize,
+        pstrUsageACMinimize,
+        pstrUsageACSave,
+        pstrUsageACPrint,
+        pstrUsageACProperties,
+        pstrUsageACUndo,
+        pstrUsageACCopy,
+        pstrUsageACCut,
+        pstrUsageACPaste,
+        pstrUsageACSelectAll,
+        pstrUsageACFind,
+        pstrUsageACFindAndReplace,
+        pstrUsageACSearch,
+        pstrUsageACGoto,
+        pstrUsageACHome,
+        pstrUsageACBack,
+        pstrUsageACForward,
+        pstrUsageACStop,
+        pstrUsageACRefresh,
+        pstrUsageACPreviousLink,
+        pstrUsageACNextLink,
+        pstrUsageACBookmarks,
+        pstrUsageACHistory,
+        pstrUsageACSubscriptions,
+        pstrUsageACZoomIn,
+        pstrUsageACZoomOut,
+        pstrUsageACZoom,
+        pstrUsageACFullScreenView,
+        pstrUsageACNormalView,
+        pstrUsageACViewToggle,
+        pstrUsageACScrollUp,
+        pstrUsageACScrollDown,
+        pstrUsageACScroll,
+        pstrUsageACPanLeft,
+        pstrUsageACPanRight,
+        pstrUsageACPan,
+        pstrUsageACNewWindow,
+        pstrUsageACTileHoriz,
+        pstrUsageACTileVert,
+        pstrUsageACFormat,
+        pstrUsageACEdit,
+        pstrUsageACBold,
+        pstrUsageACItalics,
+        pstrUsageACUnderline,
+        pstrUsageACStrikethrough,
+        pstrUsageACSubscript,
+        pstrUsageACSuperscript,
+        pstrUsageACAllCaps,
+        pstrUsageACRotate,
+        pstrUsageACResize,
+        pstrUsageACFlipHorizontal,
+        pstrUsageACFlipVertical,
+        pstrUsageACMirrorHorizontal,
+        pstrUsageACMirrorVertical,
+        pstrUsageACFontSelect,
+        pstrUsageACFontColor,
+        pstrUsageACFontSize,
+        pstrUsageACJustifyLeft,
+        pstrUsageACJustifyCenterH,
+        pstrUsageACJustifyRight,
+        pstrUsageACJustifyBlockH,
+        pstrUsageACJustifyTop,
+        pstrUsageACJustifyCenterV,
+        pstrUsageACJustifyBottom,
+        pstrUsageACJustifyBlockV,
+        pstrUsageACIndentDecrease,
+        pstrUsageACIndentIncrease,
+        pstrUsageACNumberedList,
+        pstrUsageACRestartNumbering,
+        pstrUsageACBulletedList,
+        pstrUsageACPromote,
+        pstrUsageACDemote,
+        pstrUsageACYes,
+        pstrUsageACNo,
+        pstrUsageACCancel,
+        pstrUsageACCatalog,
+        pstrUsageACBuyChkout,
+        pstrUsageACAddToCart,
+        pstrUsageACExpand,
+        pstrUsageACExpandAll,
+        pstrUsageACCollapse,
+        pstrUsageACCollapseAll,
+        pstrUsageACPrintPreview,
+        pstrUsageACPasteSpecial,
+        pstrUsageACInsertMode,
+        pstrUsageACDelete,
+        pstrUsageACLock,
+        pstrUsageACUnlock,
+        pstrUsageACProtect,
+        pstrUsageACUnprotect,
+        pstrUsageACAttachComment,
+        pstrUsageACDeleteComment,
+        pstrUsageACViewComment,
+        pstrUsageACSelectWord,
+        pstrUsageACSelectSentence,
+        pstrUsageACSelectParagraph,
+        pstrUsageACSelectColumn,
+        pstrUsageACSelectRow,
+        pstrUsageACSelectTable,
+        pstrUsageACSelectObject,
+        pstrUsageACRedoRepeat,
+        pstrUsageACSort,
+        pstrUsageACSortAscending,
+        pstrUsageACSortDescending,
+        pstrUsageACFilter,
+        pstrUsageACSetClock,
+        pstrUsageACViewClock,
+        pstrUsageACSelectTimeZone,
+        pstrUsageACEditTimeZone,
+        pstrUsageACSetAlarm,
+        pstrUsageACClearAlarm,
+        pstrUsageACSnoozeAlarm,
+        pstrUsageACResetAlarm,
+        pstrUsageACSyncronize,
+        pstrUsageACSendReceive,
+        pstrUsageACSendTo,
+        pstrUsageACReply,
+        pstrUsageACReplyAll,
+        pstrUsageACForwardMessage,
+        pstrUsageACSend,
+        pstrUsageACAttachFile,
+        pstrUsageACUpload,
+        pstrUsageACDownload,
+        pstrUsageACSetBorders,
+        pstrUsageACInsertRow,
+        pstrUsageACInsertColumn,
+        pstrUsageACInsertFile,
+        pstrUsageACInsertPicture,
+        pstrUsageACInsertObject,
+        pstrUsageACInsertSymbol,
+        pstrUsageACSaveAndClose,
+        pstrUsageACRename,
+        pstrUsageACMerge,
+        pstrUsageACSplit,
+        pstrUsageACDistributeHorizontaly,
+        pstrUsageACDistributeVerticaly
+};
+const char * const ReportDescParserBase::digitTitles0[] PROGMEM = {
+        pstrUsageDigitizer,
+        pstrUsagePen,
+        pstrUsageLightPen,
+        pstrUsageTouchScreen,
+        pstrUsageTouchPad,
+        pstrUsageWhiteBoard,
+        pstrUsageCoordinateMeasuringMachine,
+        pstrUsage3DDigitizer,
+        pstrUsageStereoPlotter,
+        pstrUsageArticulatedArm,
+        pstrUsageArmature,
+        pstrUsageMultiplePointDigitizer,
+        pstrUsageFreeSpaceWand
+};
+const char * const ReportDescParserBase::digitTitles1[] PROGMEM = {
+        pstrUsageStylus,
+        pstrUsagePuck,
+        pstrUsageFinger
+
+};
+const char * const ReportDescParserBase::digitTitles2[] PROGMEM = {
+        pstrUsageTipPressure,
+        pstrUsageBarrelPressure,
+        pstrUsageInRange,
+        pstrUsageTouch,
+        pstrUsageUntouch,
+        pstrUsageTap,
+        pstrUsageQuality,
+        pstrUsageDataValid,
+        pstrUsageTransducerIndex,
+        pstrUsageTabletFunctionKeys,
+        pstrUsageProgramChangeKeys,
+        pstrUsageBatteryStrength,
+        pstrUsageInvert,
+        pstrUsageXTilt,
+        pstrUsageYTilt,
+        pstrUsageAzimuth,
+        pstrUsageAltitude,
+        pstrUsageTwist,
+        pstrUsageTipSwitch,
+        pstrUsageSecondaryTipSwitch,
+        pstrUsageBarrelSwitch,
+        pstrUsageEraser,
+        pstrUsageTabletPick
+};
+const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = {
+        pstrUsageAlphanumericDisplay,
+        pstrUsageBitmappedDisplay
+};
+const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = {
+        pstrUsageDisplayAttributesReport,
+        pstrUsageASCIICharacterSet,
+        pstrUsageDataReadBack,
+        pstrUsageFontReadBack,
+        pstrUsageDisplayControlReport,
+        pstrUsageClearDisplay,
+        pstrUsageDisplayEnable,
+        pstrUsageScreenSaverDelay,
+        pstrUsageScreenSaverEnable,
+        pstrUsageVerticalScroll,
+        pstrUsageHorizontalScroll,
+        pstrUsageCharacterReport,
+        pstrUsageDisplayData,
+        pstrUsageDisplayStatus,
+        pstrUsageStatusNotReady,
+        pstrUsageStatusReady,
+        pstrUsageErrorNotALoadableCharacter,
+        pstrUsageErrorFotDataCanNotBeRead,
+        pstrUsageCursorPositionReport,
+        pstrUsageRow,
+        pstrUsageColumn,
+        pstrUsageRows,
+        pstrUsageColumns,
+        pstrUsageCursorPixelPosition,
+        pstrUsageCursorMode,
+        pstrUsageCursorEnable,
+        pstrUsageCursorBlink,
+        pstrUsageFontReport,
+        pstrUsageFontData,
+        pstrUsageCharacterWidth,
+        pstrUsageCharacterHeight,
+        pstrUsageCharacterSpacingHorizontal,
+        pstrUsageCharacterSpacingVertical,
+        pstrUsageUnicodeCharset,
+        pstrUsageFont7Segment,
+        pstrUsage7SegmentDirectMap,
+        pstrUsageFont14Segment,
+        pstrUsage14SegmentDirectMap,
+        pstrUsageDisplayBrightness,
+        pstrUsageDisplayContrast,
+        pstrUsageCharacterAttribute,
+        pstrUsageAttributeReadback,
+        pstrUsageAttributeData,
+        pstrUsageCharAttributeEnhance,
+        pstrUsageCharAttributeUnderline,
+        pstrUsageCharAttributeBlink
+};
+const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = {
+        pstrUsageBitmapSizeX,
+        pstrUsageBitmapSizeY,
+        pstrUsagePageReserved,
+        pstrUsageBitDepthFormat,
+        pstrUsageDisplayOrientation,
+        pstrUsagePaletteReport,
+        pstrUsagePaletteDataSize,
+        pstrUsagePaletteDataOffset,
+        pstrUsagePaletteData,
+        pstrUsageBlitReport,
+        pstrUsageBlitRectangleX1,
+        pstrUsageBlitRectangleY1,
+        pstrUsageBlitRectangleX2,
+        pstrUsageBlitRectangleY2,
+        pstrUsageBlitData,
+        pstrUsageSoftButton,
+        pstrUsageSoftButtonID,
+        pstrUsageSoftButtonSide,
+        pstrUsageSoftButtonOffset1,
+        pstrUsageSoftButtonOffset2,
+        pstrUsageSoftButtonReport
+};
+const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = {
+        pstrUsageVCRAcquisition,
+        pstrUsageFreezeThaw,
+        pstrUsageClipStore,
+        pstrUsageUpdate,
+        pstrUsageNext,
+        pstrUsageSave,
+        pstrUsagePrint,
+        pstrUsageMicrophoneEnable
+};
+const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = {
+        pstrUsageCine,
+        pstrUsageTransmitPower,
+        pstrUsageVolume,
+        pstrUsageFocus,
+        pstrUsageDepth
+};
+const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = {
+        pstrUsageSoftStepPrimary,
+        pstrUsageSoftStepSecondary
+};
+const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = {
+        pstrUsageZoomSelect,
+        pstrUsageZoomAdjust,
+        pstrUsageSpectralDopplerModeSelect,
+        pstrUsageSpectralDopplerModeAdjust,
+        pstrUsageColorDopplerModeSelect,
+        pstrUsageColorDopplerModeAdjust,
+        pstrUsageMotionModeSelect,
+        pstrUsageMotionModeAdjust,
+        pstrUsage2DModeSelect,
+        pstrUsage2DModeAdjust
+};
+const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = {
+        pstrUsageSoftControlSelect,
+        pstrUsageSoftControlAdjust
+};
+
+void ReportDescParserBase::Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) {
+        uint32_t cntdn = (uint32_t)len;
+        uint8_t *p = (uint8_t*)pbuf;
+
+
+        totalSize = 0;
+
+        while(cntdn) {
+                //USB_HOST_SERIAL.println("");
+                //PrintHex<uint16_t>(offset + len - cntdn);
+                //USB_HOST_SERIAL.print(":");
+
+                ParseItem(&p, &cntdn);
+
+                //if (ParseItem(&p, &cntdn))
+                //	return;
+        }
+        //USBTRACE2("Total:", totalSize);
+}
+
+void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) {
+        E_Notify(PSTR("("), 0x80);
+        for(; len; p++, len--)
+                PrintHex<uint8_t > (*p, 0x80);
+        E_Notify(PSTR(")"), 0x80);
+}
+
+void ReportDescParserBase::PrintByteValue(uint8_t data) {
+        E_Notify(PSTR("("), 0x80);
+        PrintHex<uint8_t > (data, 0x80);
+        E_Notify(PSTR(")"), 0x80);
+}
+
+void ReportDescParserBase::PrintItemTitle(uint8_t prefix) {
+        switch(prefix & (TYPE_MASK | TAG_MASK)) {
+                case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
+                        E_Notify(PSTR("\r\nPush"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_POP):
+                        E_Notify(PSTR("\r\nPop"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
+                        E_Notify(PSTR("\r\nUsage Page"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
+                        E_Notify(PSTR("\r\nLogical Min"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
+                        E_Notify(PSTR("\r\nLogical Max"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
+                        E_Notify(PSTR("\r\nPhysical Min"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
+                        E_Notify(PSTR("\r\nPhysical Max"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
+                        E_Notify(PSTR("\r\nUnit Exp"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
+                        E_Notify(PSTR("\r\nUnit"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
+                        E_Notify(PSTR("\r\nReport Size"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
+                        E_Notify(PSTR("\r\nReport Count"), 0x80);
+                        break;
+                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
+                        E_Notify(PSTR("\r\nReport Id"), 0x80);
+                        break;
+                case (TYPE_LOCAL | TAG_LOCAL_USAGE):
+                        E_Notify(PSTR("\r\nUsage"), 0x80);
+                        break;
+                case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
+                        E_Notify(PSTR("\r\nUsage Min"), 0x80);
+                        break;
+                case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
+                        E_Notify(PSTR("\r\nUsage Max"), 0x80);
+                        break;
+                case (TYPE_MAIN | TAG_MAIN_COLLECTION):
+                        E_Notify(PSTR("\r\nCollection"), 0x80);
+                        break;
+                case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
+                        E_Notify(PSTR("\r\nEnd Collection"), 0x80);
+                        break;
+                case (TYPE_MAIN | TAG_MAIN_INPUT):
+                        E_Notify(PSTR("\r\nInput"), 0x80);
+                        break;
+                case (TYPE_MAIN | TAG_MAIN_OUTPUT):
+                        E_Notify(PSTR("\r\nOutput"), 0x80);
+                        break;
+                case (TYPE_MAIN | TAG_MAIN_FEATURE):
+                        E_Notify(PSTR("\r\nFeature"), 0x80);
+                        break;
+        } // switch (**pp & (TYPE_MASK | TAG_MASK))
+}
+
+uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint32_t *pcntdn) {
+        //uint8_t	ret = enErrorSuccess;
+        //reinterpret_cast<>(varBuffer);
+        switch(itemParseState) {
+                case 0:
+                        if(**pp == HID_LONG_ITEM_PREFIX)
+                                USBTRACE("\r\nLONG\r\n");
+                        else {
+                                uint8_t size = ((**pp) & DATA_SIZE_MASK);
+
+                                itemPrefix = (**pp);
+                                itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size);
+
+                                PrintItemTitle(itemPrefix);
+                        }
+                        (*pp)++;
+                        (*pcntdn)--;
+                        itemSize--;
+                        itemParseState = 1;
+
+                        if(!itemSize)
+                                break;
+
+                        if(!pcntdn)
+                                return enErrorIncomplete;
+                case 1:
+                        //USBTRACE2("\r\niSz:",itemSize);
+
+                        theBuffer.valueSize = itemSize;
+                        valParser.Initialize(&theBuffer);
+                        itemParseState = 2;
+                case 2:
+                        if(!valParser.Parse(pp, pcntdn))
+                                return enErrorIncomplete;
+                        itemParseState = 3;
+                case 3:
+                {
+                        uint8_t data = *((uint8_t*)varBuffer);
+
+                        switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {
+                                case (TYPE_LOCAL | TAG_LOCAL_USAGE):
+                                        if(pfUsage) {
+                                                if(theBuffer.valueSize > 1) {
+                                                        uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);
+                                                        pfUsage(*ui16);
+                                                } else
+                                                        pfUsage(data);
+                                        }
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
+                                        rptSize = data;
+                                        PrintByteValue(data);
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
+                                        rptCount = data;
+                                        PrintByteValue(data);
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
+                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
+                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
+                                        PrintValue(varBuffer, theBuffer.valueSize);
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
+                                case (TYPE_GLOBAL | TAG_GLOBAL_POP):
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
+                                        SetUsagePage(data);
+                                        PrintUsagePage(data);
+                                        PrintByteValue(data);
+                                        break;
+                                case (TYPE_MAIN | TAG_MAIN_COLLECTION):
+                                case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
+                                        switch(data) {
+                                                case 0x00:
+                                                        E_Notify(PSTR(" Physical"), 0x80);
+                                                        break;
+                                                case 0x01:
+                                                        E_Notify(PSTR(" Application"), 0x80);
+                                                        break;
+                                                case 0x02:
+                                                        E_Notify(PSTR(" Logical"), 0x80);
+                                                        break;
+                                                case 0x03:
+                                                        E_Notify(PSTR(" Report"), 0x80);
+                                                        break;
+                                                case 0x04:
+                                                        E_Notify(PSTR(" Named Array"), 0x80);
+                                                        break;
+                                                case 0x05:
+                                                        E_Notify(PSTR(" Usage Switch"), 0x80);
+                                                        break;
+                                                case 0x06:
+                                                        E_Notify(PSTR(" Usage Modifier"), 0x80);
+                                                        break;
+                                                default:
+                                                        E_Notify(PSTR(" Vendor Defined("), 0x80);
+                                                        PrintHex<uint8_t > (data, 0x80);
+                                                        E_Notify(PSTR(")"), 0x80);
+                                        }
+                                        break;
+                                case (TYPE_MAIN | TAG_MAIN_INPUT):
+                                case (TYPE_MAIN | TAG_MAIN_OUTPUT):
+                                case (TYPE_MAIN | TAG_MAIN_FEATURE):
+                                        totalSize += (uint16_t)rptSize * (uint16_t)rptCount;
+                                        rptSize = 0;
+                                        rptCount = 0;
+                                        E_Notify(PSTR("("), 0x80);
+                                        PrintBin<uint8_t > (data, 0x80);
+                                        E_Notify(PSTR(")"), 0x80);
+                                        break;
+                        } // switch (**pp & (TYPE_MASK | TAG_MASK))
+                }
+        } // switch (itemParseState)
+        itemParseState = 0;
+        return enErrorSuccess;
+}
+
+ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = {
+        &ReportDescParserBase::PrintGenericDesktopPageUsage,
+        &ReportDescParserBase::PrintSimulationControlsPageUsage,
+        &ReportDescParserBase::PrintVRControlsPageUsage,
+        &ReportDescParserBase::PrintSportsControlsPageUsage,
+        &ReportDescParserBase::PrintGameControlsPageUsage,
+        &ReportDescParserBase::PrintGenericDeviceControlsPageUsage,
+        NULL, // Keyboard/Keypad
+        &ReportDescParserBase::PrintLEDPageUsage,
+        &ReportDescParserBase::PrintButtonPageUsage,
+        &ReportDescParserBase::PrintOrdinalPageUsage,
+        &ReportDescParserBase::PrintTelephonyPageUsage,
+        &ReportDescParserBase::PrintConsumerPageUsage,
+        &ReportDescParserBase::PrintDigitizerPageUsage,
+        NULL, // Reserved
+        NULL, // PID
+        NULL // Unicode
+};
+
+void ReportDescParserBase::SetUsagePage(uint16_t page) {
+        pfUsage = NULL;
+
+        if(VALUE_BETWEEN(page, 0x00, 0x11))
+                pfUsage = (usagePageFunctions[page - 1]);
+
+                // Dead code...
+                //
+                //      pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]);
+                //else if (page > 0x7f && page < 0x84)
+                //      E_Notify(pstrUsagePageMonitor);
+                //else if (page > 0x83 && page < 0x8c)
+                //	E_Notify(pstrUsagePagePower);
+                //else if (page > 0x8b && page < 0x92)
+                //	E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c]));
+                //else if (page > 0xfeff && page <= 0xffff)
+                //	E_Notify(pstrUsagePageVendorDefined);
+                //
+        else
+                switch(page) {
+                        case 0x14:
+                                pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage;
+                                break;
+                        case 0x40:
+                                pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage;
+                                break;
+                }
+}
+
+void ReportDescParserBase::PrintUsagePage(uint16_t page) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80)
+        else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80)
+        else if(VALUE_BETWEEN(page, 0x7f, 0x84))
+                E_Notify(pstrUsagePageMonitor, 0x80);
+        else if(VALUE_BETWEEN(page, 0x83, 0x8c))
+                E_Notify(pstrUsagePagePower, 0x80);
+        else if(page > 0xfeff /* && page <= 0xffff */)
+                E_Notify(pstrUsagePageVendorDefined, 0x80);
+        else
+                switch(page) {
+                        case 0x14:
+                                E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80);
+                                break;
+                        case 0x40:
+                                E_Notify(pstrUsagePageMedicalInstruments, 0x80);
+                                break;
+                        default:
+                                E_Notify(pstrUsagePageUndefined, 0x80);
+                }
+}
+
+void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) {
+        E_Notify(pstrSpace, 0x80);
+        E_Notify(PSTR("Btn"), 0x80);
+        PrintHex<uint16_t > (usage, 0x80);
+        E_Notify(PSTR("\r\n"), 0x80);
+        //USB_HOST_SERIAL.print(usage, HEX);
+}
+
+void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) {
+        E_Notify(pstrSpace, 0x80);
+        E_Notify(PSTR("Inst"), 0x80);
+        // Sorry, HEX for now...
+        PrintHex<uint16_t > (usage, 0x80);
+        E_Notify(PSTR("\r\n"), 0x80);
+        //USB_HOST_SERIAL.print(usage, DEC);
+}
+
+void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80)
+        else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80)
+        else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80)
+        else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80)
+        else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80)
+        else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80)
+        else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80)
+        else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80)
+        else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80)
+        else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80)
+        else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80)
+        else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80)
+        else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80)
+        else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80)
+        else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80)
+        else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80)
+        else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80)
+        else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80)
+        else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80)
+        else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80)
+        else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80)
+        else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80)
+        else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80)
+        else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80)
+        else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80)
+        else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80)
+        else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80)
+        else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {
+        const char * const * w;
+        E_Notify(pstrSpace, 0x80);
+
+        if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80);
+        else if(usage == 0x70)
+                E_Notify(pstrUsageDepthGainCompensation, 0x80);
+        else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80)
+        else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80)
+        else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80)
+        else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80)
+        else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80)
+        else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint32_t *pcntdn) {
+        //uint8_t	ret = enErrorSuccess;
+
+        switch(itemParseState) {
+                case 0:
+                        if(**pp == HID_LONG_ITEM_PREFIX)
+                                USBTRACE("\r\nLONG\r\n");
+                        else {
+                                uint8_t size = ((**pp) & DATA_SIZE_MASK);
+                                itemPrefix = (**pp);
+                                itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size);
+                        }
+                        (*pp)++;
+                        (*pcntdn)--;
+                        itemSize--;
+                        itemParseState = 1;
+
+                        if(!itemSize)
+                                break;
+
+                        if(!pcntdn)
+                                return enErrorIncomplete;
+                case 1:
+                        theBuffer.valueSize = itemSize;
+                        valParser.Initialize(&theBuffer);
+                        itemParseState = 2;
+                case 2:
+                        if(!valParser.Parse(pp, pcntdn))
+                                return enErrorIncomplete;
+                        itemParseState = 3;
+                case 3:
+                {
+                        uint8_t data = *((uint8_t*)varBuffer);
+
+                        switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {
+                                case (TYPE_LOCAL | TAG_LOCAL_USAGE):
+                                        if(pfUsage) {
+                                                if(theBuffer.valueSize > 1) {
+                                                        uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);
+                                                        pfUsage(*ui16);
+                                                } else
+                                                        pfUsage(data);
+                                        }
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
+                                        rptSize = data;
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
+                                        rptCount = data;
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
+                                        rptId = data;
+                                        break;
+                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
+                                        useMin = data;
+                                        break;
+                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
+                                        useMax = data;
+                                        break;
+                                case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
+                                        SetUsagePage(data);
+                                        break;
+                                case (TYPE_MAIN | TAG_MAIN_OUTPUT):
+                                case (TYPE_MAIN | TAG_MAIN_FEATURE):
+                                        rptSize = 0;
+                                        rptCount = 0;
+                                        useMin = 0;
+                                        useMax = 0;
+                                        break;
+                                case (TYPE_MAIN | TAG_MAIN_INPUT):
+                                        OnInputItem(data);
+
+                                        totalSize += (uint16_t)rptSize * (uint16_t)rptCount;
+
+                                        rptSize = 0;
+                                        rptCount = 0;
+                                        useMin = 0;
+                                        useMax = 0;
+                                        break;
+                        } // switch (**pp & (TYPE_MASK | TAG_MASK))
+                }
+        } // switch (itemParseState)
+        itemParseState = 0;
+        return enErrorSuccess;
+}
+
+void ReportDescParser2::OnInputItem(uint8_t itm) {
+        uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8);
+        uint32_t tmp = (byte_offset << 3);
+        uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled
+        uint8_t *p = pBuf + byte_offset; // current byte pointer
+
+        if(bit_offset)
+                *p >>= bit_offset;
+
+        uint8_t usage = useMin;
+
+        bool print_usemin_usemax = ((useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false;
+
+        uint8_t bits_of_byte = 8;
+
+        // for each field in field array defined by rptCount
+        for(uint8_t field = 0; field < rptCount; field++, usage++) {
+
+                union {
+                        uint8_t bResult[4];
+                        uint16_t wResult[2];
+                        uint32_t dwResult;
+                } result;
+
+                result.dwResult = 0;
+                uint8_t mask = 0;
+
+                if(print_usemin_usemax)
+                        pfUsage(usage);
+
+                // bits_left		- number of bits in the field(array of fields, depending on Report Count) left to process
+                // bits_of_byte		- number of bits in current byte left to process
+                // bits_to_copy		- number of bits to copy to result buffer
+
+                // for each bit in a field
+                for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left;
+                        bits_left -= bits_to_copy) {
+                        bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left;
+
+                        result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it
+
+                        uint8_t val = *p;
+
+                        val >>= (8 - bits_of_byte); // Shift by the number of bits already processed
+
+                        mask = 0;
+
+                        for(uint8_t j = bits_to_copy; j; j--) {
+                                mask <<= 1;
+                                mask |= 1;
+                        }
+
+                        result.bResult[0] = (result.bResult[0] | (val & mask));
+
+                        bits_of_byte -= bits_to_copy;
+
+                        if(bits_of_byte < 1) {
+                                bits_of_byte = 8;
+                                p++;
+                        }
+                }
+                PrintByteValue(result.dwResult);
+        }
+        E_Notify(PSTR("\r\n"), 0x80);
+}
+
+void UniversalReportParser::Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf) {
+        ReportDescParser2 prs(len, buf);
+
+        uint8_t ret = hid->GetReportDescr(0, &prs);
+
+        if(ret)
+                ErrorMessage<uint8_t > (PSTR("GetReportDescr-2"), ret);
+}
diff --git a/libraries/USBHost/src/hidescriptorparser.h b/libraries/USBHost/src/hidescriptorparser.h
new file mode 100644
index 0000000000000000000000000000000000000000..920b4ee753411aa49df6b962d49ea12238879a6a
--- /dev/null
+++ b/libraries/USBHost/src/hidescriptorparser.h
@@ -0,0 +1,173 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#if !defined(__HIDDESCRIPTORPARSER_H__)
+#define __HIDDESCRIPTORPARSER_H__
+
+#include "hid.h"
+
+class ReportDescParserBase : public USBReadParser {
+public:
+        typedef void (*UsagePageFunc)(uint16_t usage);
+
+        static void PrintGenericDesktopPageUsage(uint16_t usage);
+        static void PrintSimulationControlsPageUsage(uint16_t usage);
+        static void PrintVRControlsPageUsage(uint16_t usage);
+        static void PrintSportsControlsPageUsage(uint16_t usage);
+        static void PrintGameControlsPageUsage(uint16_t usage);
+        static void PrintGenericDeviceControlsPageUsage(uint16_t usage);
+        static void PrintLEDPageUsage(uint16_t usage);
+        static void PrintButtonPageUsage(uint16_t usage);
+        static void PrintOrdinalPageUsage(uint16_t usage);
+        static void PrintTelephonyPageUsage(uint16_t usage);
+        static void PrintConsumerPageUsage(uint16_t usage);
+        static void PrintDigitizerPageUsage(uint16_t usage);
+        static void PrintAlphanumDisplayPageUsage(uint16_t usage);
+        static void PrintMedicalInstrumentPageUsage(uint16_t usage);
+
+        static void PrintValue(uint8_t *p, uint8_t len);
+        static void PrintByteValue(uint8_t data);
+
+        static void PrintItemTitle(uint8_t prefix);
+
+        static const char * const usagePageTitles0[];
+        static const char * const usagePageTitles1[];
+        static const char * const genDesktopTitles0[];
+        static const char * const genDesktopTitles1[];
+        static const char * const genDesktopTitles2[];
+        static const char * const genDesktopTitles3[];
+        static const char * const genDesktopTitles4[];
+        static const char * const simuTitles0[];
+        static const char * const simuTitles1[];
+        static const char * const simuTitles2[];
+        static const char * const vrTitles0[];
+        static const char * const vrTitles1[];
+        static const char * const sportsCtrlTitles0[];
+        static const char * const sportsCtrlTitles1[];
+        static const char * const sportsCtrlTitles2[];
+        static const char * const gameTitles0[];
+        static const char * const gameTitles1[];
+        static const char * const genDevCtrlTitles[];
+        static const char * const ledTitles[];
+        static const char * const telTitles0[];
+        static const char * const telTitles1[];
+        static const char * const telTitles2[];
+        static const char * const telTitles3[];
+        static const char * const telTitles4[];
+        static const char * const telTitles5[];
+        static const char * const consTitles0[];
+        static const char * const consTitles1[];
+        static const char * const consTitles2[];
+        static const char * const consTitles3[];
+        static const char * const consTitles4[];
+        static const char * const consTitles5[];
+        static const char * const consTitles6[];
+        static const char * const consTitles7[];
+        static const char * const consTitles8[];
+        static const char * const consTitles9[];
+        static const char * const consTitlesA[];
+        static const char * const consTitlesB[];
+        static const char * const consTitlesC[];
+        static const char * const consTitlesD[];
+        static const char * const consTitlesE[];
+        static const char * const digitTitles0[];
+        static const char * const digitTitles1[];
+        static const char * const digitTitles2[];
+        static const char * const aplphanumTitles0[];
+        static const char * const aplphanumTitles1[];
+        static const char * const aplphanumTitles2[];
+        static const char * const medInstrTitles0[];
+        static const char * const medInstrTitles1[];
+        static const char * const medInstrTitles2[];
+        static const char * const medInstrTitles3[];
+        static const char * const medInstrTitles4[];
+
+protected:
+        static UsagePageFunc usagePageFunctions[];
+
+        MultiValueBuffer theBuffer;
+        MultiByteValueParser valParser;
+        ByteSkipper theSkipper;
+        uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)];
+
+        uint8_t itemParseState; // Item parser state variable
+        uint8_t itemSize; // Item size
+        uint8_t itemPrefix; // Item prefix (first byte)
+        uint8_t rptSize; // Report Size
+        uint8_t rptCount; // Report Count
+
+        uint16_t totalSize; // Report size in bits
+
+        virtual uint8_t ParseItem(uint8_t **pp, uint32_t *pcntdn);
+
+        UsagePageFunc pfUsage;
+
+        static void PrintUsagePage(uint16_t page);
+        void SetUsagePage(uint16_t page);
+
+public:
+
+        ReportDescParserBase() :
+        itemParseState(0),
+        itemSize(0),
+        itemPrefix(0),
+        rptSize(0),
+        rptCount(0),
+        pfUsage(NULL) {
+                theBuffer.pValue = varBuffer;
+                valParser.Initialize(&theBuffer);
+                theSkipper.Initialize(&theBuffer);
+        };
+
+        virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset);
+
+        enum {
+                enErrorSuccess = 0
+                , enErrorIncomplete // value or record is partialy read in buffer
+                , enErrorBufferTooSmall
+        };
+};
+
+class ReportDescParser : public ReportDescParserBase {
+};
+
+class ReportDescParser2 : public ReportDescParserBase {
+        uint8_t rptId; // Report ID
+        uint8_t useMin; // Usage Minimum
+        uint8_t useMax; // Usage Maximum
+        uint8_t fieldCount; // Number of field being currently processed
+
+        void OnInputItem(uint8_t itm); // Method which is called every time Input item is found
+
+        uint8_t *pBuf; // Report buffer pointer
+        uint8_t bLen; // Report length
+
+protected:
+        virtual uint8_t ParseItem(uint8_t **pp, uint32_t *pcntdn);
+
+public:
+
+        ReportDescParser2(uint16_t len, uint8_t *pbuf) :
+        ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) {
+        };
+};
+
+class UniversalReportParser : public HIDReportParser {
+public:
+        virtual void Parse(HID *hid, uint32_t is_rpt_id, uint32_t len, uint8_t *buf);
+};
+
+#endif // __HIDDESCRIPTORPARSER_H__
diff --git a/libraries/USBHost/src/hiduniversal.cpp b/libraries/USBHost/src/hiduniversal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69630893e045f8552daae7f3e8a543f4acca06d5
--- /dev/null
+++ b/libraries/USBHost/src/hiduniversal.cpp
@@ -0,0 +1,421 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#include "Arduino.h"
+#include "hiduniversal.h"
+
+HIDUniversal::HIDUniversal(USBHost *p) :
+HID(p),
+qNextPollTime(0),
+pollInterval(0),
+bPollEnable(false),
+bHasReportId(false) {
+        Initialize();
+
+        if(pUsb)
+                pUsb->RegisterDeviceClass(this);
+}
+
+uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
+        for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
+                if(descrInfo[i].bDescrType == type) {
+                        if(n == num)
+                                return descrInfo[i].wDescriptorLength;
+                        n++;
+                }
+        }
+        return 0;
+}
+
+void HIDUniversal::Initialize() {
+        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
+                rptParsers[i].rptId = 0;
+                rptParsers[i].rptParser = NULL;
+        }
+        for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
+                descrInfo[i].bDescrType = 0;
+                descrInfo[i].wDescriptorLength = 0;
+        }
+        for(uint8_t i = 0; i < maxHidInterfaces; i++) {
+                hidInterfaces[i].bmInterface = 0;
+                hidInterfaces[i].bmProtocol = 0;
+
+                for(uint8_t j = 0; j < maxEpPerInterface; j++)
+                        hidInterfaces[i].epIndex[j] = 0;
+        }
+        for(uint8_t i = 0; i < totalEndpoints; i++) {
+                epInfo[i].epAddr = 0;
+                epInfo[i].maxPktSize = (i) ? 0 : 8;
+                epInfo[i].epAttribs = 0;
+                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+        }
+        bNumEP = 1;
+        bNumIface = 0;
+        bConfNum = 0;
+        pollInterval = 0;
+
+        ZeroMemory(constBuffLen, prevBuf);
+}
+
+uint32_t HIDUniversal::SetReportParser(uint32_t id, HIDReportParser *prs) {
+        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
+                if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
+                        rptParsers[i].rptId = id;
+                        rptParsers[i].rptParser = prs;
+                        return true;
+                }
+        }
+        return false;
+}
+
+HIDReportParser* HIDUniversal::GetReportParser(uint32_t id) {
+        if(!bHasReportId)
+                return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
+
+        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
+                if(rptParsers[i].rptId == id)
+                        return rptParsers[i].rptParser;
+        }
+        return NULL;
+}
+
+uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+        uint8_t buf[constBufSize];
+        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+        uint8_t rcode;
+        UsbDeviceDefinition *p = NULL;
+        EpInfo *oldep_ptr = NULL;
+        uint8_t len = 0;
+
+        uint8_t num_of_conf; // number of configurations
+        //uint8_t		num_of_intf;	// number of interfaces
+
+        AddressPool &addrPool = pUsb->GetAddressPool();
+
+        USBTRACE("HU Init\r\n");
+
+        if(bAddress)
+                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+        // Get pointer to pseudo device with address 0 assigned
+        p = addrPool.GetUsbDevicePtr(0);
+
+        if(!p)
+                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+        if(!p->epinfo) {
+                USBTRACE("epinfo\r\n");
+                return USB_ERROR_EPINFO_IS_NULL;
+        }
+
+        // Save old pointer to EP_RECORD of address 0
+        oldep_ptr = p->epinfo;
+
+        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+        p->epinfo = epInfo;
+
+        p->lowspeed = lowspeed;
+
+        // Get device descriptor
+        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
+
+        if(!rcode)
+                len = (buf[0] > constBufSize) ? constBufSize : buf[0];
+
+        if(rcode) {
+                // Restore p->epinfo
+                p->epinfo = oldep_ptr;
+
+                goto FailGetDevDescr;
+        }
+
+        // Restore p->epinfo
+        p->epinfo = oldep_ptr;
+
+        // Allocate new address according to device class
+        bAddress = addrPool.AllocAddress(parent, false, port);
+
+        if(!bAddress)
+                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+        // Extract Max Packet Size from the device descriptor
+        epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+        // Assign new address to the device
+        rcode = pUsb->setAddr(0, 0, bAddress);
+
+        if(rcode) {
+                p->lowspeed = false;
+                addrPool.FreeAddress(bAddress);
+                bAddress = 0;
+                USBTRACE2("setAddr:", rcode);
+                return rcode;
+        }
+
+        //delay(2); //per USB 2.0 sect.9.2.6.3
+
+        USBTRACE2("Addr:", bAddress);
+
+        p->lowspeed = false;
+
+        p = addrPool.GetUsbDevicePtr(bAddress);
+
+        if(!p)
+                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+        p->lowspeed = lowspeed;
+
+        if(len)
+                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
+
+        if(rcode)
+                goto FailGetDevDescr;
+
+        VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device
+        PID = udd->idProduct;
+
+        num_of_conf = udd->bNumConfigurations;
+
+        // Assign epInfo to epinfo pointer
+        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+        if(rcode)
+                goto FailSetDevTblEntry;
+
+        USBTRACE2("NC:", num_of_conf);
+
+        for(uint8_t i = 0; i < num_of_conf; i++) {
+                //HexDumper<USBReadParser, uint16_t, uint16_t>		HexDump;
+                ConfigDescParser<USB_CLASS_HID, 0, 0,
+                        CP_MASK_COMPARE_CLASS> confDescrParser(this);
+
+                //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
+                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+
+                if(rcode)
+                        goto FailGetConfDescr;
+
+                if(bNumEP > 1)
+                        break;
+        } // for
+
+        if(bNumEP < 2)
+                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+        // Assign epInfo to epinfo pointer
+        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+        USBTRACE2("Cnf:", bConfNum);
+
+        // Set Configuration Value
+        rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+        if(rcode)
+                goto FailSetConfDescr;
+
+        for(uint8_t i = 0; i < bNumIface; i++) {
+                if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
+                        continue;
+
+                rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
+
+                if(rcode)/* && rcode != hrSTALL) */
+                        goto FailSetIdle;
+        }
+
+        USBTRACE("HU configured\r\n");
+
+        OnInitSuccessful();
+
+        bPollEnable = true;
+        return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+        NotifyFailGetDevDescr();
+        goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+        NotifyFailSetDevTblEntry();
+        goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+        NotifyFailGetConfDescr();
+        goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+        NotifyFailSetConfDescr();
+        goto Fail;
+#endif
+
+
+FailSetIdle:
+#ifdef DEBUG_USB_HOST
+        USBTRACE("SetIdle:");
+#endif
+
+#ifdef DEBUG_USB_HOST
+Fail:
+        NotifyFail(rcode);
+#endif
+        Release();
+        return rcode;
+}
+
+HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
+        for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
+                if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
+                        && hidInterfaces[i].bmProtocol == proto)
+                        return hidInterfaces + i;
+        return NULL;
+}
+
+void HIDUniversal::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+        // If the first configuration satisfies, the others are not concidered.
+        if(bNumEP > 1 && conf != bConfNum)
+                return;
+
+        //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
+        //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
+        //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
+
+        bConfNum = conf;
+
+        uint8_t index = 0;
+        HIDInterface *piface = FindInterface(iface, alt, proto);
+
+        // Fill in interface structure in case of new interface
+        if(!piface) {
+                piface = hidInterfaces + bNumIface;
+                piface->bmInterface = iface;
+                piface->bmAltSet = alt;
+                piface->bmProtocol = proto;
+                bNumIface++;
+        }
+
+        if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
+                index = epInterruptInIndex;
+        else
+                index = epInterruptOutIndex;
+
+        if(index) {
+                // Fill in the endpoint info structure
+                epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
+                epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+                epInfo[bNumEP].epAttribs = 0;
+                epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
+
+                // Fill in the endpoint index list
+                piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);
+
+                if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
+                        pollInterval = pep->bInterval;
+
+                bNumEP++;
+        }
+        //PrintEndpointDescriptor(pep);
+}
+
+uint32_t HIDUniversal::Release() {
+        pUsb->GetAddressPool().FreeAddress(bAddress);
+
+        bNumEP = 1;
+        bAddress = 0;
+        qNextPollTime = 0;
+        bPollEnable = false;
+        return 0;
+}
+
+bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
+        for(uint8_t i = 0; i < len; i++)
+                if(buf1[i] != buf2[i])
+                        return false;
+        return true;
+}
+
+void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
+        for(uint8_t i = 0; i < len; i++)
+                buf[i] = 0;
+}
+
+void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
+        for(uint8_t i = 0; i < len; i++)
+                dest[i] = src[i];
+}
+
+uint32_t HIDUniversal::Poll() {
+        uint32_t rcode = 0;
+
+        if(!bPollEnable)
+                return 0;
+
+        if((long)(millis() - qNextPollTime) >= 0L) {
+                qNextPollTime = millis() + pollInterval;
+
+                uint8_t buf[constBuffLen];
+
+                for(uint8_t i = 0; i < bNumIface; i++) {
+                        uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
+                        uint16_t read = (uint8_t)epInfo[index].maxPktSize;
+
+                        ZeroMemory(constBuffLen, buf);
+
+                        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, (uint8_t*)&read, buf);
+
+                        if(rcode) {
+                                if(rcode != USB_ERRORFLOW/*hrNAK*/)
+                                        USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81);
+                                return rcode;
+                        }
+
+                        if(read > constBuffLen)
+                                read = constBuffLen;
+
+                        bool identical = BuffersIdentical(read, buf, prevBuf);
+
+                        SaveBuffer(read, buf, prevBuf);
+
+                        if(identical)
+                                return 0;
+#if 0
+                        Notify(PSTR("\r\nBuf: "), 0x80);
+
+                        for(uint8_t i = 0; i < read; i++) {
+                                D_PrintHex<uint8_t > (buf[i], 0x80);
+                                Notify(PSTR(" "), 0x80);
+                        }
+
+                        Notify(PSTR("\r\n"), 0x80);
+#endif
+                        ParseHIDData(this, bHasReportId, (uint8_t)read, buf);
+
+                        HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
+
+                        if(prs)
+                                prs->Parse(this, bHasReportId, (uint8_t)read, buf);
+                }
+        }
+        return rcode;
+}
diff --git a/libraries/USBHost/src/hiduniversal.h b/libraries/USBHost/src/hiduniversal.h
new file mode 100644
index 0000000000000000000000000000000000000000..b0e7958a67b4029660cc7ce1a440316fd3dd9a09
--- /dev/null
+++ b/libraries/USBHost/src/hiduniversal.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#if !defined(__HIDUNIVERSAL_H__)
+#define __HIDUNIVERSAL_H__
+
+#include "hid.h"
+//#include "hidescriptorparser.h"
+
+class HIDUniversal : public HID {
+
+        struct ReportParser {
+                uint8_t rptId;
+                HIDReportParser *rptParser;
+        } rptParsers[MAX_REPORT_PARSERS];
+
+        // HID class specific descriptor type and length info obtained from HID descriptor
+        HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS];
+
+        // Returns HID class specific descriptor length by its type and order number
+        uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num);
+
+        struct HIDInterface {
+                struct {
+                        uint8_t bmInterface : 3;
+                        uint8_t bmAltSet : 3;
+                        uint8_t bmProtocol : 2;
+                };
+                uint8_t epIndex[maxEpPerInterface];
+        };
+
+        uint8_t bConfNum; // configuration number
+        uint8_t bNumIface; // number of interfaces in the configuration
+        uint8_t bNumEP; // total number of EP in the configuration
+        uint32_t qNextPollTime; // next poll time
+        uint8_t pollInterval;
+        bool bPollEnable; // poll enable flag
+
+        static const uint16_t constBuffLen = 64; // event buffer length
+        uint8_t prevBuf[constBuffLen]; // previous event buffer
+
+        void Initialize();
+        HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto);
+
+        void ZeroMemory(uint8_t len, uint8_t *buf);
+        bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2);
+        void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest);
+
+protected:
+        EpInfo epInfo[totalEndpoints];
+        HIDInterface hidInterfaces[maxHidInterfaces];
+
+        bool bHasReportId;
+
+        uint16_t PID, VID; // PID and VID of connected device
+
+        // HID implementation
+        virtual HIDReportParser* GetReportParser(uint32_t id);
+
+        virtual uint32_t OnInitSuccessful() {
+                return 0;
+        };
+
+        virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+                return;
+        };
+
+public:
+        HIDUniversal(USBHost *p);
+
+        // HID implementation
+        virtual uint32_t SetReportParser(uint32_t id, HIDReportParser *prs);
+
+        // USBDeviceConfig implementation
+        virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+        virtual uint32_t Release();
+        virtual uint32_t Poll();
+
+        virtual uint32_t GetAddress() {
+                return bAddress;
+        };
+
+        virtual uint32_t isReady() {
+                return bPollEnable;
+        };
+
+        // UsbConfigXtracter implementation
+        virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+};
+
+#endif // __HIDUNIVERSAL_H__
diff --git a/libraries/USBHost/src/hidusagestr.h b/libraries/USBHost/src/hidusagestr.h
new file mode 100644
index 0000000000000000000000000000000000000000..71e5378739919fc4c6cc95bc237344e4d6c466da
--- /dev/null
+++ b/libraries/USBHost/src/hidusagestr.h
@@ -0,0 +1,977 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+#if !defined( __HIDUSAGESTR_H__)
+#define  __HIDUSAGESTR_H__
+
+#include "Usb.h"
+
+const char pstrSpace [] PROGMEM = " ";
+const char pstrCRLF [] PROGMEM = "\r\n";
+const char pstrSingleTab [] PROGMEM = "\t";
+const char pstrDoubleTab [] PROGMEM = "\t\t";
+const char pstrTripleTab [] PROGMEM = "\t\t\t";
+
+// Usage Page String Titles
+const char pstrUsagePageUndefined [] PROGMEM = "Undef";
+const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls";
+const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls";
+const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls";
+const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls";
+const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls";
+const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls";
+const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad";
+const char pstrUsagePageLEDs [] PROGMEM = "LEDs";
+const char pstrUsagePageButton [] PROGMEM = "Button";
+const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal";
+const char pstrUsagePageTelephone [] PROGMEM = "Tel";
+const char pstrUsagePageConsumer [] PROGMEM = "Consumer";
+const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer";
+const char pstrUsagePagePID [] PROGMEM = "PID";
+const char pstrUsagePageUnicode [] PROGMEM = "Unicode";
+const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp";
+const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr";
+const char pstrUsagePageMonitor [] PROGMEM = "Monitor";
+const char pstrUsagePagePower [] PROGMEM = "Power";
+const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan";
+const char pstrUsagePageScale [] PROGMEM = "Scale";
+const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev";
+const char pstrUsagePagePointOfSale [] PROGMEM = "POS";
+const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl";
+const char pstrUsagePageArcade [] PROGMEM = "Arcade";
+const char pstrUsagePageReserved [] PROGMEM = "Reserved";
+const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def";
+
+// Generic Desktop Controls Page
+const char pstrUsagePointer [] PROGMEM = "Pointer";
+const char pstrUsageMouse [] PROGMEM = "Mouse";
+const char pstrUsageJoystick [] PROGMEM = "Joystick";
+const char pstrUsageGamePad [] PROGMEM = "Game Pad";
+const char pstrUsageKeyboard [] PROGMEM = "Kbrd";
+const char pstrUsageKeypad [] PROGMEM = "Keypad";
+const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl";
+const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls";
+const char pstrUsageX [] PROGMEM = "X";
+const char pstrUsageY [] PROGMEM = "Y";
+const char pstrUsageZ [] PROGMEM = "Z";
+const char pstrUsageRx [] PROGMEM = "Rx";
+const char pstrUsageRy [] PROGMEM = "Ry";
+const char pstrUsageRz [] PROGMEM = "Rz";
+const char pstrUsageSlider [] PROGMEM = "Slider";
+const char pstrUsageDial [] PROGMEM = "Dial";
+const char pstrUsageWheel [] PROGMEM = "Wheel";
+const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch";
+const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf";
+const char pstrUsageByteCount [] PROGMEM = "Byte Count";
+const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup";
+const char pstrUsageStart [] PROGMEM = "Start";
+const char pstrUsageSelect [] PROGMEM = "Sel";
+const char pstrUsageVx [] PROGMEM = "Vx";
+const char pstrUsageVy [] PROGMEM = "Vy";
+const char pstrUsageVz [] PROGMEM = "Vz";
+const char pstrUsageVbrx [] PROGMEM = "Vbrx";
+const char pstrUsageVbry [] PROGMEM = "Vbry";
+const char pstrUsageVbrz [] PROGMEM = "Vbrz";
+const char pstrUsageVno [] PROGMEM = "Vno";
+const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif";
+const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult";
+const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl";
+const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down";
+const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep";
+const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup";
+const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu";
+const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu";
+const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu";
+const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help";
+const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit";
+const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select";
+const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right";
+const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left";
+const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up";
+const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down";
+const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart";
+const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart";
+const char pstrUsageDPadUp [] PROGMEM = "D-pad Up";
+const char pstrUsageDPadDown [] PROGMEM = "D-pad Down";
+const char pstrUsageDPadRight [] PROGMEM = "D-pad Right";
+const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left";
+const char pstrUsageSystemDock [] PROGMEM = "Sys Dock";
+const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock";
+const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup";
+const char pstrUsageSystemBreak [] PROGMEM = "Sys Break";
+const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk";
+const char pstrUsageApplicationBreak [] PROGMEM = "App Break";
+const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk";
+const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute";
+const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber";
+const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv";
+const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int";
+const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext";
+const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both";
+const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual";
+const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext";
+const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec";
+const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale";
+
+// Simulation Controls Page
+const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev";
+const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev";
+const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev";
+const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev";
+const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev";
+const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev";
+const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev";
+const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev";
+const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev";
+const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev";
+const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev";
+const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev";
+const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick";
+const char pstrUsageFlightStick [] PROGMEM = "Flight Stick";
+const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl";
+const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim";
+const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke";
+const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl";
+const char pstrUsageAileron [] PROGMEM = "Aileron";
+const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim";
+const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl";
+const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable";
+const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release";
+const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl";
+const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake";
+const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures";
+const char pstrUsageElevator [] PROGMEM = "Elevator";
+const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim";
+const char pstrUsageRudder [] PROGMEM = "Rudder";
+const char pstrUsageThrottle [] PROGMEM = "Throttle";
+const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm";
+const char pstrUsageFlareRelease [] PROGMEM = "Flare Release";
+const char pstrUsageLandingGear [] PROGMEM = "Landing Gear";
+const char pstrUsageToeBrake [] PROGMEM = "Toe Brake";
+const char pstrUsageTrigger [] PROGMEM = "Trigger";
+const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm";
+const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel";
+const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps";
+const char pstrUsageAccelerator [] PROGMEM = "Accel";
+const char pstrUsageBrake [] PROGMEM = "Brake";
+const char pstrUsageClutch [] PROGMEM = "Clutch";
+const char pstrUsageShifter [] PROGMEM = "Shifter";
+const char pstrUsageSteering [] PROGMEM = "Steering";
+const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir";
+const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele";
+const char pstrUsageDivePlane [] PROGMEM = "Dive Plane";
+const char pstrUsageBallast [] PROGMEM = "Ballast";
+const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank";
+const char pstrUsageHandleBars [] PROGMEM = "Handle Bars";
+const char pstrUsageFrontBrake [] PROGMEM = "Front Brake";
+const char pstrUsageRearBrake [] PROGMEM = "Rear Brake";
+
+// VR Controls Page
+const char pstrUsageBelt [] PROGMEM = "Belt";
+const char pstrUsageBodySuit [] PROGMEM = "Body Suit";
+const char pstrUsageFlexor [] PROGMEM = "Flexor";
+const char pstrUsageGlove [] PROGMEM = "Glove";
+const char pstrUsageHeadTracker [] PROGMEM = "Head Track";
+const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp";
+const char pstrUsageHandTracker [] PROGMEM = "Hand Track";
+const char pstrUsageOculometer [] PROGMEM = "Oculometer";
+const char pstrUsageVest [] PROGMEM = "Vest";
+const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev";
+const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl";
+const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl";
+
+// Sport Controls Page
+const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat";
+const char pstrUsageGolfClub [] PROGMEM = "Golf Club";
+const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach";
+const char pstrUsageTreadmill [] PROGMEM = "Treadmill";
+const char pstrUsageOar [] PROGMEM = "Oar";
+const char pstrUsageSlope [] PROGMEM = "Slope";
+const char pstrUsageRate [] PROGMEM = "Rate";
+const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed";
+const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang";
+const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe";
+const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru";
+const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo";
+const char pstrUsageStickType [] PROGMEM = "Stick Type";
+const char pstrUsageStickHeight [] PROGMEM = "Stick Hght";
+const char pstrUsagePutter [] PROGMEM = "Putter";
+const char pstrUsage1Iron [] PROGMEM = "1 Iron";
+const char pstrUsage2Iron [] PROGMEM = "2 Iron";
+const char pstrUsage3Iron [] PROGMEM = "3 Iron";
+const char pstrUsage4Iron [] PROGMEM = "4 Iron";
+const char pstrUsage5Iron [] PROGMEM = "5 Iron";
+const char pstrUsage6Iron [] PROGMEM = "6 Iron";
+const char pstrUsage7Iron [] PROGMEM = "7 Iron";
+const char pstrUsage8Iron [] PROGMEM = "8 Iron";
+const char pstrUsage9Iron [] PROGMEM = "9 Iron";
+const char pstrUsage10Iron [] PROGMEM = "10 Iron";
+const char pstrUsage11Iron [] PROGMEM = "11 Iron";
+const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge";
+const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge";
+const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge";
+const char pstrUsage1Wood [] PROGMEM = "1 Wood";
+const char pstrUsage3Wood [] PROGMEM = "3 Wood";
+const char pstrUsage5Wood [] PROGMEM = "5 Wood";
+const char pstrUsage7Wood [] PROGMEM = "7 Wood";
+const char pstrUsage9Wood [] PROGMEM = "9 Wood";
+
+// Game Controls Page
+const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl";
+const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev";
+const char pstrUsageGunDevice [] PROGMEM = "Gun Dev";
+const char pstrUsagePointOfView [] PROGMEM = "POV";
+const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left";
+const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back";
+const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left";
+const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left";
+const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back";
+const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down";
+const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left";
+const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back";
+const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV";
+const char pstrUsageFlipper [] PROGMEM = "Flipper";
+const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper";
+const char pstrUsageBump [] PROGMEM = "Bump";
+const char pstrUsageNewGame [] PROGMEM = "New Game";
+const char pstrUsageShootBall [] PROGMEM = "Shoot Ball";
+const char pstrUsagePlayer [] PROGMEM = "Player";
+const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt";
+const char pstrUsageGunClip [] PROGMEM = "Gun Clip";
+const char pstrUsageGunSelector [] PROGMEM = "Gun Sel";
+const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot";
+const char pstrUsageGunBurst [] PROGMEM = "Gun Burst";
+const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto";
+const char pstrUsageGunSafety [] PROGMEM = "Gun Safety";
+const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump";
+const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig";
+
+// Generic Device Controls Page
+const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength";
+const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch";
+const char pstrUsageWirelessID [] PROGMEM = "Wireless ID";
+const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl";
+const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd";
+const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased";
+const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared";
+
+// LED Page
+const char pstrUsageNumLock [] PROGMEM = "Num Lock";
+const char pstrUsageCapsLock [] PROGMEM = "Caps Lock";
+const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock";
+const char pstrUsageCompose [] PROGMEM = "Compose";
+const char pstrUsageKana [] PROGMEM = "Kana";
+const char pstrUsagePower [] PROGMEM = "Pwr";
+const char pstrUsageShift [] PROGMEM = "Shift";
+const char pstrUsageDoNotDisturb [] PROGMEM = "DND";
+const char pstrUsageMute [] PROGMEM = "Mute";
+const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl";
+const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr";
+const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr";
+const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl";
+const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On";
+const char pstrUsageSurroundOn [] PROGMEM = "Surround On";
+const char pstrUsageRepeat [] PROGMEM = "Repeat";
+const char pstrUsageStereo [] PROGMEM = "Stereo";
+const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect";
+const char pstrUsageSpinning [] PROGMEM = "Spinning";
+const char pstrUsageCAV [] PROGMEM = "CAV";
+const char pstrUsageCLV [] PROGMEM = "CLV";
+const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect";
+const char pstrUsageOffHook [] PROGMEM = "Off Hook";
+const char pstrUsageRing [] PROGMEM = "Ring";
+const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait";
+const char pstrUsageDataMode [] PROGMEM = "Data Mode";
+const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op";
+const char pstrUsageBatteryOK [] PROGMEM = "Bat OK";
+const char pstrUsageBatteryLow [] PROGMEM = "Bat Low";
+const char pstrUsageSpeaker [] PROGMEM = "Speaker";
+const char pstrUsageHeadSet [] PROGMEM = "Head Set";
+const char pstrUsageHold [] PROGMEM = "Hold";
+const char pstrUsageMicrophone [] PROGMEM = "Mic";
+const char pstrUsageCoverage [] PROGMEM = "Coverage";
+const char pstrUsageNightMode [] PROGMEM = "Night Mode";
+const char pstrUsageSendCalls [] PROGMEM = "Send Calls";
+const char pstrUsageCallPickup [] PROGMEM = "Call Pickup";
+const char pstrUsageConference [] PROGMEM = "Conf";
+const char pstrUsageStandBy [] PROGMEM = "Stand-by";
+const char pstrUsageCameraOn [] PROGMEM = "Cam On";
+const char pstrUsageCameraOff [] PROGMEM = "Cam Off";
+const char pstrUsageOnLine [] PROGMEM = "On-Line";
+const char pstrUsageOffLine [] PROGMEM = "Off-Line";
+const char pstrUsageBusy [] PROGMEM = "Busy";
+const char pstrUsageReady [] PROGMEM = "Ready";
+const char pstrUsagePaperOut [] PROGMEM = "Paper Out";
+const char pstrUsagePaperJam [] PROGMEM = "Paper Jam";
+const char pstrUsageRemote [] PROGMEM = "Remote";
+const char pstrUsageForward [] PROGMEM = "Fwd";
+const char pstrUsageReverse [] PROGMEM = "Rev";
+const char pstrUsageStop [] PROGMEM = "Stop";
+const char pstrUsageRewind [] PROGMEM = "Rewind";
+const char pstrUsageFastForward [] PROGMEM = "Fast Fwd";
+const char pstrUsagePlay [] PROGMEM = "Play";
+const char pstrUsagePause [] PROGMEM = "Pause";
+const char pstrUsageRecord [] PROGMEM = "Rec";
+const char pstrUsageError [] PROGMEM = "Error";
+const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind";
+const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind";
+const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind";
+const char pstrUsageIndicatorOn [] PROGMEM = "Ind On";
+const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash";
+const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk";
+const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk";
+const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off";
+const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time";
+const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time";
+const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time";
+const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time";
+const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time";
+const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color";
+const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red";
+const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green";
+const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber";
+const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind";
+const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend";
+const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn";
+
+// Telephony Usage Page
+const char pstrUsagePhone [] PROGMEM = "Phone";
+const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach";
+const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls";
+const char pstrUsageHandset [] PROGMEM = "Handset";
+const char pstrUsageHeadset [] PROGMEM = "Headset";
+const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad";
+const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button";
+const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw";
+const char pstrUsageFlash [] PROGMEM = "Flash";
+const char pstrUsageFeature [] PROGMEM = "Feature";
+//const char pstrUsageHold						[] PROGMEM = "Hold";
+const char pstrUsageRedial [] PROGMEM = "Redial";
+const char pstrUsageTransfer [] PROGMEM = "Transfer";
+const char pstrUsageDrop [] PROGMEM = "Drop";
+const char pstrUsagePark [] PROGMEM = "Park";
+const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls";
+const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func";
+const char pstrUsageLine [] PROGMEM = "Line";
+const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone";
+//const char pstrUsageConference					[] PROGMEM = "Conference";
+const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl";
+const char pstrUsageRingSelect [] PROGMEM = "Ring Sel";
+const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute";
+const char pstrUsageCallerID [] PROGMEM = "Caller ID";
+const char pstrUsageSend [] PROGMEM = "Send";
+const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial";
+const char pstrUsageStoreNumber [] PROGMEM = "Store Num";
+const char pstrUsageRecallNumber [] PROGMEM = "Recall Num";
+const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir";
+const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail";
+const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls";
+//const char pstrUsageDoNotDisturb				[] PROGMEM = "Do Not Disturb";
+const char pstrUsageMessage [] PROGMEM = "Msg";
+const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off";
+const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone";
+const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone";
+const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone";
+const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone";
+const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone";
+const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback";
+const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback";
+const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone";
+const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone";
+const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone";
+const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1";
+const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2";
+const char pstrUsageTonesOff [] PROGMEM = "Tones Off";
+const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback";
+const char pstrUsageRinger [] PROGMEM = "Ringer";
+const char pstrUsagePhoneKey0 [] PROGMEM = "0";
+const char pstrUsagePhoneKey1 [] PROGMEM = "1";
+const char pstrUsagePhoneKey2 [] PROGMEM = "2";
+const char pstrUsagePhoneKey3 [] PROGMEM = "3";
+const char pstrUsagePhoneKey4 [] PROGMEM = "4";
+const char pstrUsagePhoneKey5 [] PROGMEM = "5";
+const char pstrUsagePhoneKey6 [] PROGMEM = "6";
+const char pstrUsagePhoneKey7 [] PROGMEM = "7";
+const char pstrUsagePhoneKey8 [] PROGMEM = "8";
+const char pstrUsagePhoneKey9 [] PROGMEM = "9";
+const char pstrUsagePhoneKeyStar [] PROGMEM = "*";
+const char pstrUsagePhoneKeyPound [] PROGMEM = "#";
+const char pstrUsagePhoneKeyA [] PROGMEM = "A";
+const char pstrUsagePhoneKeyB [] PROGMEM = "B";
+const char pstrUsagePhoneKeyC [] PROGMEM = "C";
+const char pstrUsagePhoneKeyD [] PROGMEM = "D";
+
+// Consumer Usage Page
+const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl";
+const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad";
+//const char pstrUsageProgrammableButton			[] PROGMEM = "Prog Btn";
+//const char pstrUsageMicrophone					[] PROGMEM = "Mic";
+const char pstrUsageHeadphone [] PROGMEM = "Headphone";
+const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq";
+const char pstrUsagePlus10 [] PROGMEM = "+10";
+const char pstrUsagePlus100 [] PROGMEM = "+100";
+const char pstrUsageAMPM [] PROGMEM = "AM/PM";
+//const char pstrUsagePower						[] PROGMEM = "Pwr";
+const char pstrUsageReset [] PROGMEM = "Reset";
+const char pstrUsageSleep [] PROGMEM = "Sleep";
+const char pstrUsageSleepAfter [] PROGMEM = "Sleep After";
+const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode";
+const char pstrUsageIllumination [] PROGMEM = "Illumin";
+const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns";
+const char pstrUsageMenu [] PROGMEM = "Menu";
+const char pstrUsageMenuPick [] PROGMEM = "Menu Pick";
+const char pstrUsageMenuUp [] PROGMEM = "Menu Up";
+const char pstrUsageMenuDown [] PROGMEM = "Menu Down";
+const char pstrUsageMenuLeft [] PROGMEM = "Menu Left";
+const char pstrUsageMenuRight [] PROGMEM = "Menu Right";
+const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc";
+const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc";
+const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec";
+const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr";
+const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn";
+const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel";
+const char pstrUsageVCRTV [] PROGMEM = "VCR/TV";
+const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode";
+const char pstrUsageSnapshot [] PROGMEM = "Snapshot";
+const char pstrUsageStill [] PROGMEM = "Still";
+const char pstrUsageSelection [] PROGMEM = "Sel";
+const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel";
+const char pstrUsageModeStep [] PROGMEM = "Mode Step";
+const char pstrUsageRecallLast [] PROGMEM = "Recall Last";
+const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel";
+const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie";
+const char pstrUsageChannel [] PROGMEM = "Channel";
+const char pstrUsageMediaSelection [] PROGMEM = "Med Sel";
+const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp";
+const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV";
+const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW";
+const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD";
+const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel";
+const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG";
+const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid";
+const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games";
+const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg";
+const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD";
+const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR";
+const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner";
+const char pstrUsageQuit [] PROGMEM = "Quit";
+const char pstrUsageHelp [] PROGMEM = "Help";
+const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape";
+const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl";
+const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat";
+const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur";
+const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home";
+const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call";
+const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc";
+const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec";
+const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP";
+const char pstrUsageVCRPlus [] PROGMEM = "VCR+";
+const char pstrUsageOnce [] PROGMEM = "Once";
+const char pstrUsageDaily [] PROGMEM = "Daily";
+const char pstrUsageWeekly [] PROGMEM = "Weekly";
+const char pstrUsageMonthly [] PROGMEM = "Monthly";
+//const char pstrUsagePlay						[] PROGMEM = "Play";
+//const char pstrUsagePause						[] PROGMEM = "Pause";
+//const char pstrUsageRecord						[] PROGMEM = "Rec";
+//const char pstrUsageFastForward					[] PROGMEM = "FF";
+//const char pstrUsageRewind						[] PROGMEM = "Rewind";
+const char pstrUsageScanNextTrack [] PROGMEM = "Next Track";
+const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track";
+//const char pstrUsageStop						[] PROGMEM = "Stop";
+const char pstrUsageEject [] PROGMEM = "Eject";
+const char pstrUsageRandomPlay [] PROGMEM = "Random";
+const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk";
+const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk";
+//const char pstrUsageRepeat						[] PROGMEM = "Repeat";
+const char pstrUsageTracking [] PROGMEM = "Tracking";
+const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm";
+const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk";
+const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd";
+const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back";
+const char pstrUsageMark [] PROGMEM = "Mark";
+const char pstrUsageClearMark [] PROGMEM = "Clr Mark";
+const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark";
+const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark";
+const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd";
+const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back";
+const char pstrUsageCounterReset [] PROGMEM = "Counter Reset";
+const char pstrUsageShowCounter [] PROGMEM = "Show Counter";
+const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc";
+const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec";
+const char pstrUsageStopEject [] PROGMEM = "Stop/Eject";
+const char pstrUsagePlayPause [] PROGMEM = "Play/Pause";
+const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip";
+const char pstrUsageVolume [] PROGMEM = "Vol";
+const char pstrUsageBalance [] PROGMEM = "Balance";
+//const char pstrUsageMute						[] PROGMEM = "Mute";
+const char pstrUsageBass [] PROGMEM = "Bass";
+const char pstrUsageTreble [] PROGMEM = "Treble";
+const char pstrUsageBassBoost [] PROGMEM = "Bass Boost";
+const char pstrUsageSurroundMode [] PROGMEM = "Surround";
+const char pstrUsageLoudness [] PROGMEM = "Loud";
+const char pstrUsageMPX [] PROGMEM = "MPX";
+const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc";
+const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec";
+const char pstrUsageSpeedSelect [] PROGMEM = "Speed";
+const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed";
+const char pstrUsageStandardPlay [] PROGMEM = "Std Play";
+const char pstrUsageLongPlay [] PROGMEM = "Long Play";
+const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play";
+const char pstrUsageSlow [] PROGMEM = "Slow";
+const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl";
+const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed";
+const char pstrUsageLightEnable [] PROGMEM = "Light Enbl";
+const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev";
+const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl";
+const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp";
+const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl";
+const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm";
+const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm";
+const char pstrUsageProximity [] PROGMEM = "Prox";
+const char pstrUsageMotion [] PROGMEM = "Motion";
+const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm";
+const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm";
+const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm";
+const char pstrUsageBalanceRight [] PROGMEM = "Balance Right";
+const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left";
+const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc";
+const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec";
+const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc";
+const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec";
+const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys";
+const char pstrUsageChannelLeft [] PROGMEM = "Ch Left";
+const char pstrUsageChannelRight [] PROGMEM = "Ch Right";
+const char pstrUsageChannelCenter [] PROGMEM = "Ch Center";
+const char pstrUsageChannelFront [] PROGMEM = "Ch Front";
+const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front";
+const char pstrUsageChannelSide [] PROGMEM = "Ch Side";
+const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround";
+const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh";
+const char pstrUsageChannelTop [] PROGMEM = "Ch Top";
+const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk";
+const char pstrUsageSubChannel [] PROGMEM = "Sub-ch";
+const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc";
+const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec";
+const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc";
+const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec";
+const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns";
+const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl";
+const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn";
+const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg";
+const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc";
+const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr";
+const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet";
+const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr";
+const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App";
+const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App";
+const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr";
+const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr";
+const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail";
+const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book";
+const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr";
+const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr";
+const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd";
+const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin";
+const char pstrUsageALCalculator [] PROGMEM = "AL Calc";
+const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play";
+const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow";
+const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow";
+const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow";
+const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con";
+const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf";
+const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat";
+const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial";
+const char pstrUsageALLogon [] PROGMEM = "AL Logon";
+const char pstrUsageALLogoff [] PROGMEM = "AL Logoff";
+const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff";
+const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav";
+const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan";
+const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run";
+const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr";
+const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App";
+const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App";
+const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App";
+const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App";
+const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr";
+const char pstrUsageALDocuments [] PROGMEM = "AL Docs";
+const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs";
+const char pstrUsageALDictionary [] PROGMEM = "AL Dict";
+const char pstrUsageALDesktop [] PROGMEM = "AL Desktop";
+const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk";
+const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk";
+const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts";
+const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout";
+const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect";
+const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt";
+const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav";
+const char pstrUsageALAlarms [] PROGMEM = "AL Alarms";
+const char pstrUsageALClock [] PROGMEM = "AL Clock";
+const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow";
+const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts";
+const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow";
+const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow";
+const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow";
+const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr";
+const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet";
+const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg";
+const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow";
+const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp";
+const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com";
+const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow";
+const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow";
+const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf";
+const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow";
+const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow";
+const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow";
+const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow";
+const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player";
+const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl";
+const char pstrUsageACNew [] PROGMEM = "AC New";
+const char pstrUsageACOpen [] PROGMEM = "AC Open";
+const char pstrUsageACClose [] PROGMEM = "AC Close";
+const char pstrUsageACExit [] PROGMEM = "AC Exit";
+const char pstrUsageACMaximize [] PROGMEM = "AC Max";
+const char pstrUsageACMinimize [] PROGMEM = "AC Min";
+const char pstrUsageACSave [] PROGMEM = "AC Save";
+const char pstrUsageACPrint [] PROGMEM = "AC Print";
+const char pstrUsageACProperties [] PROGMEM = "AC Prop";
+const char pstrUsageACUndo [] PROGMEM = "AC Undo";
+const char pstrUsageACCopy [] PROGMEM = "AC Copy";
+const char pstrUsageACCut [] PROGMEM = "AC Cut";
+const char pstrUsageACPaste [] PROGMEM = "AC Paste";
+const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All";
+const char pstrUsageACFind [] PROGMEM = "AC Find";
+const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace";
+const char pstrUsageACSearch [] PROGMEM = "AC Search";
+const char pstrUsageACGoto [] PROGMEM = "AC Goto";
+const char pstrUsageACHome [] PROGMEM = "AC Home";
+const char pstrUsageACBack [] PROGMEM = "AC Back";
+const char pstrUsageACForward [] PROGMEM = "AC Fwd";
+const char pstrUsageACStop [] PROGMEM = "AC Stop";
+const char pstrUsageACRefresh [] PROGMEM = "AC Refresh";
+const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link";
+const char pstrUsageACNextLink [] PROGMEM = "AC Next Link";
+const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks";
+const char pstrUsageACHistory [] PROGMEM = "AC Hist";
+const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr";
+const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In";
+const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out";
+const char pstrUsageACZoom [] PROGMEM = "AC Zoom";
+const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr";
+const char pstrUsageACNormalView [] PROGMEM = "AC Norm View";
+const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl";
+const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up";
+const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down";
+const char pstrUsageACScroll [] PROGMEM = "AC Scroll";
+const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left";
+const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right";
+const char pstrUsageACPan [] PROGMEM = "AC Pan";
+const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd";
+const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz";
+const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert";
+const char pstrUsageACFormat [] PROGMEM = "AC Frmt";
+const char pstrUsageACEdit [] PROGMEM = "AC Edit";
+const char pstrUsageACBold [] PROGMEM = "AC Bold";
+const char pstrUsageACItalics [] PROGMEM = "AC Ital";
+const char pstrUsageACUnderline [] PROGMEM = "AC Under";
+const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike";
+const char pstrUsageACSubscript [] PROGMEM = "AC Sub";
+const char pstrUsageACSuperscript [] PROGMEM = "AC Super";
+const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps";
+const char pstrUsageACRotate [] PROGMEM = "AC Rotate";
+const char pstrUsageACResize [] PROGMEM = "AC Resize";
+const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H";
+const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V";
+const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H";
+const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V";
+const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel";
+const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr";
+const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size";
+const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left";
+const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H";
+const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right";
+const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H";
+const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top";
+const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V";
+const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot";
+const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V";
+const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec";
+const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc";
+const char pstrUsageACNumberedList [] PROGMEM = "AC Num List";
+const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num";
+const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List";
+const char pstrUsageACPromote [] PROGMEM = "AC Promote";
+const char pstrUsageACDemote [] PROGMEM = "AC Demote";
+const char pstrUsageACYes [] PROGMEM = "AC Yes";
+const char pstrUsageACNo [] PROGMEM = "AC No";
+const char pstrUsageACCancel [] PROGMEM = "AC Cancel";
+const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg";
+const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy";
+const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart";
+const char pstrUsageACExpand [] PROGMEM = "AC Xpnd";
+const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All";
+const char pstrUsageACCollapse [] PROGMEM = "AC Collapse";
+const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All";
+const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw";
+const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec";
+const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode";
+const char pstrUsageACDelete [] PROGMEM = "AC Del";
+const char pstrUsageACLock [] PROGMEM = "AC Lock";
+const char pstrUsageACUnlock [] PROGMEM = "AC Unlock";
+const char pstrUsageACProtect [] PROGMEM = "AC Prot";
+const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot";
+const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt";
+const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt";
+const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt";
+const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word";
+const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc";
+const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para";
+const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col";
+const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row";
+const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl";
+const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj";
+const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo";
+const char pstrUsageACSort [] PROGMEM = "AC Sort";
+const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc";
+const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc";
+const char pstrUsageACFilter [] PROGMEM = "AC Filt";
+const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk";
+const char pstrUsageACViewClock [] PROGMEM = "AC View Clk";
+const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z";
+const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z";
+const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm";
+const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm";
+const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm";
+const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm";
+const char pstrUsageACSyncronize [] PROGMEM = "AC Sync";
+const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv";
+const char pstrUsageACSendTo [] PROGMEM = "AC Snd To";
+const char pstrUsageACReply [] PROGMEM = "AC Reply";
+const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All";
+const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg";
+const char pstrUsageACSend [] PROGMEM = "AC Snd";
+const char pstrUsageACAttachFile [] PROGMEM = "AC Att File";
+const char pstrUsageACUpload [] PROGMEM = "AC Upld";
+const char pstrUsageACDownload [] PROGMEM = "AC Dnld";
+const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd";
+const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row";
+const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col";
+const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File";
+const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic";
+const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj";
+const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym";
+const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls";
+const char pstrUsageACRename [] PROGMEM = "AC Rename";
+const char pstrUsageACMerge [] PROGMEM = "AC Merge";
+const char pstrUsageACSplit [] PROGMEM = "AC Split";
+const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor";
+const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver";
+
+// Digitaizers
+const char pstrUsageDigitizer [] PROGMEM = "Digitizer";
+const char pstrUsagePen [] PROGMEM = "Pen";
+const char pstrUsageLightPen [] PROGMEM = "Light Pen";
+const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr";
+const char pstrUsageTouchPad [] PROGMEM = "Touch Pad";
+const char pstrUsageWhiteBoard [] PROGMEM = "White Brd";
+const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach";
+const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz";
+const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot";
+const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm";
+const char pstrUsageArmature [] PROGMEM = "Armature";
+const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz";
+const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand";
+const char pstrUsageStylus [] PROGMEM = "Stylus";
+const char pstrUsagePuck [] PROGMEM = "Puck";
+const char pstrUsageFinger [] PROGMEM = "Finger";
+const char pstrUsageTipPressure [] PROGMEM = "Tip Press";
+const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press";
+const char pstrUsageInRange [] PROGMEM = "In Range";
+const char pstrUsageTouch [] PROGMEM = "Touch";
+const char pstrUsageUntouch [] PROGMEM = "Untouch";
+const char pstrUsageTap [] PROGMEM = "Tap";
+const char pstrUsageQuality [] PROGMEM = "Qlty";
+const char pstrUsageDataValid [] PROGMEM = "Data Valid";
+const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind";
+const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys";
+const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys";
+//const char pstrUsageBatteryStrength				[] PROGMEM = "Bat Strength";
+const char pstrUsageInvert [] PROGMEM = "Invert";
+const char pstrUsageXTilt [] PROGMEM = "X Tilt";
+const char pstrUsageYTilt [] PROGMEM = "Y Tilt";
+const char pstrUsageAzimuth [] PROGMEM = "Azimuth";
+const char pstrUsageAltitude [] PROGMEM = "Altitude";
+const char pstrUsageTwist [] PROGMEM = "Twist";
+const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw";
+const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw";
+const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw";
+const char pstrUsageEraser [] PROGMEM = "Eraser";
+const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick";
+
+// Alphanumeric Display Page
+const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp";
+const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp";
+const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt";
+const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset";
+const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back";
+const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back";
+const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt";
+const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp";
+//const char pstrUsageDisplayEnable				[] PROGMEM = "Disp Enbl";
+const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay";
+const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl";
+const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll";
+const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll";
+const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt";
+const char pstrUsageDisplayData [] PROGMEM = "Disp Data";
+const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat";
+const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready";
+const char pstrUsageStatusReady [] PROGMEM = "Stat Ready";
+const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char";
+const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err";
+const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt";
+const char pstrUsageRow [] PROGMEM = "Row";
+const char pstrUsageColumn [] PROGMEM = "Col";
+const char pstrUsageRows [] PROGMEM = "Rows";
+const char pstrUsageColumns [] PROGMEM = "Cols";
+const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos";
+const char pstrUsageCursorMode [] PROGMEM = "Cur Mode";
+const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl";
+const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk";
+const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt";
+const char pstrUsageFontData [] PROGMEM = "Fnt Data";
+const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth";
+const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght";
+const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H";
+const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V";
+const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char";
+const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg";
+const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map";
+const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg";
+const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map";
+const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright";
+const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst";
+const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr";
+const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk";
+const char pstrUsageAttributeData [] PROGMEM = "Attr Data";
+const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh";
+const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl";
+const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk";
+const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X";
+const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y";
+const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt";
+const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt";
+const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt";
+const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size";
+const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off";
+const char pstrUsagePaletteData [] PROGMEM = "Pal Data";
+const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt";
+const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1";
+const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1";
+const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2";
+const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2";
+const char pstrUsageBlitData [] PROGMEM = "Blit Data";
+const char pstrUsageSoftButton [] PROGMEM = "Soft Btn";
+const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID";
+const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side";
+const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1";
+const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2";
+const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt";
+
+// Medical Instrument Page
+const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd";
+const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq";
+const char pstrUsageFreezeThaw [] PROGMEM = "Freeze";
+const char pstrUsageClipStore [] PROGMEM = "Clip Store";
+const char pstrUsageUpdate [] PROGMEM = "Update";
+const char pstrUsageNext [] PROGMEM = "Next";
+const char pstrUsageSave [] PROGMEM = "Save";
+const char pstrUsagePrint [] PROGMEM = "Print";
+const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl";
+const char pstrUsageCine [] PROGMEM = "Cine";
+const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr";
+//const char pstrUsageVolume						[] PROGMEM = "Vol";
+const char pstrUsageFocus [] PROGMEM = "Focus";
+const char pstrUsageDepth [] PROGMEM = "Depth";
+const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri";
+const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec";
+const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp";
+const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel";
+const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj";
+const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel";
+const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj";
+const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel";
+const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj";
+const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel";
+const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj";
+const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel";
+const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj";
+const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel";
+const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj";
+
+//extern const char *usagePageTitles0[15];
+//const char *usagePageTitles1[];
+//const char *genDesktopTitles0[];
+//const char *genDesktopTitles1[];
+//const char *genDesktopTitles2[];
+//const char *genDesktopTitles3[];
+//const char *genDesktopTitles4[];
+//const char *simuTitles0[];
+//const char *simuTitles1[];
+//const char *simuTitles2[];
+//const char *vrTitles0[];
+//const char *vrTitles1[];
+//const char *sportsCtrlTitles0[];
+//const char *sportsCtrlTitles1[];
+//const char *sportsCtrlTitles2[];
+//const char *gameTitles0[];
+//const char *gameTitles1[];
+//const char *genDevCtrlTitles[];
+//const char *ledTitles[];
+//const char *telTitles0[];
+//const char *telTitles1[];
+//const char *telTitles2[];
+//const char *telTitles3[];
+//const char *telTitles4[];
+//const char *telTitles5[];
+//const char *consTitles0[];
+//const char *consTitles1[];
+//const char *consTitles2[];
+//const char *consTitles3[];
+//const char *consTitles4[];
+//const char *consTitles5[];
+//const char *consTitles6[];
+//const char *consTitles7[];
+//const char *consTitles8[];
+//const char *consTitles9[];
+//const char *consTitlesA[];
+//const char *consTitlesB[];
+//const char *consTitlesC[];
+//const char *consTitlesD[];
+//const char *consTitlesE[];
+//const char *digitTitles0[];
+//const char *digitTitles1[];
+//const char *digitTitles2[];
+//const char *aplphanumTitles0[];
+//const char *aplphanumTitles1[];
+//const char *aplphanumTitles2[];
+//const char *medInstrTitles0[];
+//const char *medInstrTitles1[];
+//const char *medInstrTitles2[];
+//const char *medInstrTitles3[];
+//const char *medInstrTitles4[];
+
+#endif //__HIDUSAGESTR_H__
diff --git a/libraries/USBHost/src/macros.h b/libraries/USBHost/src/macros.h
new file mode 100644
index 0000000000000000000000000000000000000000..5df3faff8ab2ec887c595878f65b16391186ee50
--- /dev/null
+++ b/libraries/USBHost/src/macros.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(MACROS_H)
+#error "Never include macros.h directly; include Usb.h instead"
+#else
+#define	MACROS_H
+
+////////////////////////////////////////////////////////////////////////////////
+// HANDY MACROS
+////////////////////////////////////////////////////////////////////////////////
+
+#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h)))
+#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h)))
+#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)/*pgm_read_pointer*/(wa), el)
+#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el);
+
+#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
+#ifndef __BYTE_GRABBING_DEFINED__
+#define __BYTE_GRABBING_DEFINED__ 1
+#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN
+// Note: Use this if your compiler generates horrible assembler!
+#define BGRAB0(__usi__)  (((uint8_t *)&(__usi__))[0])
+#define BGRAB1(__usi__)  (((uint8_t *)&(__usi__))[1])
+#define BGRAB2(__usi__)  (((uint8_t *)&(__usi__))[2])
+#define BGRAB3(__usi__)  (((uint8_t *)&(__usi__))[3])
+#define BGRAB4(__usi__)  (((uint8_t *)&(__usi__))[4])
+#define BGRAB5(__usi__)  (((uint8_t *)&(__usi__))[5])
+#define BGRAB6(__usi__)  (((uint8_t *)&(__usi__))[6])
+#define BGRAB7(__usi__)  (((uint8_t *)&(__usi__))[7])
+#else
+// Note: The cast alone to uint8_t is actually enough.
+// GCC throws out the "& 0xff", and the size is no different.
+// Some compilers need it.
+#define BGRAB0(__usi__)  ((uint8_t)((__usi__) & 0xff ))
+#define BGRAB1(__usi__)  ((uint8_t)(((__usi__) >> 8) & 0xff))
+#define BGRAB2(__usi__)  ((uint8_t)(((__usi__) >> 16) & 0xff))
+#define BGRAB3(__usi__)  ((uint8_t)(((__usi__) >> 24) & 0xff))
+#define BGRAB4(__usi__)  ((uint8_t)(((__usi__) >> 32) & 0xff))
+#define BGRAB5(__usi__)  ((uint8_t)(((__usi__) >> 40) & 0xff))
+#define BGRAB6(__usi__)  ((uint8_t)(((__usi__) >> 48) & 0xff))
+#define BGRAB7(__usi__)  ((uint8_t)(((__usi__) >> 56) & 0xff))
+#endif
+#define BOVER1(__usi__)  ((uint16_t)(__usi__) << 8)
+#define BOVER2(__usi__)  ((uint32_t)(__usi__) << 16)
+#define BOVER3(__usi__)  ((uint32_t)(__usi__) << 24)
+#define BOVER4(__usi__)  ((uint64_t)(__usi__) << 32)
+#define BOVER5(__usi__)  ((uint64_t)(__usi__) << 40)
+#define BOVER6(__usi__)  ((uint64_t)(__usi__) << 48)
+#define BOVER7(__usi__)  ((uint64_t)(__usi__) << 56)
+
+// These are the smallest and fastest ways I have found so far in pure C/C++.
+#define BMAKE16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)BOVER1(__usc1__)))
+#define BMAKE32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | (uint32_t)BOVER1(__usc1__) | (uint32_t)BOVER2(__usc2__) | (uint32_t)BOVER3(__usc3__)))
+#define BMAKE64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | (uint64_t)BOVER1(__usc1__) | (uint64_t)BOVER2(__usc2__) | (uint64_t)BOVER3(__usc3__) | (uint64_t)BOVER4(__usc4__) | (uint64_t)BOVER5(__usc5__) | (uint64_t)BOVER6(__usc6__) | (uint64_t)BOVER1(__usc7__)))
+#endif
+
+/*
+ * Debug macros: Strings are stored in progmem (flash) instead of RAM.
+ */
+#define USBTRACE(s) (Notify(PSTR(s), 0x80))
+#define USBTRACE1(s,l) (Notify(PSTR(s), l))
+#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80))
+#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l))
+
+
+#endif	/* MACROS_H */
+
diff --git a/libraries/USBHost/src/message.cpp b/libraries/USBHost/src/message.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..960a9fb44267c61e9a85e306c7f6e7d45062cd0d
--- /dev/null
+++ b/libraries/USBHost/src/message.cpp
@@ -0,0 +1,116 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#include "Usb.h"
+// 0x80 is the default (i.e. trace) to turn off set this global to something lower.
+// this allows for 126 other debugging levels.
+// TO-DO: Allow assignment to a different serial port by software
+int UsbDEBUGlvl = 0x80;
+
+void E_Notifyc(char c, int lvl) {
+        if(UsbDEBUGlvl < lvl) return;
+#if defined(ARDUINO) && ARDUINO >=100
+        USB_HOST_SERIAL.print(c);
+#else
+        USB_HOST_SERIAL.print(c, BYTE);
+#endif
+        //USB_HOST_SERIAL.flush();
+}
+
+void E_Notify(char const * msg, int lvl) {
+        if(UsbDEBUGlvl < lvl) return;
+        if(!msg) return;
+        char c;
+
+        while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl);
+}
+
+void E_NotifyStr(char const * msg, int lvl) {
+        if(UsbDEBUGlvl < lvl) return;
+        if(!msg) return;
+        char c;
+
+        while((c = *msg++)) E_Notifyc(c, lvl);
+}
+
+void E_Notify(uint8_t b, int lvl) {
+        if(UsbDEBUGlvl < lvl) return;
+#if defined(ARDUINO) && ARDUINO >=100
+        USB_HOST_SERIAL.print(b);
+#else
+        USB_HOST_SERIAL.print(b, DEC);
+#endif
+        //USB_HOST_SERIAL.flush();
+}
+
+void E_Notify(double d, int lvl) {
+        if(UsbDEBUGlvl < lvl) return;
+        USB_HOST_SERIAL.print(d);
+        //USB_HOST_SERIAL.flush();
+}
+
+#ifdef DEBUG_USB_HOST
+
+void NotifyFailGetDevDescr(void) {
+        Notify(PSTR("\r\ngetDevDescr "), 0x80);
+}
+
+void NotifyFailSetDevTblEntry(void) {
+        Notify(PSTR("\r\nsetDevTblEn "), 0x80);
+}
+
+void NotifyFailGetConfDescr(void) {
+        Notify(PSTR("\r\ngetConf "), 0x80);
+}
+
+void NotifyFailSetConfDescr(void) {
+        Notify(PSTR("\r\nsetConf "), 0x80);
+}
+
+void NotifyFailGetDevDescr(uint8_t reason) {
+        NotifyFailGetDevDescr();
+        NotifyFail(reason);
+}
+
+void NotifyFailSetDevTblEntry(uint8_t reason) {
+        NotifyFailSetDevTblEntry();
+        NotifyFail(reason);
+
+}
+
+void NotifyFailGetConfDescr(uint8_t reason) {
+        NotifyFailGetConfDescr();
+        NotifyFail(reason);
+}
+
+void NotifyFailSetConfDescr(uint8_t reason) {
+        NotifyFailSetConfDescr();
+        NotifyFail(reason);
+}
+
+void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) {
+        Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
+        D_PrintHex<uint16_t > (VID, 0x80);
+        Notify(PSTR(" PID: "), 0x80);
+        D_PrintHex<uint16_t > (PID, 0x80);
+}
+
+void NotifyFail(uint8_t rcode) {
+        D_PrintHex<uint8_t > (rcode, 0x80);
+        Notify(PSTR("\r\n"), 0x80);
+}
+#endif
diff --git a/libraries/USBHost/src/message.h b/libraries/USBHost/src/message.h
new file mode 100644
index 0000000000000000000000000000000000000000..41f526de2babdb03bf029c0fda7cb5865476b66e
--- /dev/null
+++ b/libraries/USBHost/src/message.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__MESSAGE_H__)
+#error "Never include message.h directly; include Usb.h instead"
+#else
+#define __MESSAGE_H__
+
+extern int UsbDEBUGlvl;
+
+void E_Notify(char const * msg, int lvl);
+void E_Notify(uint8_t b, int lvl);
+void E_NotifyStr(char const * msg, int lvl);
+void E_Notifyc(char c, int lvl);
+
+#ifdef DEBUG_USB_HOST
+#define Notify E_Notify
+#define NotifyStr E_NotifyStr
+#define Notifyc E_Notifyc
+void NotifyFailGetDevDescr(uint8_t reason);
+void NotifyFailSetDevTblEntry(uint8_t reason);
+void NotifyFailGetConfDescr(uint8_t reason);
+void NotifyFailSetConfDescr(uint8_t reason);
+void NotifyFailGetDevDescr(void);
+void NotifyFailSetDevTblEntry(void);
+void NotifyFailGetConfDescr(void);
+void NotifyFailSetConfDescr(void);
+void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID);
+void NotifyFail(uint8_t rcode);
+#else
+#define Notify(...) ((void)0)
+#define NotifyStr(...) ((void)0)
+#define Notifyc(...) ((void)0)
+#define NotifyFailGetDevDescr(...) ((void)0)
+#define NotifyFailSetDevTblEntry(...) ((void)0)
+#define NotifyFailGetConfDescr(...) ((void)0)
+#define NotifyFailGetDevDescr(...) ((void)0)
+#define NotifyFailSetDevTblEntry(...) ((void)0)
+#define NotifyFailGetConfDescr(...) ((void)0)
+#define NotifyFailSetConfDescr(...) ((void)0)
+#define NotifyFailUnknownDevice(...) ((void)0)
+#define NotifyFail(...) ((void)0)
+#endif
+
+template <class ERROR_TYPE>
+void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) {
+#ifdef DEBUG_USB_HOST
+        Notify(msg, level);
+        Notify(PSTR(": "), level);
+        D_PrintHex<ERROR_TYPE > (rcode, level);
+        Notify(PSTR("\r\n"), level);
+#endif
+}
+
+template <class ERROR_TYPE>
+void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) {
+#ifdef DEBUG_USB_HOST
+        Notify(msg, 0x80);
+        Notify(PSTR(": "), 0x80);
+        D_PrintHex<ERROR_TYPE > (rcode, 0x80);
+        Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+#endif // __MESSAGE_H__
diff --git a/libraries/USBHost/src/parsetools.cpp b/libraries/USBHost/src/parsetools.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..00ca9e6427fbb353a3a440f065070d9b63622c18
--- /dev/null
+++ b/libraries/USBHost/src/parsetools.cpp
@@ -0,0 +1,67 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+#include "Usb.h"
+
+bool MultiByteValueParser::Parse(uint8_t **pp, uint32_t *pcntdn) {
+        if(!pBuf) {
+                Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
+		return false;
+	}
+	for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
+		pBuf[valueSize - countDown] = (**pp);
+
+        if(countDown)
+		return false;
+
+	countDown = valueSize;
+	return true;
+}
+
+bool PTPListParser::Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
+        switch(nStage) {
+	case 0:
+		pBuf->valueSize = lenSize;
+		theParser.Initialize(pBuf);
+		nStage = 1;
+
+	case 1:
+		if(!theParser.Parse(pp, pcntdn))
+			return false;
+
+		arLen = 0;
+		arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
+		arLenCntdn = arLen;
+		nStage = 2;
+
+	case 2:
+		pBuf->valueSize = valSize;
+		theParser.Initialize(pBuf);
+		nStage = 3;
+
+	case 3:
+                for(; arLenCntdn; arLenCntdn--) {
+			if(!theParser.Parse(pp, pcntdn))
+				return false;
+
+			if(pf)
+				pf(pBuf, (arLen - arLenCntdn), me);
+		}
+
+		nStage = 0;
+	}
+	return true;
+}
diff --git a/libraries/USBHost/src/parsetools.h b/libraries/USBHost/src/parsetools.h
new file mode 100644
index 0000000000000000000000000000000000000000..d463358913f5753e9caf8481894de986104b35a9
--- /dev/null
+++ b/libraries/USBHost/src/parsetools.h
@@ -0,0 +1,143 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+#if !defined(_usb_h_) || defined(__PARSETOOLS_H__)
+#error "Never include parsetools.h directly; include Usb.h instead"
+#else
+#define __PARSETOOLS_H__
+
+#include <stdint.h>
+//#include "Arduino.h"
+
+struct MultiValueBuffer {
+	uint8_t		valueSize;
+	void		*pValue;
+};
+
+class MultiByteValueParser {
+	uint8_t				*pBuf;
+	uint32_t			countDown;
+	uint32_t			valueSize;
+
+public:
+
+        MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
+        };
+
+        const uint8_t* GetBuffer() {
+                return pBuf;
+        };
+
+	void Initialize(MultiValueBuffer * const pbuf) {
+		pBuf = (uint8_t*)pbuf->pValue;
+		countDown = valueSize = pbuf->valueSize;
+	};
+
+	bool Parse(uint8_t **pp, uint32_t *pcntdn);
+};
+
+class ByteSkipper {
+	uint8_t				*pBuf;
+	uint32_t			nStage;
+	uint32_t			countDown;
+
+public:
+
+	ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {
+        };
+
+	void Initialize(MultiValueBuffer *pbuf) {
+		pBuf = (uint8_t*)pbuf->pValue;
+		countDown = 0;
+	};
+
+	bool Skip(uint8_t **pp, uint32_t *pcntdn, uint32_t bytes_to_skip) {
+                switch(nStage) {
+                       case 0:
+                                countDown = bytes_to_skip;
+                                nStage++;
+                        case 1:
+                                for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
+
+                                if(!countDown)
+                                        nStage = 0;
+		};
+		return (!countDown);
+	};
+};
+
+// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
+typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
+
+class PTPListParser {
+public:
+
+        enum ParseMode {
+                modeArray, modeRange/*, modeEnum*/
+        };
+
+private:
+	uint32_t				nStage;
+	uint32_t				enStage;
+
+	uint32_t				arLen;
+	uint32_t				arLenCntdn;
+
+	uint32_t				lenSize;		// size of the array length field in bytes
+	uint32_t				valSize;		// size of the array element in bytes
+
+	MultiValueBuffer		*pBuf;
+
+	// The only parser for both size and array element parsing
+	MultiByteValueParser	theParser;
+
+	uint32_t /*ParseMode*/	prsMode;
+
+public:
+
+	PTPListParser() :
+		nStage(0),
+		enStage(0),
+		arLen(0),
+		arLenCntdn(0),
+		lenSize(0),
+		valSize(0),
+		pBuf(NULL),
+		prsMode(modeArray) {
+                };
+
+	void Initialize(const uint32_t len_size, const uint32_t val_size, MultiValueBuffer * const p, const uint32_t mode = modeArray) {
+		pBuf	= p;
+		lenSize	= len_size;
+		valSize = val_size;
+		prsMode = mode;
+
+		if(prsMode == modeRange) {
+			arLenCntdn = arLen = 3;
+			nStage = 2;
+		} else {
+			arLenCntdn = arLen = 0;
+			nStage = 0;
+		}
+		enStage = 0;
+		theParser.Initialize(p);
+	};
+
+	bool Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
+};
+
+#endif // __PARSETOOLS_H__
diff --git a/libraries/USBHost/src/printhex.h b/libraries/USBHost/src/printhex.h
new file mode 100644
index 0000000000000000000000000000000000000000..369d7e1f7ebe55761ea291973e5edc76eac7ee3c
--- /dev/null
+++ b/libraries/USBHost/src/printhex.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(__PRINTHEX_H__)
+#error "Never include printhex.h directly; include Usb.h instead"
+#else
+#define __PRINTHEX_H__
+
+void E_Notifyc(char c, int lvl);
+
+template <class T>
+void PrintHex(T val, int lvl) {
+        int num_nibbles = sizeof (T) * 2;
+
+        do {
+                char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
+                if(v > 57) v += 7;
+                E_Notifyc(v, lvl);
+        } while(--num_nibbles);
+}
+
+template <class T>
+void PrintBin(T val, int lvl) {
+        for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)
+                if(val & mask)
+                        E_Notifyc('1', lvl);
+                else
+                        E_Notifyc('0', lvl);
+}
+
+template <class T>
+void SerialPrintHex(T val) {
+        int num_nibbles = sizeof (T) * 2;
+
+        do {
+                char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
+                if(v > 57) v += 7;
+                USB_HOST_SERIAL.print(v);
+        } while(--num_nibbles);
+}
+
+template <class T>
+void PrintHex2(Print *prn, T val) {
+        T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2));
+
+        while(mask > 1) {
+                if(val < mask)
+                        prn->print("0");
+
+                mask >>= 4;
+        }
+        prn->print((T)val, HEX);
+}
+
+template <class T> void D_PrintHex(T val, int lvl) {
+#ifdef DEBUG_USB_HOST
+        PrintHex<T > (val, lvl);
+#endif
+}
+
+template <class T>
+void D_PrintBin(T val, int lvl) {
+#ifdef DEBUG_USB_HOST
+        PrintBin<T > (val, lvl);
+#endif
+}
+
+
+
+#endif // __PRINTHEX_H__
diff --git a/libraries/USBHost/src/sink_parser.h b/libraries/USBHost/src/sink_parser.h
new file mode 100644
index 0000000000000000000000000000000000000000..a23637d2b74a91f529daaa1f622bbdf30acd5902
--- /dev/null
+++ b/libraries/USBHost/src/sink_parser.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__SINK_PARSER_H__)
+#error "Never include hexdump.h directly; include Usb.h instead"
+#else
+#define __SINK_PARSER_H__
+
+extern int UsbDEBUGlvl;
+
+// This parser does absolutely nothing with the data, just swallows it.
+
+template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
+class SinkParser : public BASE_CLASS {
+public:
+
+        SinkParser() {
+        };
+
+        void Initialize() {
+        };
+
+        void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
+        };
+};
+
+
+#endif // __HEXDUMP_H__
diff --git a/libraries/USBHost/src/usb_ch9.h b/libraries/USBHost/src/usb_ch9.h
new file mode 100644
index 0000000000000000000000000000000000000000..09dd94b9b46c32ec90b2dcc6c29ba48ef827a3dc
--- /dev/null
+++ b/libraries/USBHost/src/usb_ch9.h
@@ -0,0 +1,174 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+*/
+
+#if !defined(_usb_h_) || defined(_ch9_h_)
+#error "Never include usb_ch9.h directly; include Usb.h instead"
+#else
+
+/* USB chapter 9 structures */
+#define _ch9_h_
+
+#include <stdint.h>
+
+/* Misc.USB constants */
+#define DEV_DESCR_LEN   18      //device descriptor length
+#define CONF_DESCR_LEN  9       //configuration descriptor length
+#define INTR_DESCR_LEN  9       //interface descriptor length
+#define EP_DESCR_LEN    7       //endpoint descriptor length
+
+/* Standard Device Requests */
+
+#define USB_REQUEST_GET_STATUS                  0       // Standard Device Request - GET STATUS
+#define USB_REQUEST_CLEAR_FEATURE               1       // Standard Device Request - CLEAR FEATURE
+#define USB_REQUEST_SET_FEATURE                 3       // Standard Device Request - SET FEATURE
+#define USB_REQUEST_SET_ADDRESS                 5       // Standard Device Request - SET ADDRESS
+#define USB_REQUEST_GET_DESCRIPTOR              6       // Standard Device Request - GET DESCRIPTOR
+#define USB_REQUEST_SET_DESCRIPTOR              7       // Standard Device Request - SET DESCRIPTOR
+#define USB_REQUEST_GET_CONFIGURATION           8       // Standard Device Request - GET CONFIGURATION
+#define USB_REQUEST_SET_CONFIGURATION           9       // Standard Device Request - SET CONFIGURATION
+#define USB_REQUEST_GET_INTERFACE               10      // Standard Device Request - GET INTERFACE
+#define USB_REQUEST_SET_INTERFACE               11      // Standard Device Request - SET INTERFACE
+#define USB_REQUEST_SYNCH_FRAME                 12      // Standard Device Request - SYNCH FRAME
+
+#define USB_FEATURE_ENDPOINT_HALT               0       // CLEAR/SET FEATURE - Endpoint Halt
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP        1       // CLEAR/SET FEATURE - Device remote wake-up
+#define USB_FEATURE_TEST_MODE                   2       // CLEAR/SET FEATURE - Test mode
+
+/* Setup Data Constants */
+
+#define USB_SETUP_HOST_TO_DEVICE                0x00    // Device Request bmRequestType transfer direction - host to device transfer
+#define USB_SETUP_DEVICE_TO_HOST                0x80    // Device Request bmRequestType transfer direction - device to host transfer
+#define USB_SETUP_TYPE_STANDARD                 0x00    // Device Request bmRequestType type - standard
+#define USB_SETUP_TYPE_CLASS                    0x20    // Device Request bmRequestType type - class
+#define USB_SETUP_TYPE_VENDOR                   0x40    // Device Request bmRequestType type - vendor
+#define USB_SETUP_RECIPIENT_DEVICE              0x00    // Device Request bmRequestType recipient - device
+#define USB_SETUP_RECIPIENT_INTERFACE           0x01    // Device Request bmRequestType recipient - interface
+#define USB_SETUP_RECIPIENT_ENDPOINT            0x02    // Device Request bmRequestType recipient - endpoint
+#define USB_SETUP_RECIPIENT_OTHER               0x03    // Device Request bmRequestType recipient - other
+
+/* USB descriptors  */
+
+#define USB_DESCRIPTOR_DEVICE           0x01    // bDescriptorType for a Device Descriptor.
+#define USB_DESCRIPTOR_CONFIGURATION    0x02    // bDescriptorType for a Configuration Descriptor.
+#define USB_DESCRIPTOR_STRING           0x03    // bDescriptorType for a String Descriptor.
+#define USB_DESCRIPTOR_INTERFACE        0x04    // bDescriptorType for an Interface Descriptor.
+#define USB_DESCRIPTOR_ENDPOINT         0x05    // bDescriptorType for an Endpoint Descriptor.
+#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06    // bDescriptorType for a Device Qualifier.
+#define USB_DESCRIPTOR_OTHER_SPEED      0x07    // bDescriptorType for a Other Speed Configuration.
+#define USB_DESCRIPTOR_INTERFACE_POWER  0x08    // bDescriptorType for Interface Power.
+#define USB_DESCRIPTOR_OTG              0x09    // bDescriptorType for an OTG Descriptor.
+
+#define HID_DESCRIPTOR_HID			0x21
+
+
+
+/* OTG SET FEATURE Constants    */
+#define OTG_FEATURE_B_HNP_ENABLE                3       // SET FEATURE OTG - Enable B device to perform HNP
+#define OTG_FEATURE_A_HNP_SUPPORT               4       // SET FEATURE OTG - A device supports HNP
+#define OTG_FEATURE_A_ALT_HNP_SUPPORT           5       // SET FEATURE OTG - Another port on the A device supports HNP
+
+/* USB Endpoint Transfer Types  */
+#define USB_TRANSFER_TYPE_CONTROL               0x00    // Endpoint is a control endpoint.
+#define USB_TRANSFER_TYPE_ISOCHRONOUS           0x01    // Endpoint is an isochronous endpoint.
+#define USB_TRANSFER_TYPE_BULK                  0x02    // Endpoint is a bulk endpoint.
+#define USB_TRANSFER_TYPE_INTERRUPT             0x03    // Endpoint is an interrupt endpoint.
+#define bmUSB_TRANSFER_TYPE                     0x03    // bit mask to separate transfer type from ISO attributes
+
+
+/* Standard Feature Selectors for CLEAR_FEATURE Requests    */
+#define USB_FEATURE_ENDPOINT_STALL              0       // Endpoint recipient
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP        1       // Device recipient
+#define USB_FEATURE_TEST_MODE                   2       // Device recipient
+
+_Pragma("pack(1)")
+
+/* descriptor data structures */
+
+/* Device descriptor structure */
+typedef struct {
+    uint8_t		bLength;               // Length of this descriptor.
+    uint8_t		bDescriptorType;       // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
+    uint16_t	bcdUSB;				   // USB Spec Release Number (BCD).
+    uint8_t		bDeviceClass;          // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
+    uint8_t		bDeviceSubClass;       // Subclass code (assigned by the USB-IF).
+    uint8_t		bDeviceProtocol;       // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
+    uint8_t		bMaxPacketSize0;       // Maximum packet size for endpoint 0.
+    uint16_t	idVendor;			   // Vendor ID (assigned by the USB-IF).
+    uint16_t	idProduct;			   // Product ID (assigned by the manufacturer).
+    uint16_t	bcdDevice;			   // Device release number (BCD).
+    uint8_t		iManufacturer;         // Index of String Descriptor describing the manufacturer.
+    uint8_t		iProduct;              // Index of String Descriptor describing the product.
+    uint8_t		iSerialNumber;         // Index of String Descriptor with the device's serial number.
+    uint8_t		bNumConfigurations;    // Number of possible configurations.
+} USB_DEVICE_DESCRIPTOR;
+
+/* Configuration descriptor structure */
+typedef struct {
+    uint8_t bLength;               // Length of this descriptor.
+    uint8_t bDescriptorType;       // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
+    uint16_t wTotalLength;          // Total length of all descriptors for this configuration.
+    uint8_t bNumInterfaces;        // Number of interfaces in this configuration.
+    uint8_t bConfigurationValue;   // Value of this configuration (1 based).
+    uint8_t iConfiguration;        // Index of String Descriptor describing the configuration.
+    uint8_t bmAttributes;          // Configuration characteristics.
+    uint8_t bMaxPower;             // Maximum power consumed by this configuration.
+} USB_CONFIGURATION_DESCRIPTOR;
+
+/* Interface descriptor structure */
+typedef struct {
+    uint8_t bLength;               // Length of this descriptor.
+    uint8_t bDescriptorType;       // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
+    uint8_t bInterfaceNumber;      // Number of this interface (0 based).
+    uint8_t bAlternateSetting;     // Value of this alternate interface setting.
+    uint8_t bNumEndpoints;         // Number of endpoints in this interface.
+    uint8_t bInterfaceClass;       // Class code (assigned by the USB-IF).  0xFF-Vendor specific.
+    uint8_t bInterfaceSubClass;    // Subclass code (assigned by the USB-IF).
+    uint8_t bInterfaceProtocol;    // Protocol code (assigned by the USB-IF).  0xFF-Vendor specific.
+    uint8_t iInterface;            // Index of String Descriptor describing the interface.
+} USB_INTERFACE_DESCRIPTOR;
+
+/* Endpoint descriptor structure */
+typedef struct {
+    uint8_t bLength;               // Length of this descriptor.
+    uint8_t bDescriptorType;       // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
+    uint8_t bEndpointAddress;      // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
+    uint8_t bmAttributes;          // Endpoint transfer type.
+    uint16_t wMaxPacketSize;       // Maximum packet size.
+    uint8_t bInterval;             // Polling interval in frames.
+} USB_ENDPOINT_DESCRIPTOR;
+
+
+/* HID descriptor */
+typedef struct {
+    uint8_t		bLength;
+	uint8_t		bDescriptorType;
+	uint16_t	bcdHID;					// HID class specification release
+    uint8_t		bCountryCode;
+	uint8_t		bNumDescriptors;		// Number of additional class specific descriptors
+	uint8_t		bDescrType;				// Type of class descriptor
+    uint16_t	wDescriptorLength;		// Total size of the Report descriptor
+} USB_HID_DESCRIPTOR;
+
+typedef struct {
+	uint8_t		bDescrType;				// Type of class descriptor
+    uint16_t	wDescriptorLength;		// Total size of the Report descriptor
+} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
+
+_Pragma("pack()")
+
+#endif // _ch9_h_
+
diff --git a/libraries/USBHost/src/usbhub.cpp b/libraries/USBHost/src/usbhub.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a6aebd973272c2a29c30493de5b4de6c650f4b1e
--- /dev/null
+++ b/libraries/USBHost/src/usbhub.cpp
@@ -0,0 +1,426 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#include "usbhub.h"
+#include "delay.h"
+
+bool USBHub::bResetInitiated = false;
+
+USBHub::USBHub(USBHost *p) :
+pUsb(p),
+bAddress(0),
+bNbrPorts(0),
+//bInitState(0),
+qNextPollTime(0),
+bPollEnable(false) {
+        epInfo[0].epAddr = 0;
+        epInfo[0].maxPktSize = 8;
+        epInfo[0].epAttribs = 0;
+        epInfo[0].bmNakPower = USB_NAK_MAX_POWER;
+
+        epInfo[1].epAddr = 1;
+        epInfo[1].maxPktSize = 8; //kludge
+        epInfo[1].epAttribs = 0;
+        epInfo[1].bmNakPower = USB_NAK_NOWAIT;
+
+        if(pUsb)
+                pUsb->RegisterDeviceClass(this);
+}
+
+uint32_t USBHub::Init(uint32_t parent, uint32_t port, uint32_t lowspeed) {
+        uint8_t buf[32];
+        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+        HubDescriptor* hd = reinterpret_cast<HubDescriptor*>(buf);
+        USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(buf);
+        uint32_t rcode;
+        UsbDeviceDefinition *p = NULL;
+        EpInfo *oldep_ptr = NULL;
+        uint32_t len = 0;
+        uint32_t cd_len = 0;
+
+        //USBTRACE("\r\nHub Init Start ");
+        //D_PrintHex<uint8_t > (bInitState, 0x80);
+
+        AddressPool &addrPool = pUsb->GetAddressPool();
+
+        //switch (bInitState) {
+        //        case 0:
+        if(bAddress)
+                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+        // Get pointer to pseudo device with address 0 assigned
+        p = addrPool.GetUsbDevicePtr(0);
+
+        if(!p)
+                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+        if(!p->epinfo)
+                return USB_ERROR_EPINFO_IS_NULL;
+
+        // Save old pointer to EP_RECORD of address 0
+        oldep_ptr = p->epinfo;
+
+        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+        p->epinfo = epInfo;
+
+        p->lowspeed = lowspeed;
+
+        // Get device descriptor
+        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
+
+        p->lowspeed = false;
+
+        if(!rcode)
+                len = (buf[0] > 32) ? 32 : buf[0];
+
+        if(rcode) {
+                // Restore p->epinfo
+                p->epinfo = oldep_ptr;
+                return rcode;
+        }
+
+        // Extract device class from device descriptor
+        // If device class is not a hub return
+        if(udd->bDeviceClass != 0x09)
+                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+        // Allocate new address according to device class
+        bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port);
+
+        if(!bAddress)
+                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+        // Extract Max Packet Size from the device descriptor
+        epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+        // Assign new address to the device
+        rcode = pUsb->setAddr(0, 0, bAddress);
+
+        if(rcode) {
+                // Restore p->epinfo
+                p->epinfo = oldep_ptr;
+                addrPool.FreeAddress(bAddress);
+                bAddress = 0;
+                return rcode;
+        }
+
+        //USBTRACE2("\r\nHub address: ", bAddress );
+
+        // Restore p->epinfo
+        p->epinfo = oldep_ptr;
+
+        if(len)
+                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
+
+        if(rcode)
+                goto FailGetDevDescr;
+
+        // Assign epInfo to epinfo pointer
+        rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);
+
+        if(rcode)
+                goto FailSetDevTblEntry;
+
+        //                bInitState = 1;
+
+        //        case 1:
+        // Get hub descriptor
+        rcode = GetHubDescriptor(0, 8, buf);
+
+        if(rcode)
+                goto FailGetHubDescr;
+
+        // Save number of ports for future use
+        bNbrPorts = hd->bNbrPorts;
+
+        //                bInitState = 2;
+
+        //        case 2:
+        // Read configuration Descriptor in Order To Obtain Proper Configuration Value
+        rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
+
+        if(!rcode) {
+                cd_len = ucd->wTotalLength;
+                rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
+        }
+        if(rcode)
+                goto FailGetConfDescr;
+
+        // The following code is of no practical use in real life applications.
+        // It only intended for the usb protocol sniffer to properly parse hub-class requests.
+        {
+                uint8_t buf2[24];
+
+                rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2);
+
+                if(rcode)
+                        goto FailGetConfDescr;
+        }
+
+        // Set Configuration Value
+        rcode = pUsb->setConf(bAddress, 0, buf[5]);
+
+        if(rcode)
+                goto FailSetConfDescr;
+
+        //                bInitState = 3;
+
+        //        case 3:
+        // Power on all ports
+        for(uint32_t j = 1; j <= bNbrPorts; j++)
+                SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j);
+
+        pUsb->SetHubPreMask();
+        bPollEnable = true;
+        //                bInitState = 0;
+        //}
+        //bInitState = 0;
+        //USBTRACE("...OK\r\n");
+        return 0;
+
+        // Oleg, No debugging?? -- xxxajk
+FailGetDevDescr:
+        goto Fail;
+
+FailSetDevTblEntry:
+        goto Fail;
+
+FailGetHubDescr:
+        goto Fail;
+
+FailGetConfDescr:
+        goto Fail;
+
+FailSetConfDescr:
+        goto Fail;
+
+Fail:
+        USBTRACE("...FAIL\r\n");
+        return rcode;
+}
+
+uint32_t USBHub::Release() {
+        pUsb->GetAddressPool().FreeAddress(bAddress);
+
+        if(bAddress == 0x41)
+                pUsb->SetHubPreMask();
+
+        bAddress = 0;
+        bNbrPorts = 0;
+        qNextPollTime = 0;
+        bPollEnable = false;
+        return 0;
+}
+
+uint32_t USBHub::Poll() {
+        uint32_t rcode = 0;
+
+        if(!bPollEnable)
+                return 0;
+
+        if(((long)(millis() - qNextPollTime) >= 0L)) {
+                rcode = CheckHubStatus();
+                qNextPollTime = millis() + 100;
+        }
+        return rcode;
+}
+
+uint32_t USBHub::CheckHubStatus() {
+        uint32_t rcode;
+        uint8_t buf[8];
+        uint32_t read = 1;
+
+        rcode = pUsb->inTransfer(bAddress, 1, (uint8_t*)&read, buf);
+
+        if(rcode)
+                return rcode;
+
+        //if (buf[0] & 0x01) // Hub Status Change
+        //{
+        //        pUsb->PrintHubStatus(addr);
+        //        rcode = GetHubStatus(1, 0, 1, 4, buf);
+        //        if (rcode)
+        //        {
+        //        	USB_HOST_SERIAL.print("GetHubStatus Error");
+        //        	USB_HOST_SERIAL.println(rcode, HEX);
+        //        	return rcode;
+        //        }
+        //}
+        for(uint32_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) {
+                if(buf[0] & mask) {
+                        HubEvent evt;
+                        evt.bmEvent = 0;
+
+                        rcode = GetPortStatus(port, 4, evt.evtBuff);
+
+                        if(rcode)
+                                continue;
+
+                        rcode = PortStatusChange(port, evt);
+
+                        if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
+                                return 0;
+
+                        if(rcode)
+                                return rcode;
+                }
+        } // for
+
+        for(uint32_t port = 1; port <= bNbrPorts; port++) {
+                HubEvent evt;
+                evt.bmEvent = 0;
+
+                rcode = GetPortStatus(port, 4, evt.evtBuff);
+
+                if(rcode)
+                        continue;
+
+                if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED)
+                        continue;
+
+                // Emulate connection event for the port
+                evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION;
+
+                rcode = PortStatusChange(port, evt);
+
+                if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
+                        return 0;
+
+                if(rcode)
+                        return rcode;
+        } // for
+        return 0;
+}
+
+void USBHub::ResetHubPort(uint32_t port) {
+        HubEvent evt;
+        evt.bmEvent = 0;
+        uint8_t rcode;
+
+        ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
+        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+        SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
+
+
+        for(int i = 0; i < 3; i++) {
+                rcode = GetPortStatus(port, 4, evt.evtBuff);
+                if(rcode) break; // Some kind of error, bail.
+                if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) {
+                        break;
+                }
+                delay(100); // simulate polling.
+        }
+        ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);
+        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+        delay(20);
+}
+
+uint32_t USBHub::PortStatusChange(uint32_t port, HubEvent &evt) {
+        switch(evt.bmEvent) {
+                        // Device connected event
+                case bmHUB_PORT_EVENT_CONNECT:
+                case bmHUB_PORT_EVENT_LS_CONNECT:
+                        if(bResetInitiated)
+                                return 0;
+
+                        ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
+                        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+                        SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
+                        bResetInitiated = true;
+                        return HUB_ERROR_PORT_HAS_BEEN_RESET;
+
+                        // Device disconnected event
+                case bmHUB_PORT_EVENT_DISCONNECT:
+                        ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
+                        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+                        bResetInitiated = false;
+
+                        UsbDeviceAddress a;
+                        a.devAddress = 0;
+                        a.bmHub = 0;
+                        a.bmParent = bAddress;
+                        a.bmAddress = port;
+                        pUsb->ReleaseDevice(a.devAddress);
+                        return 0;
+
+                        // Reset complete event
+                case bmHUB_PORT_EVENT_RESET_COMPLETE:
+                case bmHUB_PORT_EVENT_LS_RESET_COMPLETE:
+                        ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);
+                        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+
+                        delay(20);
+
+                        a.devAddress = bAddress;
+
+                        pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED));
+                        bResetInitiated = false;
+                        break;
+
+        } // switch (evt.bmEvent)
+        return 0;
+}
+
+void PrintHubPortStatus(USBHub *hubptr, uint32_t addr, uint32_t port, uint32_t print_changes) {
+        uint8_t rcode = 0;
+        HubEvent evt;
+
+        rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);
+
+        if(rcode) {
+                USB_HOST_SERIAL.println("ERROR!");
+                return;
+        }
+        USB_HOST_SERIAL.print("\r\nPort ");
+        USB_HOST_SERIAL.println(port, DEC);
+
+        USB_HOST_SERIAL.println("Status");
+        USB_HOST_SERIAL.print("CONNECTION:\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC);
+        USB_HOST_SERIAL.print("ENABLE:\t\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC);
+        USB_HOST_SERIAL.print("SUSPEND:\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC);
+        USB_HOST_SERIAL.print("OVER_CURRENT:\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC);
+        USB_HOST_SERIAL.print("RESET:\t\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC);
+        USB_HOST_SERIAL.print("POWER:\t\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC);
+        USB_HOST_SERIAL.print("LOW_SPEED:\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC);
+        USB_HOST_SERIAL.print("HIGH_SPEED:\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC);
+        USB_HOST_SERIAL.print("TEST:\t\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC);
+        USB_HOST_SERIAL.print("INDICATOR:\t");
+        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);
+
+        if(!print_changes)
+                return;
+
+        USB_HOST_SERIAL.println("\r\nChange");
+        USB_HOST_SERIAL.print("CONNECTION:\t");
+        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
+        USB_HOST_SERIAL.print("ENABLE:\t\t");
+        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC);
+        USB_HOST_SERIAL.print("SUSPEND:\t");
+        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC);
+        USB_HOST_SERIAL.print("OVER_CURRENT:\t");
+        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC);
+        USB_HOST_SERIAL.print("RESET:\t\t");
+        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC);
+}
diff --git a/libraries/USBHost/src/usbhub.h b/libraries/USBHost/src/usbhub.h
new file mode 100644
index 0000000000000000000000000000000000000000..a785f9a189934c9c8dea9f732b2e2ca770e53f99
--- /dev/null
+++ b/libraries/USBHost/src/usbhub.h
@@ -0,0 +1,252 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#if !defined(__USBHUB_H__)
+#define __USBHUB_H__
+
+#include "Usb.h"
+
+#define USB_DESCRIPTOR_HUB			0x09 // Hub descriptor type
+
+// Hub Requests
+#define bmREQ_CLEAR_HUB_FEATURE                 USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_CLEAR_PORT_FEATURE                USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_CLEAR_TT_BUFFER                   USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_GET_HUB_DESCRIPTOR                USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_GET_HUB_STATUS                    USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_GET_PORT_STATUS                   USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_RESET_TT                          USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_SET_HUB_DESCRIPTOR                USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_SET_HUB_FEATURE                   USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_SET_PORT_FEATURE                  USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_GET_TT_STATE                      USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_STOP_TT                           USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+
+// Hub Class Requests
+#define HUB_REQUEST_CLEAR_TT_BUFFER             8
+#define HUB_REQUEST_RESET_TT                    9
+#define HUB_REQUEST_GET_TT_STATE                10
+#define HUB_REQUEST_STOP_TT                     11
+
+// Hub Features
+#define HUB_FEATURE_C_HUB_LOCAL_POWER           0
+#define HUB_FEATURE_C_HUB_OVER_CURRENT          1
+#define HUB_FEATURE_PORT_CONNECTION             0
+#define HUB_FEATURE_PORT_ENABLE                 1
+#define HUB_FEATURE_PORT_SUSPEND                2
+#define HUB_FEATURE_PORT_OVER_CURRENT           3
+#define HUB_FEATURE_PORT_RESET                  4
+#define HUB_FEATURE_PORT_POWER                  8
+#define HUB_FEATURE_PORT_LOW_SPEED              9
+#define HUB_FEATURE_C_PORT_CONNECTION           16
+#define HUB_FEATURE_C_PORT_ENABLE               17
+#define HUB_FEATURE_C_PORT_SUSPEND              18
+#define HUB_FEATURE_C_PORT_OVER_CURRENT         19
+#define HUB_FEATURE_C_PORT_RESET                20
+#define HUB_FEATURE_PORT_TEST                   21
+#define HUB_FEATURE_PORT_INDICATOR              22
+
+// Hub Port Test Modes
+#define HUB_PORT_TEST_MODE_J                    1
+#define HUB_PORT_TEST_MODE_K                    2
+#define HUB_PORT_TEST_MODE_SE0_NAK              3
+#define HUB_PORT_TEST_MODE_PACKET               4
+#define HUB_PORT_TEST_MODE_FORCE_ENABLE         5
+
+// Hub Port Indicator Color
+#define HUB_PORT_INDICATOR_AUTO                 0
+#define HUB_PORT_INDICATOR_AMBER                1
+#define HUB_PORT_INDICATOR_GREEN                2
+#define HUB_PORT_INDICATOR_OFF                  3
+
+// Hub Port Status Bitmasks
+#define bmHUB_PORT_STATUS_PORT_CONNECTION	0x0001
+#define bmHUB_PORT_STATUS_PORT_ENABLE		0x0002
+#define bmHUB_PORT_STATUS_PORT_SUSPEND		0x0004
+#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT	0x0008
+#define bmHUB_PORT_STATUS_PORT_RESET		0x0010
+#define bmHUB_PORT_STATUS_PORT_POWER		0x0100
+#define bmHUB_PORT_STATUS_PORT_LOW_SPEED	0x0200
+#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED	0x0400
+#define bmHUB_PORT_STATUS_PORT_TEST		0x0800
+#define bmHUB_PORT_STATUS_PORT_INDICATOR	0x1000
+
+// Hub Port Status Change Bitmasks (used one byte instead of two)
+#define bmHUB_PORT_STATUS_C_PORT_CONNECTION	0x0001
+#define bmHUB_PORT_STATUS_C_PORT_ENABLE		0x0002
+#define bmHUB_PORT_STATUS_C_PORT_SUSPEND	0x0004
+#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT	0x0008
+#define bmHUB_PORT_STATUS_C_PORT_RESET		0x0010
+
+// Hub Status Bitmasks (used one byte instead of two)
+#define bmHUB_STATUS_LOCAL_POWER_SOURCE		0x01
+#define bmHUB_STATUS_OVER_CURRENT		0x12
+
+// Hub Status Change Bitmasks (used one byte instead of two)
+#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE	0x01
+#define bmHUB_STATUS_C_OVER_CURRENT		0x12
+
+
+// Hub Port Configuring Substates
+#define USB_STATE_HUB_PORT_CONFIGURING		0xb0
+#define USB_STATE_HUB_PORT_POWERED_OFF		0xb1
+#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD	0xb2
+#define USB_STATE_HUB_PORT_DISCONNECTED		0xb3
+#define USB_STATE_HUB_PORT_DISABLED		0xb4
+#define USB_STATE_HUB_PORT_RESETTING		0xb5
+#define USB_STATE_HUB_PORT_ENABLED		0xb6
+
+// Additional Error Codes
+#define HUB_ERROR_PORT_HAS_BEEN_RESET		0xb1
+
+// The bit mask to check for all necessary state bits
+#define bmHUB_PORT_STATUS_ALL_MAIN		((0UL  | bmHUB_PORT_STATUS_C_PORT_CONNECTION  | bmHUB_PORT_STATUS_C_PORT_ENABLE  | bmHUB_PORT_STATUS_C_PORT_SUSPEND  | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
+
+// Bit mask to check for DISABLED state in HubEvent::bmStatus field
+#define bmHUB_PORT_STATE_CHECK_DISABLED		(0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
+
+// Hub Port States
+#define bmHUB_PORT_STATE_DISABLED		(0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
+
+// Hub Port Events
+#define bmHUB_PORT_EVENT_CONNECT		(((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION)	<< 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
+#define bmHUB_PORT_EVENT_DISCONNECT		(((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION)	<< 16) | bmHUB_PORT_STATUS_PORT_POWER)
+#define bmHUB_PORT_EVENT_RESET_COMPLETE		(((0UL | bmHUB_PORT_STATUS_C_PORT_RESET)		<< 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
+
+#define bmHUB_PORT_EVENT_LS_CONNECT		(((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION)	<< 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
+#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE	(((0UL | bmHUB_PORT_STATUS_C_PORT_RESET)		<< 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
+#define bmHUB_PORT_EVENT_LS_PORT_ENABLED	(((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE)		<< 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
+
+struct HubDescriptor {
+        uint32_t bDescLength; // descriptor length
+        uint32_t bDescriptorType; // descriptor type
+        uint32_t bNbrPorts; // number of ports a hub equiped with
+
+        struct {
+                uint32_t LogPwrSwitchMode : 2;
+                uint32_t CompoundDevice : 1;
+                uint32_t OverCurrentProtectMode : 2;
+                uint32_t TTThinkTime : 2;
+                uint32_t PortIndicatorsSupported : 1;
+                uint32_t Reserved : 24;
+        } __attribute__((packed));
+
+        uint32_t bPwrOn2PwrGood;
+        uint32_t bHubContrCurrent;
+} __attribute__((packed));
+
+struct HubEvent {
+
+        union {
+
+                struct {
+                        uint32_t bmStatus; // port status bits
+                        uint32_t bmChange; // port status change bits
+                } __attribute__((packed));
+                uint32_t bmEvent;
+                uint8_t evtBuff[4];
+        };
+} __attribute__((packed));
+
+class USBHub : USBDeviceConfig {
+        static bool bResetInitiated; // True when reset is triggered
+
+        USBHost *pUsb; // USB class instance pointer
+
+        EpInfo epInfo[2]; // interrupt endpoint info structure
+
+        uint32_t bAddress; // address
+        uint32_t bNbrPorts; // number of ports
+        //        uint8_t bInitState; // initialization state variable
+        uint32_t qNextPollTime; // next poll time
+        uint32_t bPollEnable; // poll enable flag
+
+        uint32_t CheckHubStatus();
+        uint32_t PortStatusChange(uint32_t port, HubEvent &evt);
+
+public:
+        USBHub(USBHost *p);
+
+        uint32_t ClearHubFeature(uint32_t fid);
+        uint32_t ClearPortFeature(uint32_t fid, uint32_t port, uint32_t sel = 0);
+        uint32_t GetHubDescriptor(uint32_t index, uint32_t nbytes, uint8_t *dataptr);
+        uint32_t GetHubStatus(uint32_t nbytes, uint8_t* dataptr);
+        uint32_t GetPortStatus(uint32_t port, uint32_t nbytes, uint8_t* dataptr);
+        uint32_t SetHubDescriptor(uint32_t port, uint32_t nbytes, uint8_t* dataptr);
+        uint32_t SetHubFeature(uint32_t fid);
+        uint32_t SetPortFeature(uint32_t fid, uint32_t port, uint32_t sel = 0);
+
+        void PrintHubStatus();
+
+        virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
+        virtual uint32_t Release();
+        virtual uint32_t Poll();
+        virtual void ResetHubPort(uint32_t port);
+
+        virtual uint32_t GetAddress() {
+                return bAddress;
+        };
+
+        virtual uint32_t DEVCLASSOK(uint32_t klass) {
+                return (klass == 0x09);
+        }
+
+};
+
+// Clear Hub Feature
+
+inline uint32_t USBHub::ClearHubFeature(uint32_t fid) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
+}
+// Clear Port Feature
+
+inline uint32_t USBHub::ClearPortFeature(uint32_t fid, uint32_t port, uint32_t sel) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
+}
+// Get Hub Descriptor
+
+inline uint32_t USBHub::GetHubDescriptor(uint32_t index, uint32_t nbytes, uint8_t *dataptr) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
+}
+// Get Hub Status
+
+inline uint32_t USBHub::GetHubStatus(uint32_t nbytes, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
+}
+// Get Port Status
+
+inline uint32_t USBHub::GetPortStatus(uint32_t port, uint32_t nbytes, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
+}
+// Set Hub Descriptor
+
+inline uint32_t USBHub::SetHubDescriptor(uint32_t port, uint32_t nbytes, uint8_t* dataptr) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
+}
+// Set Hub Feature
+
+inline uint32_t USBHub::SetHubFeature(uint32_t fid) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
+}
+// Set Port Feature
+
+inline uint32_t USBHub::SetPortFeature(uint32_t fid, uint32_t port, uint32_t sel) {
+        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
+}
+
+void PrintHubPortStatus(USBHost *usbptr, uint32_t addr, uint32_t port, uint32_t print_changes = false);
+
+#endif // __USBHUB_H__
diff --git a/variants/arduino_zero/variant.h b/variants/arduino_zero/variant.h
index d414ff2b6664b7865ea262411ca367e78aa7bef4..2853525d0bf8a473435af0191bf2048b417b5f76 100644
--- a/variants/arduino_zero/variant.h
+++ b/variants/arduino_zero/variant.h
@@ -230,7 +230,7 @@ extern Uart Serial5;
 //
 // SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
 //                            pins are NOT connected to anything by default.
-#define SERIAL_PORT_MONITOR         Serial
+#define SERIAL_PORT_MONITOR         Serial5
 #define SERIAL_PORT_USBVIRTUAL      SerialUSB
 #define SERIAL_PORT_HARDWARE_OPEN   Serial1
 #define SERIAL_PORT_HARDWARE_OPEN1  Serial2