ADC Niose test Connect four analog signals to your MBED. and then run the Windows app. The four traces are displayed on an oscilloscope like display. I have used a USB HID DEVICE link, so connections to D+, D- are required. The MBED code is otherwise quite basic, So you can modify it to your own test needs. Additionaly, there is a 16 bit count value, in my MBED code Mainly to test if MSB & LSB are correct.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
ceri
Date:
Sat Nov 19 22:54:22 2011 +0000
Commit message:
just enough to work

Changed in this revision

HID/USBBusInterface.h Show annotated file Show diff for this revision Revisions of this file
HID/USBBusInterface_LPC11U.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBBusInterface_LPC17_LPC23.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBDescriptor.h Show annotated file Show diff for this revision Revisions of this file
HID/USBDevice.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBDevice.h Show annotated file Show diff for this revision Revisions of this file
HID/USBDevice_Types.h Show annotated file Show diff for this revision Revisions of this file
HID/USBEndpoints.h Show annotated file Show diff for this revision Revisions of this file
HID/USBEndpoints_LPC11U.h Show annotated file Show diff for this revision Revisions of this file
HID/USBEndpoints_LPC17_LPC23.h Show annotated file Show diff for this revision Revisions of this file
HID/USBHID.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBHID.h Show annotated file Show diff for this revision Revisions of this file
HID/USBHID_Types.h Show annotated file Show diff for this revision Revisions of this file
HID/USBKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBKeyboard.h Show annotated file Show diff for this revision Revisions of this file
HID/USBMouse.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBMouse.h Show annotated file Show diff for this revision Revisions of this file
HID/USBMouseKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
HID/USBMouseKeyboard.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBBusInterface.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,59 @@
+/* USBBusInterface.h */
+/* USB Bus Interface */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBBUSINTERFACE_H
+#define USBBUSINTERFACE_H
+
+#include "mbed.h"
+#include "USBEndpoints.h"
+
+class USBHAL {
+public:
+    /* Configuration */
+	USBHAL();
+	~USBHAL();
+    void connect(void);
+    void disconnect(void);
+    void configureDevice(void);
+    void unconfigureDevice(void);
+    void setAddress(uint8_t address);
+    void remoteWakeup(void);
+
+    /* Endpoint 0 */
+    void EP0setup(uint8_t *buffer);
+    void EP0read(void);
+    uint32_t EP0getReadResult(uint8_t *buffer);
+    void EP0write(uint8_t *buffer, uint32_t size);
+    void EP0getWriteResult(void);
+    void EP0stall(void);
+
+    /* Other endpoints */
+    EP_STATUS endpointRead(uint8_t endpoint, uint32_t maximumSize);
+    EP_STATUS endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead);
+    EP_STATUS endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size);
+    EP_STATUS endpointWriteResult(uint8_t endpoint);
+    void stallEndpoint(uint8_t endpoint);
+    void unstallEndpoint(uint8_t endpoint);
+    bool realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options);
+    bool getEndpointStallState(unsigned char endpoint);
+    
+protected:
+    virtual void busReset(void){};
+    virtual void EP0setupCallback(void){};
+    virtual void EP0out(void){};
+    virtual void EP0in(void){};
+    virtual void connectStateChanged(unsigned int connected){};
+    virtual void suspendStateChanged(unsigned int suspended){};
+    void SOF(int frameNumber){};
+    virtual bool EPBULK_OUT_callback(){return false;};
+    virtual bool EPBULK_IN_callback(){return false;};
+    
+private:
+    void usbisr(void);
+    static void _usbisr(void);
+    static USBHAL * instance;
+};
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBBusInterface_LPC11U.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,660 @@
+// USBBusInterface_LPC11U.c
+// USB Bus Interface for NXP LPC11Uxx
+// Copyright (c) 2011 ARM Limited. All rights reserved.
+
+// Reference:
+// NXP UM10462 LPC11U1x User manual Rev. 1 � 14 April 2011
+
+#ifdef TARGET_LPC11U24
+
+#include "USBBusInterface.h"
+
+USBHAL * USBHAL::instance;
+
+
+// Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
+#define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Convert physical to logical
+#define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// USB RAM
+#define USB_RAM_START (0x20004000)
+#define USB_RAM_SIZE  (0x00000800)
+
+// SYSAHBCLKCTRL
+#define CLK_USB     (1UL<<14)
+#define CLK_USBRAM  (1UL<<27)
+
+// USB Information register
+#define FRAME_NR(a)     ((a) & 0x7ff)   // Frame number
+
+// USB Device Command/Status register
+#define DEV_ADDR_MASK   (0x7f)          // Device address
+#define DEV_ADDR(a)     ((a) & DEV_ADDR_MASK)
+#define DEV_EN          (1UL<<7)        // Device enable
+#define SETUP           (1UL<<8)        // SETUP token received
+#define PLL_ON          (1UL<<9)        // PLL enabled in suspend
+#define DCON            (1UL<<16)       // Device status - connect
+#define DSUS            (1UL<<17)       // Device status - suspend
+#define DCON_C          (1UL<<24)       // Connect change
+#define DSUS_C          (1UL<<25)       // Suspend change
+#define DRES_C          (1UL<<26)       // Reset change
+#define VBUSDEBOUNCED   (1UL<<28)       // Vbus detected
+
+// Endpoint Command/Status list
+#define CMDSTS_A                 (1UL<<31)          // Active
+#define CMDSTS_D                 (1UL<<30)          // Disable
+#define CMDSTS_S                 (1UL<<29)          // Stall
+#define CMDSTS_TR                (1UL<<28)          // Toggle Reset
+#define CMDSTS_RF                (1UL<<27)          // Rate Feedback mode
+#define CMDSTS_TV                (1UL<<27)          // Toggle Value
+#define CMDSTS_T                 (1UL<<26)          // Endpoint Type
+#define CMDSTS_NBYTES(n)         (((n)&0x3ff)<<16)  // Number of bytes
+#define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff)  // Buffer start address
+
+#define BYTES_REMAINING(s)       (((s)>>16)&0x3ff)  // Bytes remaining after transfer
+
+// USB Non-endpoint interrupt sources
+#define FRAME_INT   (1UL<<30)
+#define DEV_INT     (1UL<<31)
+
+static int epComplete = 0;
+
+// One entry for a double-buffered logical endpoint in the endpoint
+// command/status list. Endpoint 0 is single buffered, out[1] is used
+// for the SETUP packet and in[1] is not used
+typedef __packed struct {
+	uint32_t out[2];
+	uint32_t in[2];
+} EP_COMMAND_STATUS;
+
+typedef __packed struct {
+	uint8_t out[MAX_PACKET_SIZE_EP0];
+	uint8_t in[MAX_PACKET_SIZE_EP0];
+	uint8_t setup[SETUP_PACKET_SIZE];
+} CONTROL_TRANSFER;
+
+typedef __packed struct {
+	uint32_t    maxPacket;
+	uint32_t    buffer[2];
+	uint32_t    options;
+} EP_STATE;
+
+static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
+
+// Pointer to the endpoint command/status list
+static EP_COMMAND_STATUS *ep = NULL;
+
+// Pointer to endpoint 0 data (IN/OUT and SETUP)
+static CONTROL_TRANSFER *ct = NULL;
+
+// Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
+// initiating a remote wakeup event.
+static volatile uint32_t devCmdStat;
+
+// Pointers used to allocate USB RAM
+static uint32_t usbRamPtr = USB_RAM_START;
+static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
+
+#define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
+
+void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
+void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
+	if (size > 0) {
+		do {
+			*dst++ = *src++;
+		} while (--size > 0);
+	}
+}
+
+
+USBHAL::USBHAL(void) {
+	NVIC_DisableIRQ(USB_IRQn);
+
+	// USB_VBUS input, Pull down, Hysteresis enabled
+	//LPC_IOCON->PIO0_3 = 0x00000029;
+	// nUSB_CONNECT output
+	LPC_IOCON->PIO0_6 = 0x00000001;
+
+	// Enable clocks (USB registers, USB RAM)
+	LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
+
+	// Ensure device disconnected (DCON not set)
+	LPC_USB->DEVCMDSTAT = 0;
+
+	// Device must be disconnected for at least 2.5uS
+	// to ensure that the USB host sees the device as
+	// disconnected if the target CPU is reset.
+	wait(0.3);
+
+
+	// Reserve space in USB RAM for endpoint command/status list
+	// Must be 256 byte aligned
+	usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
+	ep = (EP_COMMAND_STATUS *)usbRamPtr;
+	usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
+	LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
+
+	// Reserve space in USB RAM for Endpoint 0
+	// Must be 64 byte aligned
+	usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
+	ct = (CONTROL_TRANSFER *)usbRamPtr;
+	usbRamPtr += sizeof(CONTROL_TRANSFER);
+	LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
+
+	// Setup command/status list for EP0
+	ep[0].out[0] = 0;
+	ep[0].in[0] =  0;
+	ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
+
+	// Route all interrupts to IRQ, some can be routed to
+	// USB_FIQ if you wish.
+	LPC_USB->INTROUTING = 0;
+
+	// Set device address 0, enable USB device, no remote wakeup
+	devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
+	LPC_USB->DEVCMDSTAT = devCmdStat;
+
+	// Enable interrupts for device events and EP0
+	LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT);
+	instance = this;
+	NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
+	NVIC_EnableIRQ(USB_IRQn);
+}
+
+USBHAL::~USBHAL(void) {
+	// Ensure device disconnected (DCON not set)
+	LPC_USB->DEVCMDSTAT = 0;
+
+	// Disable USB interrupts
+	NVIC_DisableIRQ(USB_IRQn);
+}
+
+void USBHAL::connect(void) {
+	devCmdStat |= DCON;
+	LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+void USBHAL::disconnect(void) {
+	devCmdStat &= ~DCON;
+	LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+void USBHAL::configureDevice(void) {
+}
+
+void USBHAL::unconfigureDevice(void) {
+}
+
+void USBHAL::EP0setup(uint8_t *buffer) {
+	// Copy setup packet data
+	USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
+}
+
+void USBHAL::EP0read(void) {
+	// Start an endpoint 0 read
+
+	// The USB ISR will call USBDevice_EP0out() when a packet has been read,
+	// the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
+	// read the data.
+
+	ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
+			| CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
+	// Complete an endpoint 0 read
+	uint32_t bytesRead;
+
+	// Find how many bytes were read
+	bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
+
+	// Copy data
+	USBMemCopy(buffer, ct->out, bytesRead);
+	return bytesRead;
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
+	// Start and endpoint 0 write
+
+	// The USB ISR will call USBDevice_EP0in() when the data has
+	// been written, the USBDevice layer then calls
+	// USBBusInterface_EP0getWriteResult() to complete the transaction.
+
+	// Copy data
+	USBMemCopy(ct->in, buffer, size);
+
+	// Start transfer
+	ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
+			| CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
+}
+
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+	ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
+			| CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
+	return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
+	if (!(epComplete & EP(endpoint)))
+		return EP_PENDING;
+	else {
+		epComplete &= ~EP(endpoint);
+		// Find how many bytes were read
+		*bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[0]));
+		// Copy data
+		USBMemCopy(data, ct->out, *bytesRead);
+		return EP_COMPLETED;
+	}
+}
+
+void USBHAL::EP0getWriteResult(void) {
+	// Complete an endpoint 0 write
+
+	// Nothing required for this target
+	return;
+}
+
+void USBHAL::EP0stall(void) {
+	ep[0].in[0] = CMDSTS_S;
+	ep[0].out[0] = CMDSTS_S;
+}
+
+void USBHAL::setAddress(uint8_t address) {
+	devCmdStat &= ~DEV_ADDR_MASK;
+	devCmdStat |= DEV_ADDR(address);
+	LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+	uint32_t flags = 0;
+	uint32_t bf;
+
+	// Validate parameters
+	if (data == NULL) {
+		return EP_INVALID;
+	}
+
+	if (endpoint > LAST_PHYSICAL_ENDPOINT) {
+		return EP_INVALID;
+	}
+
+	if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
+		return EP_INVALID;
+	}
+
+	if (size > endpointState[endpoint].maxPacket) {
+		return EP_INVALID;
+	}
+
+	if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+		// Double buffered  // TODO: FIX THIS
+		if (LPC_USB->EPINUSE & EP(endpoint)) {
+			bf = 1;
+		} else {
+			bf = 0;
+		}
+	} else {
+		// Single buffered
+		bf = 0;
+	}
+
+	// Check if already active
+	if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
+		return EP_INVALID;
+	}
+
+	// Check if stalled
+	if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
+		return EP_STALLED;
+	}
+
+	// Copy data to USB RAM
+	USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
+
+	// Add options
+	if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
+		flags |= CMDSTS_RF;
+	}
+
+	if (endpointState[endpoint].options & ISOCHRONOUS) {
+		flags |= CMDSTS_T;
+	}
+
+	// Add transfer
+	ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
+			endpointState[endpoint].buffer[bf]) \
+			| CMDSTS_NBYTES(size) | CMDSTS_A | flags;
+
+	return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+	uint32_t bf;
+	// Validate parameters
+
+	if (endpoint > LAST_PHYSICAL_ENDPOINT) {
+		return EP_INVALID;
+	}
+
+	if (OUT_EP(endpoint)) {
+		return EP_INVALID;
+	}
+
+	if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+		// Double buffered     // TODO: FIX THIS
+		if (LPC_USB->EPINUSE & EP(endpoint)) {
+			bf = 1;
+		} else {
+			bf = 0;
+		}
+	} else {
+		// Single buffered
+		bf = 0;
+	}
+
+	// Check if endpoint still active
+	if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
+		return EP_PENDING;
+	}
+
+	// Check if stalled
+	if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
+		return EP_STALLED;
+	}
+
+	return EP_COMPLETED;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint) {
+
+	// TODO: should this clear active bit?
+
+	if (IN_EP(endpoint)) {
+		ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
+		ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
+	} else {
+		ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
+		ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
+	}
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+	if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+		// Double buffered
+		if (IN_EP(endpoint)) {
+			ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
+			ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
+
+			if (LPC_USB->EPINUSE & EP(endpoint)) {
+				ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
+			} else {
+				ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
+			}
+		} else {
+			ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
+			ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
+
+			if (LPC_USB->EPINUSE & EP(endpoint)) {
+				ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
+			} else {
+				ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
+			}
+		}
+	} else {
+		// Single buffered
+		if (IN_EP(endpoint)) {
+			ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
+		} else {
+			ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
+		}
+	}
+}
+
+bool USBHAL::getEndpointStallState(unsigned char endpoint) {
+	if (IN_EP(endpoint)) {
+		if (LPC_USB->EPINUSE & EP(endpoint)) {
+			if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
+				return true;
+			}
+		} else {
+			if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
+				return true;
+			}
+		}
+	} else {
+		if (LPC_USB->EPINUSE & EP(endpoint)) {
+			if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
+				return true;
+			}
+		} else {
+			if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
+	uint32_t tmpEpRamPtr;
+
+	//  Support for double buffered endpoints needs to be fixed/finished in this
+	//  software - force single buffered for now.
+
+
+	options |= SINGLE_BUFFERED; // TODO - FIX THIS
+
+	if (endpoint > LAST_PHYSICAL_ENDPOINT) {
+		return false;
+	}
+
+	// Not applicable to the control endpoints
+	if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
+		return false;
+	}
+
+	// Allocate buffers in USB RAM
+	tmpEpRamPtr = epRamPtr;
+
+	// Must be 64 byte aligned
+	tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
+
+	if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
+		// Out of memory
+		return false;
+	}
+
+	// Allocate first buffer
+	endpointState[endpoint].buffer[0] = tmpEpRamPtr;
+	tmpEpRamPtr += maxPacket;
+
+	if (!(options & SINGLE_BUFFERED)) {
+		// Must be 64 byte aligned
+		tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
+
+		if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
+			// Out of memory
+			return false;
+		}
+
+		// Allocate second buffer
+		endpointState[endpoint].buffer[1] = tmpEpRamPtr;
+		tmpEpRamPtr += maxPacket;
+	}
+
+	// Commit to this USB RAM allocation
+	epRamPtr = tmpEpRamPtr;
+
+	// Remaining endpoint state values
+	endpointState[endpoint].maxPacket = maxPacket;
+	endpointState[endpoint].options = options;
+
+	// Enable double buffering if required
+	if (options & SINGLE_BUFFERED) {
+		LPC_USB->EPBUFCFG &= ~EP(endpoint);
+	} else {
+		// Double buffered
+		LPC_USB->EPBUFCFG |= EP(endpoint);
+	}
+
+	// Enable interrupt for OUT endpoint
+	LPC_USB->INTEN |= EP(endpoint);
+
+	// Enable endpoint
+	unstallEndpoint(endpoint);
+	return true;
+}
+
+void USBHAL::remoteWakeup(void) {
+	// Clearing DSUS bit initiates a remote wakeup if the
+	// device is currently enabled and suspended - otherwise
+	// it has no effect.
+	LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
+}
+
+
+static void disableEndpoints(void) {
+	uint32_t logEp;
+
+	// Ref. Table 158 "When a bus reset is received, software
+	// must set the disable bit of all endpoints to 1".
+
+	for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
+		ep[logEp].out[0] = CMDSTS_D;
+		ep[logEp].out[1] = CMDSTS_D;
+		ep[logEp].in[0] =  CMDSTS_D;
+		ep[logEp].in[1] =  CMDSTS_D;
+	}
+
+	// Start of USB RAM for endpoints > 0
+	epRamPtr = usbRamPtr;
+}
+
+
+
+void USBHAL::_usbisr(void)
+{
+	instance->usbisr();
+}
+
+
+void USBHAL::usbisr(void) {
+	// Start of frame
+	if (LPC_USB->INTSTAT & FRAME_INT) {
+		// Clear SOF interrupt
+		LPC_USB->INTSTAT = FRAME_INT;
+
+		// SOF event, read frame number
+		SOF(FRAME_NR(LPC_USB->INFO));
+	}
+
+	// Device state
+	if (LPC_USB->INTSTAT & DEV_INT) {
+		LPC_USB->INTSTAT = DEV_INT;
+
+		if (LPC_USB->DEVCMDSTAT & DCON_C) {
+			// Connect status changed
+			LPC_USB->DEVCMDSTAT = devCmdStat | DCON_C;
+
+			connectStateChanged((LPC_USB->DEVCMDSTAT & DCON) != 0);
+		}
+
+		if (LPC_USB->DEVCMDSTAT & DSUS_C) {
+			// Suspend status changed
+			LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
+
+			suspendStateChanged((LPC_USB->DEVCMDSTAT & DSUS) != 0);
+		}
+
+		if (LPC_USB->DEVCMDSTAT & DRES_C) {
+			// Bus reset
+			LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
+
+			// Disable endpoints > 0
+			disableEndpoints();
+
+			// Bus reset event
+			busReset();
+		}
+	}
+
+	// Endpoint 0
+	if (LPC_USB->INTSTAT & EP(EP0OUT)) {
+		// Clear EP0OUT/SETUP interrupt
+		LPC_USB->INTSTAT = EP(EP0OUT);
+
+		// Check if SETUP
+		if (LPC_USB->DEVCMDSTAT & SETUP) {
+			// Clear Active and Stall bits for EP0
+			// Documentation does not make it clear if we must use the
+			// EPSKIP register to achieve this, Fig. 16 and NXP reference
+			// code suggests we can just clear the Active bits - check with
+			// NXP to be sure.
+			ep[0].in[0] = 0;
+			ep[0].out[0] = 0;
+
+			// Clear EP0IN interrupt
+			LPC_USB->INTSTAT = EP(EP0IN);
+
+			// Clear SETUP (and INTONNAK_CI/O) in device status register
+			LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
+
+			// EP0 SETUP event (SETUP data received)
+			EP0setupCallback();
+		} else {
+			// EP0OUT ACK event (OUT data received)
+			EP0out();
+		}
+	}
+
+	if (LPC_USB->INTSTAT & EP(EP0IN)) {
+		// Clear EP0IN interrupt
+		LPC_USB->INTSTAT = EP(EP0IN);
+
+		// EP0IN ACK event (IN data sent)
+		EP0in();
+	}
+
+	if (LPC_USB->INTSTAT & EP(EP1IN)) {
+		// Clear EP1IN interrupt
+		LPC_USB->INTSTAT = EP(EP1IN);
+		epComplete |= EP(EP1IN);
+	}
+
+	if (LPC_USB->INTSTAT & EP(EP1OUT)) {
+		// Clear EP1OUT interrupt
+		LPC_USB->INTSTAT = EP(EP1OUT);
+		epComplete |= EP(EP1OUT);
+	}
+
+	if (LPC_USB->INTSTAT & EP(EPBULK_IN)) {
+		// Clear EPBULK_OUT interrupt
+		LPC_USB->INTSTAT = EP(EPBULK_IN);
+		epComplete |= EP(EPBULK_IN);
+		if(EPBULK_IN_callback())
+			epComplete &= ~EP(EPBULK_IN);
+	}
+
+	if (LPC_USB->INTSTAT & EP(EPBULK_OUT)) {
+		// Clear EPBULK_OUT interrupt
+		LPC_USB->INTSTAT = EP(EPBULK_OUT);
+		epComplete |= EP(EPBULK_OUT);
+		//Call callback function. If true, clear epComplete
+		if(EPBULK_OUT_callback())
+			epComplete &= ~EP(EPBULK_OUT);
+	}
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBBusInterface_LPC17_LPC23.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,675 @@
+// USBBusInterface_LPC17_LPC23.c
+// USB Bus Interface for NXP LPC1768 and LPC2368
+// Copyright (c) 2011 ARM Limited. All rights reserved.
+
+#ifdef TARGET_LPC1768
+
+#include "USBBusInterface.h"
+
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Power Control for Peripherals register
+#define PCUSB      (1UL<<31)
+
+// USB Clock Control register
+#define DEV_CLK_EN (1UL<<1)
+#define AHB_CLK_EN (1UL<<4)
+
+// USB Clock Status register
+#define DEV_CLK_ON (1UL<<1)
+#define AHB_CLK_ON (1UL<<4)
+
+// USB Device Interupt registers
+#define FRAME      (1UL<<0)
+#define EP_FAST    (1UL<<1)
+#define EP_SLOW    (1UL<<2)
+#define DEV_STAT   (1UL<<3)
+#define CCEMPTY    (1UL<<4)
+#define CDFULL     (1UL<<5)
+#define RxENDPKT   (1UL<<6)
+#define TxENDPKT   (1UL<<7)
+#define EP_RLZED   (1UL<<8)
+#define ERR_INT    (1UL<<9)
+
+// USB Control register
+#define RD_EN (1<<0)
+#define WR_EN (1<<1)
+#define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
+
+// USB Receive Packet Length register
+#define DV      (1UL<<10)
+#define PKT_RDY (1UL<<11)
+#define PKT_LNGTH_MASK (0x3ff)
+
+// Serial Interface Engine (SIE)
+#define SIE_WRITE   (0x01)
+#define SIE_READ    (0x02)
+#define SIE_COMMAND (0x05)
+#define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
+
+// SIE Command codes
+#define SIE_CMD_SET_ADDRESS        (0xD0)
+#define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
+#define SIE_CMD_SET_MODE           (0xF3)
+#define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
+#define SIE_CMD_READ_TEST_REGISTER (0xFD)
+#define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_ERROR_CODE     (0xFF)
+#define SIE_CMD_READ_ERROR_STATUS  (0xFB)
+
+#define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
+#define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
+#define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
+
+#define SIE_CMD_CLEAR_BUFFER    (0xF2)
+#define SIE_CMD_VALIDATE_BUFFER (0xFA)
+
+// SIE Device Status register
+#define SIE_DS_CON    (1<<0)
+#define SIE_DS_CON_CH (1<<1)
+#define SIE_DS_SUS    (1<<2)
+#define SIE_DS_SUS_CH (1<<3)
+#define SIE_DS_RST    (1<<4)
+
+// SIE Device Set Address register
+#define SIE_DSA_DEV_EN  (1<<7)
+
+// SIE Configue Device register
+#define SIE_CONF_DEVICE (1<<0)
+
+// Select Endpoint register
+#define SIE_SE_FE       (1<<0)
+#define SIE_SE_ST       (1<<1)
+#define SIE_SE_STP      (1<<2)
+#define SIE_SE_PO       (1<<3)
+#define SIE_SE_EPN      (1<<4)
+#define SIE_SE_B_1_FULL (1<<5)
+#define SIE_SE_B_2_FULL (1<<6)
+
+// Set Endpoint Status command
+#define SIE_SES_ST      (1<<0)
+#define SIE_SES_DA      (1<<5)
+#define SIE_SES_RF_MO   (1<<6)
+#define SIE_SES_CND_ST  (1<<7)
+
+
+USBHAL * USBHAL::instance;
+
+volatile int epComplete;
+uint32_t endpointStallState;
+
+static void SIECommand(uint32_t command)
+{
+	// The command phase of a SIE transaction
+	LPC_USB->USBDevIntClr = CCEMPTY;
+	LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
+	while (!(LPC_USB->USBDevIntSt & CCEMPTY));
+}
+
+static void SIEWriteData(uint8_t data)
+{
+	// The data write phase of a SIE transaction
+	LPC_USB->USBDevIntClr = CCEMPTY;
+	LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
+	while (!(LPC_USB->USBDevIntSt & CCEMPTY));
+}
+
+static uint8_t SIEReadData(uint32_t command)
+{
+	// The data read phase of a SIE transaction
+	LPC_USB->USBDevIntClr = CDFULL;
+	LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
+	while (!(LPC_USB->USBDevIntSt & CDFULL));
+	return (uint8_t)LPC_USB->USBCmdData;
+}
+
+static void SIEsetDeviceStatus(uint8_t status)
+{
+	// Write SIE device status register
+	SIECommand(SIE_CMD_SET_DEVICE_STATUS);
+	SIEWriteData(status);
+}
+
+static uint8_t SIEgetDeviceStatus(void)
+{
+	// Read SIE device status register
+	SIECommand(SIE_CMD_GET_DEVICE_STATUS);
+	return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
+}
+
+void SIEsetAddress(uint8_t address)
+{
+	// Write SIE device address register
+	SIECommand(SIE_CMD_SET_ADDRESS);
+	SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
+}
+
+static uint8_t SIEselectEndpoint(uint8_t endpoint)
+{
+	// SIE select endpoint command
+	SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
+	return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
+}
+
+static uint8_t SIEclearBuffer(void)
+{
+	// SIE clear buffer command
+	SIECommand(SIE_CMD_CLEAR_BUFFER);
+	return SIEReadData(SIE_CMD_CLEAR_BUFFER);
+}
+
+static void SIEvalidateBuffer(void)
+{
+	// SIE validate buffer command
+	SIECommand(SIE_CMD_VALIDATE_BUFFER);
+}
+
+static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status)
+{
+	// SIE set endpoint status command
+	SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
+	SIEWriteData(status);
+}
+
+static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
+static uint16_t SIEgetFrameNumber(void)
+{
+	// Read current frame number
+	uint16_t lowByte;
+	uint16_t highByte;
+
+	SIECommand(SIE_CMD_READ_FRAME_NUMBER);
+	lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
+	highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
+
+	return (highByte << 8) | lowByte;
+}
+
+static void SIEconfigureDevice(void)
+{
+	// SIE Configure device command
+	SIECommand(SIE_CMD_CONFIGURE_DEVICE);
+	SIEWriteData(SIE_CONF_DEVICE);
+}
+
+static void SIEunconfigureDevice(void)
+{
+	// SIE Configure device command
+	SIECommand(SIE_CMD_CONFIGURE_DEVICE);
+	SIEWriteData(0);
+}
+
+static void SIEconnect(void)
+{
+	// Connect USB device
+	uint8_t status;
+
+	status = SIEgetDeviceStatus();
+	SIEsetDeviceStatus(status | SIE_DS_CON);
+}
+
+
+static void SIEdisconnect(void)
+{
+	// Disconnect USB device
+	uint8_t status;
+
+	status = SIEgetDeviceStatus();
+	SIEsetDeviceStatus(status & ~SIE_DS_CON);
+}
+
+
+static uint8_t selectEndpointClearInterrupt(uint8_t endpoint)
+{
+	// Implemented using using EP_INT_CLR.
+	LPC_USB->USBEpIntClr = EP(endpoint);
+	while (!(LPC_USB->USBDevIntSt & CDFULL));
+	return (uint8_t)LPC_USB->USBCmdData;
+}
+
+
+
+
+
+static void enableEndpointEvent(uint8_t endpoint)
+{
+	// Enable an endpoint interrupt
+	LPC_USB->USBEpIntEn |= EP(endpoint);
+}
+
+static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
+static void disableEndpointEvent(uint8_t endpoint)
+{
+	// Disable an endpoint interrupt
+	LPC_USB->USBEpIntEn &= ~EP(endpoint);
+}
+
+static volatile uint32_t __attribute__((used)) dummyRead;
+
+
+static uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer)
+{
+	// Read from an OUT endpoint
+	uint32_t size;
+	uint32_t i;
+	uint32_t data = 0;
+	uint8_t offset;
+
+	LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
+	while (!(LPC_USB->USBRxPLen & PKT_RDY));
+
+	size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
+
+	offset = 0;
+
+	if (size > 0)
+	{
+		for (i=0; i<size; i++)
+		{
+			if (offset==0)
+			{
+				// Fetch up to four bytes of data as a word
+				data = LPC_USB->USBRxData;
+			}
+
+			// extract a byte
+			*buffer = (data>>offset) & 0xff;
+			buffer++;
+
+			// move on to the next byte
+			offset = (offset + 8) % 32;
+		}
+	}
+	else
+	{
+		dummyRead = LPC_USB->USBRxData;
+	}
+
+	SIEselectEndpoint(endpoint);
+	SIEclearBuffer();
+	return size;
+}
+
+static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size)
+{
+	// Write to an IN endpoint
+	uint32_t temp, data;
+	uint8_t offset;
+
+	LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
+
+	LPC_USB->USBTxPLen = size;
+	offset = 0;
+	data = 0;
+
+	if (size>0)
+	{
+		do {
+			// Fetch next data byte into a word-sized temporary variable
+			temp = *buffer++;
+
+			// Add to current data word
+			temp = temp << offset;
+			data = data | temp;
+
+			// move on to the next byte
+			offset = (offset + 8) % 32;
+			size--;
+
+			if ((offset==0) || (size==0))
+			{
+				// Write the word to the endpoint
+				LPC_USB->USBTxData = data;
+				data = 0;
+			}
+		} while (size>0);
+	}
+	else
+	{
+		LPC_USB->USBTxData = 0;
+	}
+
+	// Clear WR_EN to cover zero length packet case
+	LPC_USB->USBCtrl=0;
+
+	SIEselectEndpoint(endpoint);
+	SIEvalidateBuffer();
+}
+
+
+
+
+
+
+
+USBHAL::USBHAL(void)
+{
+	// Disable IRQ
+	NVIC_DisableIRQ(USB_IRQn);
+
+	// Enable power to USB device controller
+	LPC_SC->PCONP |= PCUSB;
+
+	// Enable USB clocks
+	LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+	while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
+
+	// Configure pins P0.29 and P0.30 to be USB D+ and USB D-
+	LPC_PINCON->PINSEL1 &= 0xc3ffffff;
+	LPC_PINCON->PINSEL1 |= 0x14000000;
+
+	// Disconnect USB device
+	SIEdisconnect();
+
+	// Configure pin P2.9 to be Connect
+	LPC_PINCON->PINSEL4 &= 0xfffcffff;
+	LPC_PINCON->PINSEL4 |= 0x00040000;
+
+	// Connect must be low for at least 2.5uS
+	wait(0.3);
+
+	// Set the maximum packet size for the control endpoints
+	realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
+	realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
+
+	// Attach IRQ
+	instance = this;
+	NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
+	NVIC_EnableIRQ(USB_IRQn);
+
+	// Enable interrupts for device events and EP0
+	LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
+	enableEndpointEvent(EP0IN);
+	enableEndpointEvent(EP0OUT);
+}
+
+USBHAL::~USBHAL(void)
+{
+	// Ensure device disconnected
+	SIEdisconnect();
+
+	// Disable USB interrupts
+	NVIC_DisableIRQ(USB_IRQn);
+}
+
+void USBHAL::connect(void)
+{
+	// Connect USB device
+	SIEconnect();
+}
+
+void USBHAL::disconnect(void)
+{
+	// Disconnect USB device
+	SIEdisconnect();
+}
+
+void USBHAL::configureDevice(void)
+{
+	SIEconfigureDevice();
+}
+
+void USBHAL::unconfigureDevice(void)
+{
+	SIEunconfigureDevice();
+}
+
+void USBHAL::setAddress(uint8_t address)
+{
+	SIEsetAddress(address);
+}
+
+void USBHAL::EP0setup(uint8_t *buffer)
+{
+	endpointReadcore(EP0OUT, buffer);
+}
+
+void USBHAL::EP0read(void)
+{
+	// Not required
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
+{
+	return endpointReadcore(EP0OUT, buffer);
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
+{
+	endpointWritecore(EP0IN, buffer, size);
+}
+
+void USBHAL::EP0getWriteResult(void)
+{
+	// Not required
+}
+
+void USBHAL::EP0stall(void)
+{
+	// This will stall both control endpoints
+	stallEndpoint(EP0OUT);
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
+{
+	return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead)
+{
+	if(!(epComplete & EP(endpoint)))
+		return EP_PENDING;
+	*bytesRead = endpointReadcore(endpoint, buffer);
+	epComplete &= ~EP(endpoint);
+	return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
+{
+	if (getEndpointStallState(endpoint))
+	{
+		return EP_STALLED;
+	}
+
+	epComplete &= ~EP(endpoint);
+
+	endpointWritecore(endpoint, data, size);
+	return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
+{
+	if (epComplete & EP(endpoint))
+	{
+		epComplete &= ~EP(endpoint);
+		return EP_COMPLETED;
+	}
+
+	return EP_PENDING;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags)
+{
+	// Realise an endpoint
+	LPC_USB->USBDevIntClr = EP_RLZED;
+	LPC_USB->USBReEp |= EP(endpoint);
+	LPC_USB->USBEpInd = endpoint;
+	LPC_USB->USBMaxPSize = maxPacket;
+
+	while (!(LPC_USB->USBDevIntSt & EP_RLZED));
+	LPC_USB->USBDevIntClr = EP_RLZED;
+
+	// Clear stall state
+	endpointStallState &= ~EP(endpoint);
+
+	enableEndpointEvent(endpoint);
+	return true;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint)
+{
+	// Stall an endpoint
+	if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
+	{
+		// Conditionally stall both control endpoints
+		SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
+	}
+	else
+	{
+		SIEsetEndpointStatus(endpoint, SIE_SES_ST);
+
+		// Update stall state
+		endpointStallState |= EP(endpoint);
+	}
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint)
+{
+	// Unstall an endpoint. The endpoint will also be reinitialised
+	SIEsetEndpointStatus(endpoint, 0);
+
+	// Update stall state
+	endpointStallState &= ~EP(endpoint);
+}
+
+bool USBHAL::getEndpointStallState(uint8_t endpoint)
+{
+	// Returns true if endpoint stalled
+	return endpointStallState & EP(endpoint);
+}
+
+void USBHAL::remoteWakeup(void)
+{
+	// Remote wakeup
+	uint8_t status;
+
+	// Enable USB clocks
+	LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+	while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
+
+	status = SIEgetDeviceStatus();
+	SIEsetDeviceStatus(status & ~SIE_DS_SUS);
+}
+
+
+
+
+
+void USBHAL::_usbisr(void)
+{
+	instance->usbisr();
+} 
+
+DigitalOut ledd(LED1);
+void USBHAL::usbisr(void)
+{ 
+	uint8_t devStat;
+
+	if (LPC_USB->USBDevIntSt & FRAME)
+	{
+		// Start of frame event
+		SOF(SIEgetFrameNumber());
+		// Clear interrupt status flag
+		LPC_USB->USBDevIntClr = FRAME;
+	}
+
+	if (LPC_USB->USBDevIntSt & DEV_STAT)
+	{
+		// Device Status interrupt
+		// Must clear the interrupt status flag before reading the device status from the SIE
+		LPC_USB->USBDevIntClr = DEV_STAT;
+
+		// Read device status from SIE
+		devStat = SIEgetDeviceStatus();
+
+		if (devStat & SIE_DS_RST)
+		{
+			// Bus reset
+			busReset();
+		}
+	}
+
+	if (LPC_USB->USBDevIntSt & EP_SLOW)
+	{
+		// (Slow) Endpoint Interrupt
+
+		// Process each endpoint interrupt
+		if (LPC_USB->USBEpIntSt & EP(EP0OUT))
+		{
+			if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
+			{
+				// this is a setup packet
+				EP0setupCallback();
+			}
+			else
+			{
+				EP0out();
+			}
+			LPC_USB->USBDevIntClr = EP_SLOW;
+		}
+
+		if (LPC_USB->USBEpIntSt & EP(EP0IN))
+		{
+			selectEndpointClearInterrupt(EP0IN);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+			EP0in();
+		}
+
+		// TODO: This should cover all endpoints, not just EP1,2,3:
+		if (LPC_USB->USBEpIntSt & EP(EP1IN))
+		{
+			selectEndpointClearInterrupt(EP1IN);
+			epComplete |= EP(EP1IN);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+		}
+
+		if (LPC_USB->USBEpIntSt & EP(EP1OUT))
+		{
+			selectEndpointClearInterrupt(EP1OUT);
+			epComplete |= EP(EP1OUT);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+		}
+
+		if (LPC_USB->USBEpIntSt & EP(EP2IN))
+		{
+			ledd = 1;
+			selectEndpointClearInterrupt(EP2IN);
+			epComplete |= EP(EP2IN);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+			if(EPBULK_IN_callback())
+				epComplete &= ~EP(EPBULK_OUT);
+		}
+
+		if (LPC_USB->USBEpIntSt & EP(EP2OUT))
+		{
+			selectEndpointClearInterrupt(EP2OUT);
+			epComplete |= EP(EP2OUT);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+			if(EPBULK_OUT_callback())
+				epComplete &= ~EP(EPBULK_OUT);
+		}
+
+		if (LPC_USB->USBEpIntSt & EP(EP3IN))
+		{
+			selectEndpointClearInterrupt(EP3IN);
+			epComplete |= EP(EP3IN);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+		}
+
+		if (LPC_USB->USBEpIntSt & EP(EP3OUT))
+		{
+			selectEndpointClearInterrupt(EP3OUT);
+			epComplete |= EP(EP3OUT);
+			LPC_USB->USBDevIntClr = EP_SLOW;
+		}
+	}
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBDescriptor.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,59 @@
+/* USBDescriptor.h */
+/* Definitions and macros for constructing USB descriptors */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+/* Standard descriptor types */
+#define DEVICE_DESCRIPTOR        (1)
+#define CONFIGURATION_DESCRIPTOR (2)
+#define STRING_DESCRIPTOR        (3)
+#define INTERFACE_DESCRIPTOR     (4)
+#define ENDPOINT_DESCRIPTOR      (5)
+
+/* Standard descriptor lengths */
+#define DEVICE_DESCRIPTOR_LENGTH        (0x12)
+#define CONFIGURATION_DESCRIPTOR_LENGTH (0x09)
+#define INTERFACE_DESCRIPTOR_LENGTH     (0x09)
+#define ENDPOINT_DESCRIPTOR_LENGTH      (0x07)
+
+
+/*string offset*/
+#define STRING_OFFSET_LANGID            (0) 
+#define STRING_OFFSET_IMANUFACTURER     (1)
+#define STRING_OFFSET_IPRODUCT          (2)
+#define STRING_OFFSET_ISERIAL           (3)
+#define STRING_OFFSET_ICONFIGURATION    (4)
+#define STRING_OFFSET_IINTERFACE        (5)
+
+/* USB Specification Release Number */
+#define USB_VERSION_2_0 (0x0200)
+
+/* Least/Most significant byte of short integer */
+#define LSB(n)  ((n)&0xff)
+#define MSB(n)  (((n)&0xff00)>>8)
+
+/* Convert physical endpoint number to descriptor endpoint number */
+#define PHY_TO_DESC(endpoint) (((endpoint)>>1) | (((endpoint) & 1) ? 0x80:0))
+
+/* bmAttributes in configuration descriptor */
+/* C_RESERVED must always be set */
+#define C_RESERVED      (1U<<7)
+#define C_SELF_POWERED  (1U<<6)
+#define C_REMOTE_WAKEUP (1U<<5)
+
+/* bMaxPower in configuration descriptor */
+#define C_POWER(mA)     ((mA)/2)
+
+/* bmAttributes in endpoint descriptor */
+#define E_CONTROL       (0x00)
+#define E_ISOCHRONOUS   (0x01)
+#define E_BULK          (0x02)
+#define E_INTERRUPT     (0x03)
+
+/* For isochronous endpoints only: */
+#define E_NO_SYNCHRONIZATION    (0x00)
+#define E_ASYNCHRONOUS          (0x04)
+#define E_ADAPTIVE              (0x08)
+#define E_SYNCHRONOUS           (0x0C)
+#define E_DATA                  (0x00)
+#define E_FEEDBACK              (0x10)
+#define E_IMPLICIT_FEEDBACK     (0x20)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBDevice.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,912 @@
+/* USBDevice.c */
+/* Generic USB device */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+/* Reference: */
+/* Universal Serial Bus Specification Revision 2.0, Chapter 9 "USB Device Framework" */
+
+#include "stdint.h"
+
+#include "USBEndpoints.h"
+#include "USBDevice.h"
+#include "USBDescriptor.h"
+#include "USBHID_Types.h"
+
+
+/* Device status */
+#define DEVICE_STATUS_SELF_POWERED  (1U<<0)
+#define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
+
+/* Endpoint status */
+#define ENDPOINT_STATUS_HALT        (1U<<0)
+
+/* Standard feature selectors */
+#define DEVICE_REMOTE_WAKEUP        (1)
+#define ENDPOINT_HALT               (0)
+
+/* Macro to convert wIndex endpoint number to physical endpoint number */
+#define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
+    ((endpoint & 0x80) ? 1 : 0))
+
+
+bool USBDevice::requestGetDescriptor(void)
+{
+    bool success = false;
+
+    switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
+    {
+        case DEVICE_DESCRIPTOR:
+            if (deviceDesc() != NULL)
+            {
+                if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
+                    && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
+                {
+                    transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
+                    transfer.ptr = deviceDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                }
+            }
+            break;
+        case CONFIGURATION_DESCRIPTOR:
+            if (configurationDesc() != NULL)
+            {
+                if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
+                    && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
+                {
+                    /* Get wTotalLength */
+                    transfer.remaining = configurationDesc()[2] \
+                        | (configurationDesc()[3] << 8);
+
+                    transfer.ptr = configurationDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                }
+            }
+            break;
+        case STRING_DESCRIPTOR:
+            switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
+            {
+                            case STRING_OFFSET_LANGID:
+                                transfer.remaining = stringLangidDesc()[0];
+                                transfer.ptr = stringLangidDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case STRING_OFFSET_IMANUFACTURER:
+                                transfer.remaining =  stringImanufacturerDesc()[0];
+                                transfer.ptr = stringImanufacturerDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;       
+                            case STRING_OFFSET_IPRODUCT:
+                                transfer.remaining = stringIproductDesc()[0];
+                                transfer.ptr = stringIproductDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;            
+                            case STRING_OFFSET_ISERIAL:
+                                transfer.remaining = stringIserialDesc()[0];
+                                transfer.ptr = stringIserialDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;        
+                            case STRING_OFFSET_ICONFIGURATION:
+                                transfer.remaining = stringIConfigurationDesc()[0];
+                                transfer.ptr = stringIConfigurationDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break; 
+                            case STRING_OFFSET_IINTERFACE:
+                                transfer.remaining = stringIinterfaceDesc()[0];
+                                transfer.ptr = stringIinterfaceDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break; 
+            }
+            break;
+        case INTERFACE_DESCRIPTOR:
+        case ENDPOINT_DESCRIPTOR:
+            /* TODO: Support is optional, not implemented here */
+            break;
+        default:
+            break;
+    }
+
+    return success;
+}
+
+void USBDevice::decodeSetupPacket(uint8_t *data, SETUP_PACKET *packet)
+{
+    /* Fill in the elements of a SETUP_PACKET structure from raw data */
+    packet->bmRequestType.dataTransferDirection = (data[0] & 0x80) >> 7;
+    packet->bmRequestType.Type = (data[0] & 0x60) >> 5;
+    packet->bmRequestType.Recipient = data[0] & 0x1f;
+    packet->bRequest = data[1];
+    packet->wValue = (data[2] | (uint16_t)data[3] << 8);
+    packet->wIndex = (data[4] | (uint16_t)data[5] << 8);
+    packet->wLength = (data[6] | (uint16_t)data[7] << 8);
+}
+
+
+bool USBDevice::controlOut(void)
+{
+    /* Control transfer data OUT stage */
+    uint8_t buffer[MAX_PACKET_SIZE_EP0];
+    uint32_t packetSize;
+
+    /* Check we should be transferring data OUT */
+    if (transfer.direction != HOST_TO_DEVICE)
+    {
+        return false;
+    }
+
+    /* Read from endpoint */
+    packetSize = EP0getReadResult(buffer);
+
+    /* Check if transfer size is valid */
+    if (packetSize > transfer.remaining)
+    {
+        /* Too big */
+        return false;
+    }
+
+    /* Update transfer */
+    transfer.ptr += packetSize;
+    transfer.remaining -= packetSize;
+
+    /* Check if transfer has completed */
+    if (transfer.remaining == 0)
+    {
+        /* Transfer completed */
+        if (transfer.notify)
+        {
+            /* Notify class layer. */
+            USBCallback_requestCompleted();
+            transfer.notify = false;
+        }
+        /* Status stage */
+        EP0write(NULL, 0);
+    }
+    else
+    {
+        EP0read();
+    }
+
+    return true;
+}
+
+bool USBDevice::controlIn(void)
+{
+    /* Control transfer data IN stage */
+    uint32_t packetSize;
+
+    /* Check if transfer has completed (status stage transactions */
+    /* also have transfer.remaining == 0) */
+    if (transfer.remaining == 0)
+    {
+        if (transfer.zlp)
+        {
+            /* Send zero length packet */
+            EP0write(NULL, 0);
+            transfer.zlp = false;
+        }
+
+        /* Transfer completed */
+        if (transfer.notify)
+        {
+            /* Notify class layer. */
+            USBCallback_requestCompleted();
+            transfer.notify = false;
+        }
+
+        EP0read();
+
+        /* Completed */
+        return true;
+    }
+
+    /* Check we should be transferring data IN */
+    if (transfer.direction != DEVICE_TO_HOST)
+    {
+        return false;
+    }
+
+    packetSize = transfer.remaining;
+
+    if (packetSize > MAX_PACKET_SIZE_EP0)
+    {
+        packetSize = MAX_PACKET_SIZE_EP0;
+    }
+
+    /* Write to endpoint */
+    EP0write(transfer.ptr, packetSize);
+
+    /* Update transfer */
+    transfer.ptr += packetSize;
+    transfer.remaining -= packetSize;
+
+    return true;
+}
+
+bool USBDevice::requestSetAddress(void)
+{
+    /* Set the device address */
+    setAddress(transfer.setup.wValue);
+
+    if (transfer.setup.wValue == 0)
+    {
+        device.state = DEFAULT;
+    }
+    else
+    {
+        device.state = ADDRESS;
+    }
+
+    return true;
+}
+
+bool USBDevice::requestSetConfiguration(void)
+{
+
+    device.configuration = transfer.setup.wValue;
+    /* Set the device configuration */
+    if (device.configuration == 0)
+    {
+        /* Not configured */
+        unconfigureDevice();
+        device.state = ADDRESS;
+    }
+    else
+    {
+        if (USBCallback_setConfiguration(device.configuration))
+        {
+            /* Valid configuration */
+            configureDevice();
+            device.state = CONFIGURED;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool USBDevice::requestGetConfiguration(void)
+{
+    /* Send the device configuration */
+    transfer.ptr = &device.configuration;
+    transfer.remaining = sizeof(device.configuration);
+    transfer.direction = DEVICE_TO_HOST;
+    return true;
+}
+
+bool USBDevice::requestGetInterface(void)
+{
+    static uint8_t alternateSetting;
+
+    /* Return the selected alternate setting for an interface */
+
+    if (device.state != CONFIGURED)
+    {
+        return false;
+    }
+
+    /* TODO: We currently do not support alternate settings */
+    /* so always return zero */
+    /* TODO: Should check that the interface number is valid */
+    alternateSetting = 0;
+
+    /* Send the alternate setting */
+    transfer.ptr = &alternateSetting;
+    transfer.remaining = sizeof(alternateSetting);
+    transfer.direction = DEVICE_TO_HOST;
+    return true;
+}
+
+bool USBDevice::requestSetInterface(void)
+{
+    /* TODO: We currently do not support alternate settings, return false */
+    return false;
+}
+
+bool USBDevice::requestSetFeature()
+{
+    bool success = false;
+
+    if (device.state != CONFIGURED)
+    {
+        /* Endpoint or interface must be zero */
+        if (transfer.setup.wIndex != 0)
+        {
+            return false;
+        }
+    }
+
+    switch (transfer.setup.bmRequestType.Recipient)
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Remote wakeup feature not supported */
+            break;
+        case ENDPOINT_RECIPIENT:
+            if (transfer.setup.wValue == ENDPOINT_HALT)
+            {
+                /* TODO: We should check that the endpoint number is valid */
+                stallEndpoint(
+                    WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
+                success = true;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestClearFeature()
+{
+    bool success = false;
+
+    if (device.state != CONFIGURED)
+    {
+        /* Endpoint or interface must be zero */
+        if (transfer.setup.wIndex != 0)
+        {
+            return false;
+        }
+    }
+
+    switch (transfer.setup.bmRequestType.Recipient)
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Remote wakeup feature not supported */
+            break;
+        case ENDPOINT_RECIPIENT:
+            /* TODO: We should check that the endpoint number is valid */
+            if (transfer.setup.wValue == ENDPOINT_HALT)
+            {
+                unstallEndpoint(
+                    WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
+                success = true;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestGetStatus(void)
+{
+    static uint16_t status;
+    bool success = false;
+
+    if (device.state != CONFIGURED)
+    {
+        /* Endpoint or interface must be zero */
+        if (transfer.setup.wIndex != 0)
+        {
+            return false;
+        }
+    }
+
+    switch (transfer.setup.bmRequestType.Recipient)
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Currently only supports self powered devices */
+            status = DEVICE_STATUS_SELF_POWERED;
+            success = true;
+            break;
+        case INTERFACE_RECIPIENT:
+            status = 0;
+            success = true;
+            break;
+        case ENDPOINT_RECIPIENT:
+            /* TODO: We should check that the endpoint number is valid */
+            if (getEndpointStallState(
+                WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
+            {
+                status = ENDPOINT_STATUS_HALT;
+            }
+            else
+            {
+                status = 0;
+            }
+            success = true;
+            break;
+        default:
+            break;
+    }
+
+    if (success)
+    {
+        /* Send the status */ 
+        transfer.ptr = (uint8_t *)&status; /* Assumes little endian */
+        transfer.remaining = sizeof(status);
+        transfer.direction = DEVICE_TO_HOST;
+    }
+    
+    return success;
+}
+
+bool USBDevice::requestSetup(void)
+{
+    bool success = false;
+
+    /* Process standard requests */
+    if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
+    {
+        switch (transfer.setup.bRequest)
+        {
+             case GET_STATUS:
+                 success = requestGetStatus();
+                 break;
+             case CLEAR_FEATURE:
+                 success = requestClearFeature();
+                 break;
+             case SET_FEATURE:
+                 success = requestSetFeature();
+                 break;
+             case SET_ADDRESS:
+                success = requestSetAddress();
+                 break;
+             case GET_DESCRIPTOR:
+                 success = requestGetDescriptor();
+                 break;
+             case SET_DESCRIPTOR:
+                 /* TODO: Support is optional, not implemented here */
+                 success = false;
+                 break;
+             case GET_CONFIGURATION:
+                 success = requestGetConfiguration();
+                 break;
+             case SET_CONFIGURATION:
+                 success = requestSetConfiguration();
+                 break;
+             case GET_INTERFACE:
+                 success = requestGetInterface();
+                 break;
+             case SET_INTERFACE:
+                 success = requestSetInterface();
+                 break;
+             default:
+                 break;
+        }
+    }
+
+    return success;
+}
+
+bool USBDevice::controlSetup(void)
+{
+    bool success = false;
+
+    /* Control transfer setup stage */
+    uint8_t buffer[MAX_PACKET_SIZE_EP0];
+
+    EP0setup(buffer);
+
+    /* Initialise control transfer state */
+    decodeSetupPacket(buffer, &transfer.setup);
+    transfer.ptr = NULL;
+    transfer.remaining = 0;
+    transfer.direction = 0;
+    transfer.zlp = false;
+    transfer.notify = false;
+
+    /* Process request */
+
+    /* Class / vendor specific */
+    success = USBCallback_request();
+
+    if (!success)
+    {
+        /* Standard requests */
+        if (!requestSetup())
+        {
+            return false;
+        }
+    }
+
+    /* Check transfer size and direction */
+    if (transfer.setup.wLength>0)
+    {
+        if (transfer.setup.bmRequestType.dataTransferDirection \
+            == DEVICE_TO_HOST)
+        {
+            /* IN data stage is required */
+            if (transfer.direction != DEVICE_TO_HOST)
+            {
+                return false;
+            }
+
+            /* Transfer must be less than or equal to the size */
+            /* requested by the host */
+            if (transfer.remaining > transfer.setup.wLength)
+            {
+                transfer.remaining = transfer.setup.wLength;
+            }
+        }
+        else
+        {
+            
+            /* OUT data stage is required */
+            if (transfer.direction != HOST_TO_DEVICE)
+            {
+                return false;
+            }
+
+            /* Transfer must be equal to the size requested by the host */
+            if (transfer.remaining != transfer.setup.wLength)
+            {
+                return false;
+            }
+        }
+    }
+    else
+    {
+        /* No data stage; transfer size must be zero */
+        if (transfer.remaining != 0)
+        {
+            return false;
+        }
+    }
+
+    /* Data or status stage if applicable */
+    if (transfer.setup.wLength>0)
+    {
+        if (transfer.setup.bmRequestType.dataTransferDirection \
+            == DEVICE_TO_HOST)
+        {
+            /* Check if we'll need to send a zero length packet at */
+            /* the end of this transfer */
+            if (transfer.setup.wLength > transfer.remaining)
+            {
+                /* Device wishes to transfer less than host requested */
+                if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
+                {
+                    /* Transfer is a multiple of EP0 max packet size */
+                    transfer.zlp = true;
+                }
+            }
+
+            /* IN stage */
+            controlIn();
+        }
+        else
+        {
+            /* OUT stage */
+            EP0read();
+        }
+    }
+    else
+    {
+        /* Status stage */
+        EP0write(NULL, 0);
+    }
+
+    return true;
+}
+
+void USBDevice::busReset(void)
+{
+    device.state = DEFAULT;
+    device.configuration = 0;
+    device.suspended = false;
+
+    /* Call class / vendor specific busReset function */
+    USBCallback_busReset();
+}
+
+void USBDevice::EP0setupCallback(void)
+{
+    /* Endpoint 0 setup event */
+    if (!controlSetup())
+    {
+        /* Protocol stall */
+        EP0stall();
+    }
+
+    /* Return true if an OUT data stage is expected */
+}
+
+void USBDevice::EP0out(void)
+{
+    /* Endpoint 0 OUT data event */
+    if (!controlOut())
+    {
+        /* Protocol stall; this will stall both endpoints */
+        EP0stall();
+    }
+}
+
+void USBDevice::EP0in(void)
+{
+    /* Endpoint 0 IN data event */
+    if (!controlIn())
+    {
+        /* Protocol stall; this will stall both endpoints */
+        EP0stall();
+    }
+}
+
+bool USBDevice::configured(void)
+{
+    /* Returns true if device is in the CONFIGURED state */
+    return (device.state == CONFIGURED);
+}
+
+void USBDevice::connect(void)
+{
+    /* Connect device */
+    USBHAL::connect();
+}
+
+void USBDevice::disconnect(void)
+{
+    /* Disconnect device */
+    USBHAL::disconnect();
+}
+
+CONTROL_TRANSFER * USBDevice::getTransferPtr(void)
+{
+    return &transfer;
+}
+
+bool USBDevice::addEndpoint(uint8_t endpoint, uint32_t maxPacket)
+{
+    return realiseEndpoint(endpoint, maxPacket, 0);
+}
+
+bool USBDevice::addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket)
+{
+    /* For interrupt endpoints only */
+    return realiseEndpoint(endpoint, maxPacket, RATE_FEEDBACK_MODE);
+}
+
+uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
+{
+    /* Find a descriptor within the list of descriptors */
+    /* following a configuration descriptor. */
+    uint16_t wTotalLength;
+    uint8_t *ptr;
+
+    if (configurationDesc() == NULL)
+    {
+        return NULL;
+    }
+
+    /* Check this is a configuration descriptor */
+    if ((configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH) \
+            || (configurationDesc()[1] != CONFIGURATION_DESCRIPTOR))
+    {
+        return NULL;
+    }
+
+    wTotalLength = configurationDesc()[2] | (configurationDesc()[3] << 8);
+
+    /* Check there are some more descriptors to follow */
+    if (wTotalLength <= (CONFIGURATION_DESCRIPTOR_LENGTH+2))
+    /* +2 is for bLength and bDescriptorType of next descriptor */
+    {
+        return false;
+    }
+
+    /* Start at first descriptor after the configuration descriptor */
+    ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
+
+    do {
+        if (ptr[1] /* bDescriptorType */ == descriptorType)
+        {
+            /* Found */
+            return ptr;
+        }
+
+        /* Skip to next descriptor */
+        ptr += ptr[0]; /* bLength */
+    } while (ptr < (configurationDesc() + wTotalLength));
+
+    /* Reached end of the descriptors - not found */
+    return NULL;
+}
+
+void USBDevice::SOF(int frameNumber)
+{
+}
+
+void USBDevice::connectStateChanged(unsigned int connected)
+{
+}
+
+void USBDevice::suspendStateChanged(unsigned int suspended)
+{
+}
+
+
+USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){
+    VENDOR_ID = vendor_id; 
+    PRODUCT_ID = product_id; 
+    PRODUCT_RELEASE = product_release;
+
+    /* Set initial device state */
+    device.state = POWERED;
+    device.configuration = 0;
+    device.suspended = false;
+
+    connect();
+};
+
+
+bool USBDevice::readStart(uint8_t endpoint, uint16_t maxSize)
+{
+    return endpointRead(endpoint, maxSize) == EP_PENDING;
+}
+
+
+bool USBDevice::write(uint8_t endpoint, uint8_t * buffer, uint16_t size, uint16_t maxSize)
+{
+    EP_STATUS result;
+
+    if (size > maxSize)
+    {
+        return false;
+    }
+
+    /* Block if not configured */
+    while (!configured());
+    
+    /* Send report */
+    result = endpointWrite(endpoint, buffer, size);
+
+    if (result != EP_PENDING)
+    {
+        return false;
+    }
+
+    /* Wait for completion */
+    do {
+        result = endpointWriteResult(endpoint);
+    } while ((result == EP_PENDING) && configured());
+
+    return (result == EP_COMPLETED);
+}
+
+
+bool USBDevice::writeNB(uint8_t endpoint, uint8_t * buffer, uint16_t size, uint16_t maxSize)
+{
+    EP_STATUS result;
+
+    if (size > maxSize)
+    {
+        return false;
+    }
+
+    /* Block if not configured */
+    while (!configured());
+
+    /* Send report */
+    result = endpointWrite(endpoint, buffer, size);
+
+    if (result != EP_PENDING)
+    {
+        return false;
+    }
+
+    result = endpointWriteResult(endpoint);
+
+    return (result == EP_COMPLETED);
+}
+
+
+
+bool USBDevice::read(uint8_t endpoint, uint8_t * buffer, uint16_t * size, uint16_t maxSize)
+{
+    EP_STATUS result;
+
+    /* Block if not configured */
+    while (!configured());
+
+    /* Wait for completion */
+    do {
+        result = endpointReadResult(endpoint, buffer, (uint32_t *)size);
+    } while ((result == EP_PENDING) && configured());
+
+    return (result == EP_COMPLETED);
+}
+
+
+bool USBDevice::readNB(uint8_t endpoint, uint8_t * buffer, uint16_t * size, uint16_t maxSize)
+{
+    EP_STATUS result;
+
+    /* Block if not configured */
+    while (!configured());
+
+    result = endpointReadResult(endpoint, buffer, (uint32_t *)size);
+    
+    return (result == EP_COMPLETED);
+}
+
+
+
+uint8_t * USBDevice::deviceDesc() {
+    static uint8_t deviceDescriptor[] = {
+        DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
+        DEVICE_DESCRIPTOR,              /* bDescriptorType */
+        LSB(USB_VERSION_2_0),           /* bcdUSB (LSB) */
+        MSB(USB_VERSION_2_0),           /* bcdUSB (MSB) */
+        0x00,                           /* bDeviceClass */
+        0x00,                           /* bDeviceSubClass */
+        0x00,                           /* bDeviceprotocol */
+        MAX_PACKET_SIZE_EP0,            /* bMaxPacketSize0 */
+        LSB(VENDOR_ID),                 /* idVendor (LSB) */
+        MSB(VENDOR_ID),                 /* idVendor (MSB) */
+        LSB(PRODUCT_ID),                /* idProduct (LSB) */
+        MSB(PRODUCT_ID),                /* idProduct (MSB) */
+        LSB(PRODUCT_RELEASE),           /* bcdDevice (LSB) */
+        MSB(PRODUCT_RELEASE),           /* bcdDevice (MSB) */
+        STRING_OFFSET_IMANUFACTURER,    /* iManufacturer */
+        STRING_OFFSET_IPRODUCT,         /* iProduct */
+        STRING_OFFSET_ISERIAL,          /* iSerialNumber */
+        0x01                            /* bNumConfigurations */
+    };
+    return deviceDescriptor;
+}
+
+uint8_t * USBDevice::stringLangidDesc() {
+    static uint8_t stringLangidDescriptor[] = {
+        0x04,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        0x09,0x00,          /*bString Lang ID - 0x009 - English*/
+    };
+    return stringLangidDescriptor;
+}
+
+uint8_t * USBDevice::stringImanufacturerDesc() {
+    static uint8_t stringImanufacturerDescriptor[] = {
+        0x12,                                            /*bLength*/
+        STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
+        'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
+    };
+    return stringImanufacturerDescriptor;
+}
+
+uint8_t * USBDevice::stringIserialDesc() {
+    static uint8_t stringIserialDescriptor[] = {
+        0x16,                                                           /*bLength*/
+        STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
+        '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0,    /*bString iSerial - 0123456789*/
+    };
+    return stringIserialDescriptor;
+}
+
+uint8_t * USBDevice::stringIConfigurationDesc() {
+    static uint8_t stringIconfigurationDescriptor[] = {
+        0x06,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        '0',0,'1',0,        /*bString iConfiguration - 01*/
+    };
+    return stringIconfigurationDescriptor;
+}
+
+uint8_t * USBDevice::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        'U',0,'S',0,'B',0,  /*bString iInterface - USB*/
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBDevice::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       /*bLength*/
+        STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
+        'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/
+    };
+    return stringIproductDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBDevice.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,231 @@
+/* USBDevice.h */
+/* Generic USB device */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBDEVICE_H
+#define USBDEVICE_H
+
+#include "mbed.h"
+#include "USBDevice_Types.h"
+#include "USBBusInterface.h"
+
+
+
+class USBDevice: public USBHAL
+{
+public:
+    USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
+    
+    /**
+    * Check if the device is configured
+    *
+    * @returns true if configured, false otherwise
+    */
+    bool configured(void);
+    
+    /**
+    * Connect a device
+    */
+    void connect(void);
+    
+    /**
+    * Disconnect a device
+    */
+    void disconnect(void);
+    
+    /**
+    * Add an endpoint
+    *
+    * @param endpoint endpoint which will be added
+    * @param maxPacket Maximum size of a packet which can be sent for this endpoint
+    * @returns true if successful, false otherwise
+    */
+    bool addEndpoint(uint8_t endpoint, uint32_t maxPacket);
+
+    /**
+    * Start a reading on a certain endpoint.
+    * You can access the result of the reading by USBDevice_read
+    *
+    * @param endpoint endpoint which will be read
+    * @param maxSize the maximum length that can be read
+    * @return true if successful
+    */
+    bool readStart(uint8_t endpoint, uint16_t maxSize);
+    
+    /**
+    * Read a certain endpoint. Before calling this function, USBUSBDevice_readStart
+    * must be called.
+    *
+    * Warning: blocking
+    *
+    * @param endpoint endpoint which will be read
+    * @param buffer buffer will be filled with the data received
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool read(uint8_t endpoint, uint8_t * buffer, uint16_t * size, uint16_t maxSize);
+    
+    /**
+    * Read a certain endpoint.
+    *
+    * Warning: non blocking
+    *
+    * @param endpoint endpoint which will be read
+    * @param buffer buffer will be filled with the data received (if data are available) 
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readNB(uint8_t endpoint, uint8_t * buffer, uint16_t * size, uint16_t maxSize);
+    
+    /**
+    * Write a certain endpoint.
+    *
+    * Warning: blocking
+    *
+    * @param endpoint endpoint to write
+    * @param buffer data contained in buffer will be write
+    * @param size the number of bytes to write
+    * @param maxSize the maximum length that can be written on this endpoint
+    */
+    bool write(uint8_t endpoint, uint8_t * buffer, uint16_t size, uint16_t maxSize);
+    bool writeNB(uint8_t endpoint, uint8_t * buffer, uint16_t size, uint16_t maxSize);
+
+    
+    /**
+    * Called by USBDevice layer on bus reset. Warning: Called in ISR context
+    *
+    * May be used to reset state
+    */
+    virtual void USBCallback_busReset(void) {};
+    
+    /**
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request() { return false; };   
+    
+    /**
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    */
+    virtual void USBCallback_requestCompleted() {};
+    
+    /**
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration) { return false; };
+
+    /**
+    * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual uint8_t * deviceDesc();
+    
+    /**
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc(){return NULL;};
+    
+    /**
+    * Get string lang id descriptor
+    *
+    * @return pointer to the string lang id descriptor
+    */
+    virtual uint8_t * stringLangidDesc();
+    
+    /**
+    * Get string manufacturer descriptor
+    *
+    * @returns pointer to the string manufacturer descriptor
+    */
+    virtual uint8_t * stringImanufacturerDesc();
+    
+    /**
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+    
+    /**
+    * Get string serial descriptor
+    *
+    * @returns pointer to the string serial descriptor
+    */
+    virtual uint8_t * stringIserialDesc();
+    
+    /**
+    * Get string configuration descriptor
+    *
+    * @returns pointer to the string configuration descriptor
+    */
+    virtual uint8_t * stringIConfigurationDesc();
+    
+    /**
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+    
+    /**
+    * Get the length of the report descriptor
+    *
+    * @returns length of the report descriptor
+    */
+    virtual uint16_t reportDescLength() { return 0; };
+    
+
+
+protected:
+    virtual void busReset(void);
+    virtual void EP0setupCallback(void);
+    virtual void EP0out(void);
+    virtual void EP0in(void);
+    virtual void SOF(int frameNumber);
+    virtual void connectStateChanged(unsigned int connected);
+    virtual void suspendStateChanged(unsigned int suspended);
+    uint8_t * findDescriptor(uint8_t descriptorType);
+    CONTROL_TRANSFER * getTransferPtr(void);
+    
+    uint16_t VENDOR_ID;
+    uint16_t PRODUCT_ID;
+    uint16_t PRODUCT_RELEASE;
+
+private:
+    bool addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket);
+    bool requestGetDescriptor(void);
+    bool controlOut(void);
+    bool controlIn(void);
+    bool requestSetAddress(void);
+    bool requestSetConfiguration(void);
+    bool requestSetFeature(void);
+    bool requestClearFeature(void);
+    bool requestGetStatus(void);
+    bool requestSetup(void);
+    bool controlSetup(void);
+    void decodeSetupPacket(uint8_t *data, SETUP_PACKET *packet);
+    bool requestGetConfiguration(void);
+    bool requestGetInterface(void);
+    bool requestSetInterface(void);
+
+    CONTROL_TRANSFER transfer;
+    USB_DEVICE device;
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBDevice_Types.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,69 @@
+/* USBDevice_Types.h */
+/* USB Device type definitions, conversions and constants */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBDEVICE_TYPES_H
+#define USBDEVICE_TYPES_H
+
+/* Standard requests */
+#define GET_STATUS        (0)
+#define CLEAR_FEATURE     (1)
+#define SET_FEATURE       (3)
+#define SET_ADDRESS       (5)
+#define GET_DESCRIPTOR    (6)
+#define SET_DESCRIPTOR    (7)
+#define GET_CONFIGURATION (8)
+#define SET_CONFIGURATION (9)
+#define GET_INTERFACE     (10)
+#define SET_INTERFACE     (11)
+
+/* bmRequestType.dataTransferDirection */
+#define HOST_TO_DEVICE (0)
+#define DEVICE_TO_HOST (1)
+
+/* bmRequestType.Type*/
+#define STANDARD_TYPE  (0)
+#define CLASS_TYPE     (1)
+#define VENDOR_TYPE    (2)
+#define RESERVED_TYPE  (3)
+
+/* bmRequestType.Recipient */
+#define DEVICE_RECIPIENT    (0)
+#define INTERFACE_RECIPIENT (1)
+#define ENDPOINT_RECIPIENT  (2)
+#define OTHER_RECIPIENT     (3)
+
+/* Descriptors */
+#define DESCRIPTOR_TYPE(wValue)  (wValue >> 8)
+#define DESCRIPTOR_INDEX(wValue) (wValue & 0xf)
+
+typedef struct {
+    struct {
+        uint8_t dataTransferDirection;
+        uint8_t Type;
+        uint8_t Recipient;
+    } bmRequestType;
+    uint8_t  bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+} SETUP_PACKET;
+
+typedef struct {
+    SETUP_PACKET setup;
+    uint8_t *ptr;
+    uint32_t remaining;
+    uint8_t direction;
+    bool zlp;
+    bool notify;
+} CONTROL_TRANSFER;
+
+typedef enum {ATTACHED, POWERED, DEFAULT, ADDRESS, CONFIGURED} DEVICE_STATE;
+
+typedef struct {
+    volatile DEVICE_STATE state;
+    uint8_t configuration;
+    bool suspended;
+} USB_DEVICE;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBEndpoints.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,34 @@
+/* USBEndpoints.h */
+/* USB endpoint configuration */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBENDPOINTS_H
+#define USBENDPOINTS_H
+
+/* SETUP packet size */
+#define SETUP_PACKET_SIZE (8)
+
+/* Options flags for configuring endpoints */
+#define DEFAULT_OPTIONS     (0)
+#define SINGLE_BUFFERED     (1U << 0)
+#define ISOCHRONOUS         (1U << 1)
+#define RATE_FEEDBACK_MODE  (1U << 2) /* Interrupt endpoints only */
+
+/* Endpoint transfer status, for endpoints > 0 */
+typedef enum {
+    EP_COMPLETED,   /* Transfer completed */
+    EP_PENDING,     /* Transfer in progress */
+    EP_INVALID,     /* Invalid parameter */
+    EP_STALLED,     /* Endpoint stalled */
+} EP_STATUS;
+
+/* Include configuration for specific target */
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+#include "USBEndpoints_LPC17_LPC23.h"
+#elif defined(TARGET_LPC11U24)
+#include "USBEndpoints_LPC11U.h"
+#else
+#error "Unknown target type"
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBEndpoints_LPC11U.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,51 @@
+/* USBEndpoints_LPC11U.h */
+/* Endpoint configuration for LPC11U */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (5)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP1IN       (3)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2OUT      (4)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2IN       (5)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3OUT      (6)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3IN       (7)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP4OUT      (8)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP4IN       (9)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0 (64)
+#define MAX_PACKET_SIZE_EP1 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP2 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP3 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP4 (64) /* Int/Bulk */
+
+#define MAX_PACKET_SIZE_EP1_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP2_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP3_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP4_ISO (1023) /* Isochronous */
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoint */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+/* Interrupt endpoint */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+/* Isochronous endpoint */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3_ISO)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBEndpoints_LPC17_LPC23.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,79 @@
+/* USBEndpoints_LPC17_LPC23.h */
+/* Endpoint configuration for LPC1768 and LPC2368 */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (16)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Interrupt     64          No            */
+#define EP1IN       (3)  /* Interrupt     64          No            */
+#define EP2OUT      (4)  /* Bulk          64          Yes           */
+#define EP2IN       (5)  /* Bulk          64          Yes           */
+#define EP3OUT      (6)  /* Isochronous   1023        Yes           */
+#define EP3IN       (7)  /* Isochronous   1023        Yes           */
+#define EP4OUT      (8)  /* Interrupt     64          No            */
+#define EP4IN       (9)  /* Interrupt     64          No            */
+#define EP5OUT      (10) /* Bulk          64          Yes           */
+#define EP5IN       (11) /* Bulk          64          Yes           */
+#define EP6OUT      (12) /* Isochronous   1023        Yes           */
+#define EP6IN       (13) /* Isochronous   1023        Yes           */
+#define EP7OUT      (14) /* Interrupt     64          No            */
+#define EP7IN       (15) /* Interrupt     64          No            */
+#define EP8OUT      (16) /* Bulk          64          Yes           */
+#define EP8IN       (17) /* Bulk          64          Yes           */
+#define EP9OUT      (18) /* Isochronous   1023        Yes           */
+#define EP9IN       (19) /* Isochronous   1023        Yes           */
+#define EP10OUT     (20) /* Interrupt     64          No            */
+#define EP10IN      (21) /* Interrupt     64          No            */
+#define EP11OUT     (22) /* Bulk          64          Yes           */
+#define EP11IN      (23) /* Bulk          64          Yes           */
+#define EP12OUT     (24) /* Isochronous   1023        Yes           */
+#define EP12IN      (25) /* Isochronous   1023        Yes           */
+#define EP13OUT     (26) /* Interrupt     64          No            */
+#define EP13IN      (27) /* Interrupt     64          No            */
+#define EP14OUT     (28) /* Bulk          64          Yes           */
+#define EP14IN      (29) /* Bulk          64          Yes           */
+#define EP15OUT     (30) /* Bulk          64          Yes           */
+#define EP15IN      (31) /* Bulk          64          Yes           */
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0  (64)
+#define MAX_PACKET_SIZE_EP1  (64)
+#define MAX_PACKET_SIZE_EP2  (64)
+#define MAX_PACKET_SIZE_EP3  (1023)
+#define MAX_PACKET_SIZE_EP4  (64)
+#define MAX_PACKET_SIZE_EP5  (64)
+#define MAX_PACKET_SIZE_EP6  (1023)
+#define MAX_PACKET_SIZE_EP7  (64)
+#define MAX_PACKET_SIZE_EP8  (64)
+#define MAX_PACKET_SIZE_EP9  (1023)
+#define MAX_PACKET_SIZE_EP10 (64)
+#define MAX_PACKET_SIZE_EP11 (64)
+#define MAX_PACKET_SIZE_EP12 (1023)
+#define MAX_PACKET_SIZE_EP13 (64)
+#define MAX_PACKET_SIZE_EP14 (64)
+#define MAX_PACKET_SIZE_EP15 (64)
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+/* Interrupt endpoints */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+/* Isochronous endpoints */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBHID.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,259 @@
+// USBHID.c
+// Human Interface Device (HID) class
+// Copyright (c) 2011 ARM Limited. All rights reserved.
+
+#include "stdint.h"
+#include "USBBusInterface.h"
+#include "USBHID.h"
+
+
+USBHID::USBHID(uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release)
+{
+    output_length = output_report_length;
+    input_length = input_report_length;
+}
+
+
+bool USBHID::send(HID_REPORT *report)
+{
+    return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
+}
+
+
+bool USBHID::read(HID_REPORT *report)
+{
+    uint16_t bytesRead = 0;
+    bool result;
+    result = USBDevice::read(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
+    if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
+        return false;
+    report->length = bytesRead;
+    return result;
+}
+
+
+bool USBHID::readNB(HID_REPORT *report)
+{
+    uint16_t bytesRead = 0;
+    bool result;
+    result = USBDevice::readNB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
+    report->length = bytesRead;
+    if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
+        return false;
+    return result;
+}
+
+
+uint16_t USBHID::reportDescLength() {
+    reportDesc();
+    return reportLength;
+}
+
+
+
+//
+//  Route callbacks from lower layers to class(es)
+//
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request
+// This is used to handle extensions to standard requests
+// and class specific requests
+// Return true if class handles this request
+bool USBHID::USBCallback_request() {
+    bool success = false;
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+    uint8_t *hidDescriptor;
+
+    // Process additional standard requests
+
+    if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
+    {
+        switch (transfer->setup.bRequest)
+        {
+            case GET_DESCRIPTOR:
+                switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
+                {
+                    case REPORT_DESCRIPTOR:
+                        if ((reportDesc() != NULL) \
+                            && (reportDescLength() != 0))
+                        {
+                            transfer->remaining = reportDescLength();
+                            transfer->ptr = reportDesc();
+                            transfer->direction = DEVICE_TO_HOST;
+                            success = true;
+                        }
+                        break;
+                    case HID_DESCRIPTOR:
+                            // Find the HID descriptor, after the configuration descriptor
+                            hidDescriptor = findDescriptor(HID_DESCRIPTOR);
+                            if (hidDescriptor != NULL)
+                            {
+                                transfer->remaining = HID_DESCRIPTOR_LENGTH;
+                                transfer->ptr = hidDescriptor;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                            }
+                            break;
+                     
+                    default:
+                        break;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    // Process class-specific requests
+
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
+    {
+        switch (transfer->setup.bRequest)
+        {
+             case SET_REPORT:
+                // First byte will be used for report ID
+                outputReport.data[0] = transfer->setup.wValue & 0xff;
+                outputReport.length = transfer->setup.wLength + 1;
+
+                transfer->remaining = sizeof(outputReport.data) - 1;
+                transfer->ptr = &outputReport.data[1];
+                transfer->direction = HOST_TO_DEVICE;
+                transfer->notify = true;
+                success = true;
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request completion
+// if the 'notify' flag has been set to true
+// In this case it is used to indicate that a HID report has
+// been received from the host on endpoint 0
+void USBHID::USBCallback_requestCompleted() {
+    HID_callbackSetReport(&outputReport);
+}
+
+#define DEFAULT_CONFIGURATION (1)
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported
+bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
+    addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
+
+    // We activate the endpoint to be able to recceive data
+    readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
+    return true;
+}
+
+uint8_t * USBHID::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,               //bLength
+        STRING_DESCRIPTOR,  //bDescriptorType 0x03
+        'H',0,'I',0,'D',0,  //bString iInterface - HID
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBHID::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
+    };
+    return stringIproductDescriptor;
+}
+
+
+
+uint8_t * USBHID::reportDesc() {
+    static uint8_t reportDescriptor[] = {
+        0x06, LSB(0xFFAB), MSB(0xFFAB),
+        0x0A, LSB(0x0200), MSB(0x0200),
+        0xA1, 0x01,         // Collection 0x01
+        0x75, 0x08,         // report size = 8 bits
+        0x15, 0x00,         // logical minimum = 0
+        0x26, 0xFF, 0x00,   // logical maximum = 255
+        0x95, input_length,           // report count
+        0x09, 0x01,         // usage
+        0x81, 0x02,         // Input (array)
+        0x95, output_length,           // report count
+        0x09, 0x02,         // usage
+        0x91, 0x02,         // Output (array)
+        0xC0                // end collection
+
+    };
+    reportLength = sizeof(reportDescriptor);
+    return reportDescriptor;
+}
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * HID_DESCRIPTOR_LENGTH) \
+                               + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t * USBHID::configurationDesc() {
+    static uint8_t configurationDescriptor[] = {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (LSB)
+        MSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER(0),                     // bMaxPower
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        HID_SUBCLASS_NONE,              // bInterfaceSubClass
+        HID_PROTOCOL_NONE,              // bInterfaceProtocol
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB(HID_VERSION_1_11),          // bcdHID (LSB)
+        MSB(HID_VERSION_1_11),          // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        LSB(this->reportDescLength()),  // wDescriptorLength (LSB)
+        MSB(this->reportDescLength()),  // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        10,                             // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_OUT),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        10,                             // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBHID.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,158 @@
+/* USBHID.h */
+/* Human Interface Device (HID) class */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USB_HID_H
+#define USB_HID_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBHID_Types.h"
+#include "USBDevice.h"
+
+
+/**
+ * USBHID example
+ * @code
+ * #include "mbed.h"
+ * #include "USBHID.h"
+ *
+ * USBHID hid;
+ * HID_REPORT recv;
+ * BusOut leds(LED1,LED2,LED3,LED4);
+ *
+ * int main(void) {
+ *    while (1) {
+ *        hid.read(&recv);
+ *        leds = recv.data[0];
+ *    }
+ * }
+ * @endcode
+ */
+
+class USBHID: public USBDevice {
+public:
+
+    /**
+    * Constructor
+    *
+    * @param output_report_length Maximum length of a sent report (up to 64 bytes) (default: 64 bytes)
+    * @param input_report_length Maximum length of a received report (up to 64 bytes) (default: 64 bytes)
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBHID(uint8_t output_report_length = 64, uint8_t input_report_length = 64, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0006, uint16_t product_release = 0x0001);
+
+
+    /**
+    * Send a Report
+    *
+    * @param report Report which will be sent (a report is defined by all data and the length)
+    * @returns true if successful
+    */
+    bool send(HID_REPORT *report);
+    
+    /**
+    * Read a report. Warning: blocking
+    *
+    * @param report pointer to the report to fill
+    * @returns true if successful
+    */
+    bool read(HID_REPORT * report);
+    
+    /**
+    * Read a report. Warning: non blocking
+    *
+    * @param report pointer to the report to fill
+    * @returns true if successful
+    */
+    bool readNB(HID_REPORT * report);
+
+    /**
+    * Get the Report descriptor
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t * reportDesc();
+
+    /**
+    * Get the length of the report descriptor
+    *
+    * @returns the length of the report descriptor
+    */
+    virtual uint16_t reportDescLength();
+
+    /**
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+    
+    /**
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+    
+    /**
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+
+    /**
+    * HID Report received by SET_REPORT request. Warning: Called in ISR context
+    * First byte of data will be the report ID
+    *
+    * @param report Data and length received
+    */
+    virtual void HID_callbackSetReport(HID_REPORT *report){};
+
+
+    /**
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request();
+
+    /**
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    */
+    virtual void USBCallback_requestCompleted();
+
+    /**
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+
+
+
+protected:
+    uint16_t reportLength;
+
+private:
+    HID_REPORT outputReport;
+    uint8_t output_length;
+    uint8_t input_length;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBHID_Types.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,77 @@
+/* USBClass_HID_Types.h */
+/* USB HID class type definitions, conversions and constants */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBCLASS_HID_TYPES
+#define USBCLASS_HID_TYPES
+
+#include <stdint.h>
+
+/* */
+#define HID_VERSION_1_11    (0x0111)
+
+/* HID Class */
+#define HID_CLASS           (3)
+#define HID_SUBCLASS_NONE   (0)
+#define HID_PROTOCOL_NONE   (0)
+
+/* Descriptors */
+#define HID_DESCRIPTOR          (33)
+#define HID_DESCRIPTOR_LENGTH   (0x09)
+#define REPORT_DESCRIPTOR       (34)
+
+/* Class requests */
+#define GET_REPORT (0x1)
+#define GET_IDLE   (0x2)
+#define SET_REPORT (0x9)
+#define SET_IDLE   (0xa)
+
+/* HID Class Report Descriptor */
+/* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes */
+/* of data as per HID Class standard */
+
+/* Main items */
+#define INPUT(size)             (0x80 | size)
+#define OUTPUT(size)            (0x90 | size)
+#define FEATURE(size)           (0xb0 | size)
+#define COLLECTION(size)        (0xa0 | size)
+#define END_COLLECTION(size)    (0xc0 | size)
+
+/* Global items */
+#define USAGE_PAGE(size)        (0x04 | size)
+#define LOGICAL_MINIMUM(size)   (0x14 | size)
+#define LOGICAL_MAXIMUM(size)   (0x24 | size)
+#define PHYSICAL_MINIMUM(size)  (0x34 | size)
+#define PHYSICAL_MAXIMUM(size)  (0x44 | size)
+#define UNIT_EXPONENT(size)     (0x54 | size)
+#define UNIT(size)              (0x64 | size)
+#define REPORT_SIZE(size)       (0x74 | size)
+#define REPORT_ID(size)         (0x84 | size)
+#define REPORT_COUNT(size)      (0x94 | size)
+#define PUSH(size)              (0xa4 | size)
+#define POP(size)               (0xb4 | size)
+
+/* Local items */
+#define USAGE(size)                 (0x08 | size)
+#define USAGE_MINIMUM(size)         (0x18 | size)
+#define USAGE_MAXIMUM(size)         (0x28 | size)
+#define DESIGNATOR_INDEX(size)      (0x38 | size)
+#define DESIGNATOR_MINIMUM(size)    (0x48 | size)
+#define DESIGNATOR_MAXIMUM(size)    (0x58 | size)
+#define STRING_INDEX(size)          (0x78 | size)
+#define STRING_MINIMUM(size)        (0x88 | size)
+#define STRING_MAXIMUM(size)        (0x98 | size)
+#define DELIMITER(size)             (0xa8 | size)
+
+/* HID Report */
+/* Where report IDs are used the first byte of 'data' will be the */
+/* report ID and 'length' will include this report ID byte. */
+
+#define MAX_HID_REPORT_SIZE (64)
+
+typedef struct {
+    uint32_t length;
+    uint8_t data[MAX_HID_REPORT_SIZE];
+} HID_REPORT;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBKeyboard.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,455 @@
+// USBKeyboard.c
+// USB device example: Standard keyboard
+// Copyright (c) 2011 ARM Limited. All rights reserved.
+
+#include "stdint.h"
+
+#include "USBKeyboard.h"
+
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_VOLUME   3
+
+/* Modifiers */
+enum MODIFIER_KEY
+{
+    KEY_CTRL = 1,
+    KEY_SHIFT = 2,
+    KEY_ALT = 4,
+};
+
+typedef struct {
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (145)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+{0, 0},             /* NUL */
+{0, 0},             /* SOH */
+{0, 0},             /* STX */
+{0, 0},             /* ETX */
+{0, 0},             /* EOT */
+{0, 0},             /* ENQ */
+{0, 0},             /* ACK */
+{0, 0},             /* BEL */
+{0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+{0x2b, 0},          /* TAB */  /* Keyboard Tab */
+{0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+{0, 0},             /* VT  */
+{0, 0},             /* FF  */
+{0, 0},             /* CR  */
+{0, 0},             /* SO  */
+{0, 0},             /* SI  */
+{0, 0},             /* DEL */
+{0, 0},             /* DC1 */
+{0, 0},             /* DC2 */
+{0, 0},             /* DC3 */
+{0, 0},             /* DC4 */
+{0, 0},             /* NAK */
+{0, 0},             /* SYN */
+{0, 0},             /* ETB */
+{0, 0},             /* CAN */
+{0, 0},             /* EM  */
+{0, 0},             /* SUB */
+{0, 0},             /* ESC */
+{0, 0},             /* FS  */
+{0, 0},             /* GS  */
+{0, 0},             /* RS  */
+{0, 0},             /* US  */
+{0x2c, 0},          /*   */
+{0x1e, KEY_SHIFT},      /* ! */
+{0x34, KEY_SHIFT},      /* " */
+{0x20, KEY_SHIFT},      /* # */
+{0x21, KEY_SHIFT},      /* $ */
+{0x22, KEY_SHIFT},      /* % */
+{0x24, KEY_SHIFT},      /* & */
+{0x34, 0},          /* ' */
+{0x26, KEY_SHIFT},      /* ( */
+{0x27, KEY_SHIFT},      /* ) */
+{0x25, KEY_SHIFT},      /* * */
+{0x2e, KEY_SHIFT},      /* + */
+{0x36, 0},          /* , */
+{0x2d, 0},          /* - */
+{0x37, 0},          /* . */
+{0x38, 0},          /* / */
+{0x27, 0},          /* 0 */
+{0x1e, 0},          /* 1 */
+{0x1f, 0},          /* 2 */
+{0x20, 0},          /* 3 */
+{0x21, 0},          /* 4 */
+{0x22, 0},          /* 5 */
+{0x23, 0},          /* 6 */
+{0x24, 0},          /* 7 */
+{0x25, 0},          /* 8 */
+{0x26, 0},          /* 9 */
+{0x33, KEY_SHIFT},      /* : */
+{0x33, 0},          /* ; */
+{0x36, KEY_SHIFT},      /* < */
+{0x2e, 0},          /* = */
+{0x37, KEY_SHIFT},      /* > */
+{0x38, KEY_SHIFT},      /* ? */
+{0x1f, KEY_SHIFT},      /* @ */
+{0x04, KEY_SHIFT},      /* A */
+{0x05, KEY_SHIFT},      /* B */
+{0x06, KEY_SHIFT},      /* C */
+{0x07, KEY_SHIFT},      /* D */
+{0x08, KEY_SHIFT},      /* E */
+{0x09, KEY_SHIFT},      /* F */
+{0x0a, KEY_SHIFT},      /* G */
+{0x0b, KEY_SHIFT},      /* H */
+{0x0c, KEY_SHIFT},      /* I */
+{0x0d, KEY_SHIFT},      /* J */
+{0x0e, KEY_SHIFT},      /* K */
+{0x0f, KEY_SHIFT},      /* L */
+{0x10, KEY_SHIFT},      /* M */
+{0x11, KEY_SHIFT},      /* N */
+{0x12, KEY_SHIFT},      /* O */
+{0x13, KEY_SHIFT},      /* P */
+{0x14, KEY_SHIFT},      /* Q */
+{0x15, KEY_SHIFT},      /* R */
+{0x16, KEY_SHIFT},      /* S */
+{0x17, KEY_SHIFT},      /* T */
+{0x18, KEY_SHIFT},      /* U */
+{0x19, KEY_SHIFT},      /* V */
+{0x1a, KEY_SHIFT},      /* W */
+{0x1b, KEY_SHIFT},      /* X */
+{0x1c, KEY_SHIFT},      /* Y */
+{0x1d, KEY_SHIFT},      /* Z */
+{0x2f, 0},          /* [ */
+{0x31, 0},          /* \ */
+{0x30, 0},          /* ] */
+{0x23, KEY_SHIFT},      /* ^ */
+{0x2d, KEY_SHIFT},      /* _ */
+{0x35, 0},          /* ` */
+{0x04, 0},          /* a */
+{0x05, 0},          /* b */
+{0x06, 0},          /* c */
+{0x07, 0},          /* d */
+{0x08, 0},          /* e */
+{0x09, 0},          /* f */
+{0x0a, 0},          /* g */
+{0x0b, 0},          /* h */
+{0x0c, 0},          /* i */
+{0x0d, 0},          /* j */
+{0x0e, 0},          /* k */
+{0x0f, 0},          /* l */
+{0x10, 0},          /* m */
+{0x11, 0},          /* n */
+{0x12, 0},          /* o */
+{0x13, 0},          /* p */
+{0x14, 0},          /* q */
+{0x15, 0},          /* r */
+{0x16, 0},          /* s */
+{0x17, 0},          /* t */
+{0x18, 0},          /* u */
+{0x19, 0},          /* v */
+{0x1a, 0},          /* w */
+{0x1b, 0},          /* x */
+{0x1c, 0},          /* y */
+{0x1d, 0},          /* z */
+{0x2f, KEY_SHIFT},      /* { */
+{0x31, KEY_SHIFT},      /* | */
+{0x30, KEY_SHIFT},      /* } */
+{0x35, KEY_SHIFT},      /* ~ */
+{0,0},              /* DEL */
+
+{0x3a, 0},          /* F1 */
+{0x3b, 0},          /* F2 */
+{0x3c, 0},          /* F3 */
+{0x3d, 0},          /* F4 */
+{0x3e, 0},          /* F5 */
+{0x3f, 0},          /* F6 */
+{0x40, 0},          /* F7 */
+{0x41, 0},          /* F8 */
+{0x42, 0},          /* F9 */
+{0x43, 0},          /* F10 */
+{0x44, 0},          /* F11 */
+{0x45, 0},          /* F12 */
+
+{0x46, 0},          /* PRINT_SCREEN */
+{0x49, 0},          /* INSERT */
+{0x4a, 0},          /* HOME */
+{0x4b, 0},          /* PAGE_UP */
+{0x4e, 0},          /* PAGE_DOWN */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (145)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+{0, 0},             /* NUL */
+{0, 0},             /* SOH */
+{0, 0},             /* STX */
+{0, 0},             /* ETX */
+{0, 0},             /* EOT */
+{0, 0},             /* ENQ */
+{0, 0},             /* ACK */
+{0, 0},             /* BEL */
+{0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+{0x2b, 0},          /* TAB */  /* Keyboard Tab */
+{0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+{0, 0},             /* VT  */
+{0, 0},             /* FF  */
+{0, 0},             /* CR  */
+{0, 0},             /* SO  */
+{0, 0},             /* SI  */
+{0, 0},             /* DEL */
+{0, 0},             /* DC1 */
+{0, 0},             /* DC2 */
+{0, 0},             /* DC3 */
+{0, 0},             /* DC4 */
+{0, 0},             /* NAK */
+{0, 0},             /* SYN */
+{0, 0},             /* ETB */
+{0, 0},             /* CAN */
+{0, 0},             /* EM  */
+{0, 0},             /* SUB */
+{0, 0},             /* ESC */
+{0, 0},             /* FS  */
+{0, 0},             /* GS  */
+{0, 0},             /* RS  */
+{0, 0},             /* US  */
+{0x2c, 0},          /*   */
+{0x1e, KEY_SHIFT},      /* ! */
+{0x1f, KEY_SHIFT},      /* " */
+{0x32, 0},          /* # */
+{0x21, KEY_SHIFT},      /* $ */
+{0x22, KEY_SHIFT},      /* % */
+{0x24, KEY_SHIFT},      /* & */
+{0x34, 0},          /* ' */
+{0x26, KEY_SHIFT},      /* ( */
+{0x27, KEY_SHIFT},      /* ) */
+{0x25, KEY_SHIFT},      /* * */
+{0x2e, KEY_SHIFT},      /* + */
+{0x36, 0},          /* , */
+{0x2d, 0},          /* - */
+{0x37, 0},          /* . */
+{0x38, 0},          /* / */
+{0x27, 0},          /* 0 */
+{0x1e, 0},          /* 1 */
+{0x1f, 0},          /* 2 */
+{0x20, 0},          /* 3 */
+{0x21, 0},          /* 4 */
+{0x22, 0},          /* 5 */
+{0x23, 0},          /* 6 */
+{0x24, 0},          /* 7 */
+{0x25, 0},          /* 8 */
+{0x26, 0},          /* 9 */
+{0x33, KEY_SHIFT},      /* : */
+{0x33, 0},          /* ; */
+{0x36, KEY_SHIFT},      /* < */
+{0x2e, 0},          /* = */
+{0x37, KEY_SHIFT},      /* > */
+{0x38, KEY_SHIFT},      /* ? */
+{0x34, KEY_SHIFT},      /* @ */
+{0x04, KEY_SHIFT},      /* A */
+{0x05, KEY_SHIFT},      /* B */
+{0x06, KEY_SHIFT},      /* C */
+{0x07, KEY_SHIFT},      /* D */
+{0x08, KEY_SHIFT},      /* E */
+{0x09, KEY_SHIFT},      /* F */
+{0x0a, KEY_SHIFT},      /* G */
+{0x0b, KEY_SHIFT},      /* H */
+{0x0c, KEY_SHIFT},      /* I */
+{0x0d, KEY_SHIFT},      /* J */
+{0x0e, KEY_SHIFT},      /* K */
+{0x0f, KEY_SHIFT},      /* L */
+{0x10, KEY_SHIFT},      /* M */
+{0x11, KEY_SHIFT},      /* N */
+{0x12, KEY_SHIFT},      /* O */
+{0x13, KEY_SHIFT},      /* P */
+{0x14, KEY_SHIFT},      /* Q */
+{0x15, KEY_SHIFT},      /* R */
+{0x16, KEY_SHIFT},      /* S */
+{0x17, KEY_SHIFT},      /* T */
+{0x18, KEY_SHIFT},      /* U */
+{0x19, KEY_SHIFT},      /* V */
+{0x1a, KEY_SHIFT},      /* W */
+{0x1b, KEY_SHIFT},      /* X */
+{0x1c, KEY_SHIFT},      /* Y */
+{0x1d, KEY_SHIFT},      /* Z */
+{0x2f, 0},          /* [ */
+{0x64, 0},          /* \ */
+{0x30, 0},          /* ] */
+{0x23, KEY_SHIFT},      /* ^ */
+{0x2d, KEY_SHIFT},      /* _ */
+{0x35, 0},          /* ` */
+{0x04, 0},          /* a */
+{0x05, 0},          /* b */
+{0x06, 0},          /* c */
+{0x07, 0},          /* d */
+{0x08, 0},          /* e */
+{0x09, 0},          /* f */
+{0x0a, 0},          /* g */
+{0x0b, 0},          /* h */
+{0x0c, 0},          /* i */
+{0x0d, 0},          /* j */
+{0x0e, 0},          /* k */
+{0x0f, 0},          /* l */
+{0x10, 0},          /* m */
+{0x11, 0},          /* n */
+{0x12, 0},          /* o */
+{0x13, 0},          /* p */
+{0x14, 0},          /* q */
+{0x15, 0},          /* r */
+{0x16, 0},          /* s */
+{0x17, 0},          /* t */
+{0x18, 0},          /* u */
+{0x19, 0},          /* v */
+{0x1a, 0},          /* w */
+{0x1b, 0},          /* x */
+{0x1c, 0},          /* y */
+{0x1d, 0},          /* z */
+{0x2f, KEY_SHIFT},      /* { */
+{0x64, KEY_SHIFT},      /* | */
+{0x30, KEY_SHIFT},      /* } */
+{0x32, KEY_SHIFT},      /* ~ */
+{0,0},             /* DEL */
+
+{0x3a, 0},          /* F1 */
+{0x3b, 0},          /* F2 */
+{0x3c, 0},          /* F3 */
+{0x3d, 0},          /* F4 */
+{0x3e, 0},          /* F5 */
+{0x3f, 0},          /* F6 */
+{0x40, 0},          /* F7 */
+{0x41, 0},          /* F8 */
+{0x42, 0},          /* F9 */
+{0x43, 0},          /* F10 */
+{0x44, 0},          /* F11 */
+{0x45, 0},          /* F12 */
+
+{0x46, 0},          /* PRINT_SCREEN */
+{0x49, 0},          /* INSERT */
+{0x4a, 0},          /* HOME */
+{0x4b, 0},          /* PAGE_UP */
+{0x4e, 0},          /* PAGE_DOWN */
+};
+#endif
+
+uint8_t * USBKeyboard::reportDesc() {
+    static uint8_t reportDescriptor[] = {
+        USAGE_PAGE(1), 0x01,                    // Generic Desktop
+        USAGE(1), 0x06,                         // Keyboard
+        COLLECTION(1), 0x01,                    // Application
+        REPORT_ID(1),       REPORT_ID_KEYBOARD,
+
+        USAGE_PAGE(1), 0x07,                    // Key Codes
+        USAGE_MINIMUM(1), 0xE0,
+        USAGE_MAXIMUM(1), 0xE7,
+        LOGICAL_MINIMUM(1), 0x00,
+        LOGICAL_MAXIMUM(1), 0x01,
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x08,
+        INPUT(1), 0x02,                         // Data, Variable, Absolute
+        REPORT_COUNT(1), 0x01,
+        REPORT_SIZE(1), 0x08,
+        INPUT(1), 0x01,                         // Constant
+        REPORT_COUNT(1), 0x05,
+        REPORT_SIZE(1), 0x01,
+
+
+        USAGE_PAGE(1), 0x08,                    // LEDs
+        USAGE_MINIMUM(1), 0x01,
+        USAGE_MAXIMUM(1), 0x05,
+        OUTPUT(1), 0x02,                        // Data, Variable, Absolute
+        REPORT_COUNT(1), 0x01,
+        REPORT_SIZE(1), 0x03,
+        OUTPUT(1), 0x01,                        // Constant
+        REPORT_COUNT(1), 0x06,
+        REPORT_SIZE(1), 0x08,
+        LOGICAL_MINIMUM(1), 0x00,
+        LOGICAL_MAXIMUM(1), 0x65,
+
+
+        USAGE_PAGE(1), 0x07,                    // Key Codes
+        USAGE_MINIMUM(1), 0x00,
+        USAGE_MAXIMUM(1), 0x65,
+        INPUT(1), 0x00,                         // Data, Array
+        END_COLLECTION(0),
+
+        // Media Control
+        USAGE_PAGE(1), 0x0C,
+        USAGE(1), 0x01,
+        COLLECTION(1), 0x01,
+        REPORT_ID(1), REPORT_ID_VOLUME,
+        USAGE_PAGE(1), 0x0C,
+        LOGICAL_MINIMUM(1), 0x00,
+        LOGICAL_MAXIMUM(1), 0x01,
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x07,
+        USAGE(1), 0xB5,             // Next Track
+        USAGE(1), 0xB6,             // Previous Track
+        USAGE(1), 0xB7,             // Stop
+        USAGE(1), 0xCD,             // Play / Pause
+        USAGE(1), 0xE2,             // Mute
+        USAGE(1), 0xE9,             // Volume Up
+        USAGE(1), 0xEA,             // Volume Down
+        INPUT(1), 0x02,             // Input (Data, Variable, Absolute)
+        REPORT_COUNT(1), 0x01,
+        INPUT(1), 0x01,
+        END_COLLECTION(0),
+
+    };
+    reportLength = sizeof(reportDescriptor);
+    return reportDescriptor;
+}
+
+int USBKeyboard::_putc(int c) {
+    return keyCode(c, keymap[c].modifier);
+}
+
+bool USBKeyboard::keyCode(uint8_t key, uint8_t modifier) {
+    // Send a simulated keyboard keypress. Returns true if successful.
+
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+
+    report.length = 9;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    return true;
+
+}
+
+
+bool USBKeyboard::mediaControl(MEDIA_KEY key) {
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = (1 << key) & 0x7f;
+
+    report.length = 2;
+
+    send(&report);
+    
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+
+    report.length = 2;
+
+    return send(&report);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBKeyboard.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,125 @@
+/* USBKeyboard.h */
+/* USB device example: Standard keyboard */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBKEYBOARD_H
+#define USBKEYBOARD_H
+
+#include "USBHID.h"
+#include "Stream.h"
+
+
+enum MEDIA_KEY
+{
+    KEY_NEXT_TRACK,     /*!< next Track Button */
+    KEY_PREVIOUS_TRACK, /*!< Previous track Button */
+    KEY_STOP,           /*!< Stop Button */
+    KEY_PLAY_PAUSE,     /*!< Play/Pause Button */
+    KEY_MUTE,           /*!< Mute Button */
+    KEY_VOLUME_UP,      /*!< Volume Up Button */
+    KEY_VOLUME_DOWN,    /*!< Volume Down Button */
+};
+
+enum FUNCTION_KEY
+{
+    KEY_F1 = 128,   /* F1 key */
+    KEY_F2,         /* F2 key */
+    KEY_F3,         /* F3 key */
+    KEY_F4,         /* F4 key */
+    KEY_F5,         /* F5 key */
+    KEY_F6,         /* F6 key */
+    KEY_F7,         /* F7 key */
+    KEY_F8,         /* F8 key */
+    KEY_F9,         /* F9 key */
+    KEY_F10,        /* F10 key */
+    KEY_F11,        /* F11 key */
+    KEY_F12,        /* F12 key */
+    KEY_PRINT_SCREEN,   /* Print Screen key */
+    KEY_INSERT,         /* Insert key */
+    KEY_HOME,           /* Home key */
+    KEY_PAGE_UP,        /* Page Up key */
+    KEY_PAGE_DOWN,      /* Page Down key */
+};
+
+/** USB device: a keyboard
+ *
+ * Warning: you can only instantiate one instance of a USB device: USBMouse, USBKeyboard, USBAbsMouse, USBMouseKeyboard, or USBAbsMouseKeyboard.
+ *
+ * Example:
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBKeyboard.h"
+ *
+ * USBKeyboard key;
+ * 
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *       key.puts("Hello World\r\n");
+ *       wait(1);
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class USBKeyboard: public USBHID, public Stream
+{
+    public:
+    
+        /**
+        *   Constructor
+        *
+        * @param vendor_id Your vendor_id (default: 0x1234)
+        * @param product_id Your product_id (default: 0x0001)
+        * @param product_release Your preoduct_release (default: 0x0001)
+        *
+        */
+        USBKeyboard(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0003, uint16_t product_release = 0x0001): USBHID(vendor_id, product_id, product_release){};
+        
+        /**
+        * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key 
+        *
+        * @code
+        * //To send CTRL + s (save)
+        *  keyboard.keyCode('s', KEY_CTRL);
+        * @endcode
+        *
+        * @param modifier bit 0: CTRL, bit 1: SHIFT, bit 2: ALT (default: 0)
+        * @param key character to send
+        * @returns true if there is no error, false otherwise
+        */
+        bool keyCode(uint8_t key, uint8_t modifier = 0);
+        
+        /**
+        * Send a character
+        *
+        * @param c character to be sent
+        * @returns true if there is no error, false otherwise
+        */
+        virtual int _putc(int c);
+        
+        /**
+        * Control media keys
+        *
+        * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN)
+        * @returns true if there is no error, false otherwise
+        */
+        bool mediaControl(MEDIA_KEY key);
+        
+        /**
+        * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+        *
+        * @returns pointer to the report descriptor
+        */
+        virtual uint8_t * reportDesc();
+        
+   private:
+        //dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
+        virtual int _getc() { return -1;}
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBMouse.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,176 @@
+// USBMouse.c
+// USB device example: Relative mouse
+// Copyright (c) 2011 ARM Limited. All rights reserved.
+
+#include "stdint.h"
+#include "USBMouse.h"
+
+bool USBMouse::update(int16_t x, int16_t y, uint8_t button, int8_t z) {
+    switch (mouse_type) {
+        case REL_MOUSE:
+            while (x > 127) {
+                if (!mouseSend(127, 0, button, z)) return false;
+                x = x - 127;
+            }
+            while (x < -128) {
+                if (!mouseSend(-128, 0, button, z)) return false;
+                x = x + 128;
+            }
+            while (y > 127) {
+                if (!mouseSend(0, 127, button, z)) return false;
+                y = y - 127;
+            }
+            while (y < -128) {
+                if (!mouseSend(0, -128, button, z)) return false;
+                y = y + 128;
+            }
+            return mouseSend(x, y, button, z);
+        case ABS_MOUSE:
+            HID_REPORT report;
+
+            report.data[0] = x & 0xff;
+            report.data[1] = (x >> 8) & 0xff;
+            report.data[2] = y & 0xff;
+            report.data[3] = (y >> 8) & 0xff;
+            report.data[4] = -z;
+            report.data[5] = button & 0x07;
+
+            report.length = 6;
+
+            return send(&report);
+        default:
+            return false;
+    }
+}
+
+bool USBMouse::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) {
+    HID_REPORT report;
+    report.data[0] = buttons & 0x07;
+    report.data[1] = x;
+    report.data[2] = y;
+    report.data[3] = -z; // >0 to scroll down, <0 to scroll up
+
+    report.length = 4;
+
+    return send(&report);
+}
+
+bool USBMouse::move(int16_t x, int16_t y) {
+    return update(x, y, button, 0);
+}
+
+bool USBMouse::scroll(int8_t z) {
+    return update(0, 0, button, z);
+}
+
+
+bool USBMouse::doubleClick() {
+    if (!click(MOUSE_LEFT))
+        return false;
+    wait(0.1);
+    return click(MOUSE_LEFT);
+}
+
+bool USBMouse::click(uint8_t button) {
+    if (!update(0, 0, button, 0))
+        return false;
+    wait(0.01);
+    return update(0, 0, 0, 0);
+}
+
+bool USBMouse::press(uint8_t button_) {
+    button = button_ & 0x07;
+    return update(0, 0, button, 0);
+}
+
+bool USBMouse::release(uint8_t button_) {
+    button = (button & (~button_)) & 0x07;
+    return update(0, 0, button, 0);
+}
+
+
+uint8_t * USBMouse::reportDesc() {
+
+    if (mouse_type == REL_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+            USAGE_PAGE(1),      0x01,       // Genric Desktop
+            USAGE(1),           0x02,       // Mouse
+            COLLECTION(1),      0x01,       // Application
+            USAGE(1),           0x01,       // Pointer
+            COLLECTION(1),      0x00,       // Physical
+
+            REPORT_COUNT(1),    0x03,
+            REPORT_SIZE(1),     0x01,
+            USAGE_PAGE(1),      0x09,       // Buttons
+            USAGE_MINIMUM(1),       0x1,
+            USAGE_MAXIMUM(1),       0x3,
+            LOGICAL_MINIMUM(1),     0x00,
+            LOGICAL_MAXIMUM(1),     0x01,
+            INPUT(1),           0x02,
+            REPORT_COUNT(1),    0x01,
+            REPORT_SIZE(1),     0x05,
+            INPUT(1),           0x01,
+
+            REPORT_COUNT(1),    0x03,
+            REPORT_SIZE(1),     0x08,
+            USAGE_PAGE(1),      0x01,
+            USAGE(1),           0x30,       // X
+            USAGE(1),           0x31,       // Y
+            USAGE(1),           0x38,       // scroll
+            LOGICAL_MINIMUM(1),     0x81,
+            LOGICAL_MAXIMUM(1),     0x7f,
+            INPUT(1),           0x06,       // Relative data
+
+            END_COLLECTION(0),
+            END_COLLECTION(0),
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    } else if (mouse_type == ABS_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+
+            USAGE_PAGE(1), 0x01,           // Generic Desktop
+            USAGE(1), 0x02,                // Mouse
+            COLLECTION(1), 0x01,           // Application
+            USAGE(1), 0x01,                // Pointer
+            COLLECTION(1), 0x00,           // Physical
+
+            USAGE_PAGE(1), 0x01,            // Generic Desktop
+            USAGE(1), 0x30,                 // X
+            USAGE(1), 0x31,                 // Y
+            LOGICAL_MINIMUM(1), 0x00,       // 0
+            LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
+            REPORT_SIZE(1), 0x10,
+            REPORT_COUNT(1), 0x02,
+            INPUT(1), 0x02,                 // Data, Variable, Absolute
+
+            USAGE_PAGE(1), 0x01,            // Generic Desktop
+            USAGE(1), 0x38,                 // scroll
+            LOGICAL_MINIMUM(1), 0x81,       // -127
+            LOGICAL_MAXIMUM(1), 0x7f,       // 127
+            REPORT_SIZE(1), 0x08,
+            REPORT_COUNT(1), 0x01,
+            INPUT(1), 0x06,                 // Data, Variable, Relative
+
+            USAGE_PAGE(1), 0x09,            // Buttons
+            USAGE_MINIMUM(1), 0x01,
+            USAGE_MAXIMUM(1), 0x03,
+            LOGICAL_MINIMUM(1), 0x00,       // 0
+            LOGICAL_MAXIMUM(1), 0x01,       // 1
+            REPORT_COUNT(1), 0x03,
+            REPORT_SIZE(1), 0x01,
+            INPUT(1), 0x02,                 // Data, Variable, Absolute
+            REPORT_COUNT(1), 0x01,
+            REPORT_SIZE(1), 0x05,
+            INPUT(1), 0x01,                 // Constant
+
+            END_COLLECTION(0),
+            END_COLLECTION(0)
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    }
+    return NULL;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBMouse.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,187 @@
+/* USBMouse.h */
+/* USB device example: relative mouse */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBMOUSE_H
+#define USBMOUSE_H
+
+#include "USBHID.h"
+
+#define REPORT_ID_MOUSE   2
+
+/* Common usage */
+
+enum MOUSE_BUTTON
+{
+    MOUSE_LEFT = 1,
+    MOUSE_RIGHT = 2,
+    MOUSE_MIDDLE = 4,
+};
+
+/* X and Y limits */
+/* These values do not directly map to screen pixels */
+/* Zero may be interpreted as meaning 'no movement' */
+#define X_MIN_ABS    (1)        /*!< Minimum value on x-axis */  
+#define Y_MIN_ABS    (1)        /*!< Minimum value on y-axis */
+#define X_MAX_ABS    (0x7fff)   /*!< Maximum value on x-axis */
+#define Y_MAX_ABS    (0x7fff)   /*!< Maximum value on y-axis */
+
+#define X_MIN_REL    (-127)     /*!< The maximum value that we can move to the left on the x-axis */
+#define Y_MIN_REL    (-127)     /*!< The maximum value that we can move up on the y-axis */
+#define X_MAX_REL    (127)      /*!< The maximum value that we can move to the right on the x-axis */
+#define Y_MAX_REL    (127)      /*!< The maximum value that we can move down on the y-axis */
+
+enum MOUSE_TYPE
+{
+    ABS_MOUSE,
+    REL_MOUSE,
+};
+
+/**
+ *
+ * USBMouse example
+ * @code
+ * #include "mbed.h"
+ * #include "USBMouse.h"
+ *
+ * USBMouse mouse;
+ *
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *      mouse.move(20, 0);
+ *      wait(0.5);
+ *   }
+ * }
+ *
+ * @endcode
+ *
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "USBMouse.h"
+ *
+ * USBMouse mouse(ABS_MOUSE);
+ *
+ * #include <math.h>
+ *
+ * int main(void)
+ * {
+ *   uint16_t x_center = (X_MAX_ABS - X_MIN_ABS)/2;
+ *   uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2;
+ *   uint16_t x_screen = 0;
+ *   uint16_t y_screen = 0;
+ *   
+ *   uint32_t x_origin = x_center;
+ *   uint32_t y_origin = y_center;
+ *   uint32_t radius = 5000;
+ *   uint32_t angle = 0;
+ *
+ *   while (1)
+ *   {
+ *       x_screen = x_origin + cos((double)angle*3.14/180.0)*radius;
+ *       y_screen = y_origin + sin((double)angle*3.14/180.0)*radius;
+ *       
+ *       mouse.move(x_screen, y_screen);
+ *       angle += 3;
+ *       wait(0.01);
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class USBMouse: public USBHID
+{
+    public:
+        
+        /**
+        *   Constructor
+        *
+        * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE)
+        * @param vendor_id Your vendor_id (default: 0x1234)
+        * @param product_id Your product_id (default: 0x0001)
+        * @param product_release Your preoduct_release (default: 0x0001)
+        *
+        */
+        USBMouse(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0001, uint16_t product_release = 0x0001): 
+            USBHID(vendor_id, product_id, product_release)
+            { 
+                button = 0;
+                this->mouse_type = mouse_type;
+            };
+        
+        /**
+        * Write a state of the mouse
+        *
+        * @param x x-axis position
+        * @param y y-axis position
+        * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE)
+        * @param z wheel state (>0 to scroll down, <0 to scroll up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z);
+        
+        
+        /**
+        * Move the cursor to (x, y)
+        *
+        * @param x-axis position
+        * @param y-axis position
+        * @returns true if there is no error, false otherwise
+        */
+        bool move(int16_t x, int16_t y);
+        
+        /**
+        * Press one or several buttons
+        *
+        * @param button button state (ex: press(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool press(uint8_t button);
+        
+        /**
+        * Release one or several buttons
+        *
+        * @param button button state (ex: release(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool release(uint8_t button);
+        
+        /**
+        * Double click (MOUSE_LEFT)
+        *
+        * @returns true if there is no error, false otherwise
+        */
+        bool doubleClick();
+        
+        /**
+        * Click
+        *
+        * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool click(uint8_t button); 
+        
+        /**
+        * Scrolling
+        *
+        * @param z value of the wheel (>0 to go down, <0 to go up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool scroll(int8_t z);
+        
+        /**
+        * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+        *
+        * @returns pointer to the report descriptor
+        */
+        virtual uint8_t * reportDesc();
+        
+    private:
+        MOUSE_TYPE mouse_type;
+        uint8_t button;
+        bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBMouseKeyboard.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,675 @@
+// Keyboard_RelMouse.c
+// USB device example: Keyboard and a relative mouse
+// Copyright (c) 2011 ARM Limited. All rights reserved.
+
+#include "stdint.h"
+#include "USBMouseKeyboard.h"
+
+
+/* Modifiers */
+enum MODIFIER_KEY
+{
+    KEY_CTRL = 1,
+    KEY_SHIFT = 2,
+    KEY_ALT = 4,
+};
+
+typedef struct {
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (145)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+{0, 0},             /* NUL */
+{0, 0},             /* SOH */
+{0, 0},             /* STX */
+{0, 0},             /* ETX */
+{0, 0},             /* EOT */
+{0, 0},             /* ENQ */
+{0, 0},             /* ACK */
+{0, 0},             /* BEL */
+{0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+{0x2b, 0},          /* TAB */  /* Keyboard Tab */
+{0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+{0, 0},             /* VT  */
+{0, 0},             /* FF  */
+{0, 0},             /* CR  */
+{0, 0},             /* SO  */
+{0, 0},             /* SI  */
+{0, 0},             /* DEL */
+{0, 0},             /* DC1 */
+{0, 0},             /* DC2 */
+{0, 0},             /* DC3 */
+{0, 0},             /* DC4 */
+{0, 0},             /* NAK */
+{0, 0},             /* SYN */
+{0, 0},             /* ETB */
+{0, 0},             /* CAN */
+{0, 0},             /* EM  */
+{0, 0},             /* SUB */
+{0, 0},             /* ESC */
+{0, 0},             /* FS  */
+{0, 0},             /* GS  */
+{0, 0},             /* RS  */
+{0, 0},             /* US  */
+{0x2c, 0},          /*   */
+{0x1e, KEY_SHIFT},      /* ! */
+{0x34, KEY_SHIFT},      /* " */
+{0x20, KEY_SHIFT},      /* # */
+{0x21, KEY_SHIFT},      /* $ */
+{0x22, KEY_SHIFT},      /* % */
+{0x24, KEY_SHIFT},      /* & */
+{0x34, 0},          /* ' */
+{0x26, KEY_SHIFT},      /* ( */
+{0x27, KEY_SHIFT},      /* ) */
+{0x25, KEY_SHIFT},      /* * */
+{0x2e, KEY_SHIFT},      /* + */
+{0x36, 0},          /* , */
+{0x2d, 0},          /* - */
+{0x37, 0},          /* . */
+{0x38, 0},          /* / */
+{0x27, 0},          /* 0 */
+{0x1e, 0},          /* 1 */
+{0x1f, 0},          /* 2 */
+{0x20, 0},          /* 3 */
+{0x21, 0},          /* 4 */
+{0x22, 0},          /* 5 */
+{0x23, 0},          /* 6 */
+{0x24, 0},          /* 7 */
+{0x25, 0},          /* 8 */
+{0x26, 0},          /* 9 */
+{0x33, KEY_SHIFT},      /* : */
+{0x33, 0},          /* ; */
+{0x36, KEY_SHIFT},      /* < */
+{0x2e, 0},          /* = */
+{0x37, KEY_SHIFT},      /* > */
+{0x38, KEY_SHIFT},      /* ? */
+{0x1f, KEY_SHIFT},      /* @ */
+{0x04, KEY_SHIFT},      /* A */
+{0x05, KEY_SHIFT},      /* B */
+{0x06, KEY_SHIFT},      /* C */
+{0x07, KEY_SHIFT},      /* D */
+{0x08, KEY_SHIFT},      /* E */
+{0x09, KEY_SHIFT},      /* F */
+{0x0a, KEY_SHIFT},      /* G */
+{0x0b, KEY_SHIFT},      /* H */
+{0x0c, KEY_SHIFT},      /* I */
+{0x0d, KEY_SHIFT},      /* J */
+{0x0e, KEY_SHIFT},      /* K */
+{0x0f, KEY_SHIFT},      /* L */
+{0x10, KEY_SHIFT},      /* M */
+{0x11, KEY_SHIFT},      /* N */
+{0x12, KEY_SHIFT},      /* O */
+{0x13, KEY_SHIFT},      /* P */
+{0x14, KEY_SHIFT},      /* Q */
+{0x15, KEY_SHIFT},      /* R */
+{0x16, KEY_SHIFT},      /* S */
+{0x17, KEY_SHIFT},      /* T */
+{0x18, KEY_SHIFT},      /* U */
+{0x19, KEY_SHIFT},      /* V */
+{0x1a, KEY_SHIFT},      /* W */
+{0x1b, KEY_SHIFT},      /* X */
+{0x1c, KEY_SHIFT},      /* Y */
+{0x1d, KEY_SHIFT},      /* Z */
+{0x2f, 0},          /* [ */
+{0x31, 0},          /* \ */
+{0x30, 0},          /* ] */
+{0x23, KEY_SHIFT},      /* ^ */
+{0x2d, KEY_SHIFT},      /* _ */
+{0x35, 0},          /* ` */
+{0x04, 0},          /* a */
+{0x05, 0},          /* b */
+{0x06, 0},          /* c */
+{0x07, 0},          /* d */
+{0x08, 0},          /* e */
+{0x09, 0},          /* f */
+{0x0a, 0},          /* g */
+{0x0b, 0},          /* h */
+{0x0c, 0},          /* i */
+{0x0d, 0},          /* j */
+{0x0e, 0},          /* k */
+{0x0f, 0},          /* l */
+{0x10, 0},          /* m */
+{0x11, 0},          /* n */
+{0x12, 0},          /* o */
+{0x13, 0},          /* p */
+{0x14, 0},          /* q */
+{0x15, 0},          /* r */
+{0x16, 0},          /* s */
+{0x17, 0},          /* t */
+{0x18, 0},          /* u */
+{0x19, 0},          /* v */
+{0x1a, 0},          /* w */
+{0x1b, 0},          /* x */
+{0x1c, 0},          /* y */
+{0x1d, 0},          /* z */
+{0x2f, KEY_SHIFT},      /* { */
+{0x31, KEY_SHIFT},      /* | */
+{0x30, KEY_SHIFT},      /* } */
+{0x35, KEY_SHIFT},      /* ~ */
+{0,0},              /* DEL */
+
+{0x3a, 0},          /* F1 */
+{0x3b, 0},          /* F2 */
+{0x3c, 0},          /* F3 */
+{0x3d, 0},          /* F4 */
+{0x3e, 0},          /* F5 */
+{0x3f, 0},          /* F6 */
+{0x40, 0},          /* F7 */
+{0x41, 0},          /* F8 */
+{0x42, 0},          /* F9 */
+{0x43, 0},          /* F10 */
+{0x44, 0},          /* F11 */
+{0x45, 0},          /* F12 */
+
+{0x46, 0},          /* PRINT_SCREEN */
+{0x49, 0},          /* INSERT */
+{0x4a, 0},          /* HOME */
+{0x4b, 0},          /* PAGE_UP */
+{0x4e, 0},          /* PAGE_DOWN */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (145)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+{0, 0},             /* NUL */
+{0, 0},             /* SOH */
+{0, 0},             /* STX */
+{0, 0},             /* ETX */
+{0, 0},             /* EOT */
+{0, 0},             /* ENQ */
+{0, 0},             /* ACK */
+{0, 0},             /* BEL */
+{0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+{0x2b, 0},          /* TAB */  /* Keyboard Tab */
+{0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+{0, 0},             /* VT  */
+{0, 0},             /* FF  */
+{0, 0},             /* CR  */
+{0, 0},             /* SO  */
+{0, 0},             /* SI  */
+{0, 0},             /* DEL */
+{0, 0},             /* DC1 */
+{0, 0},             /* DC2 */
+{0, 0},             /* DC3 */
+{0, 0},             /* DC4 */
+{0, 0},             /* NAK */
+{0, 0},             /* SYN */
+{0, 0},             /* ETB */
+{0, 0},             /* CAN */
+{0, 0},             /* EM  */
+{0, 0},             /* SUB */
+{0, 0},             /* ESC */
+{0, 0},             /* FS  */
+{0, 0},             /* GS  */
+{0, 0},             /* RS  */
+{0, 0},             /* US  */
+{0x2c, 0},          /*   */
+{0x1e, KEY_SHIFT},      /* ! */
+{0x1f, KEY_SHIFT},      /* " */
+{0x32, 0},          /* # */
+{0x21, KEY_SHIFT},      /* $ */
+{0x22, KEY_SHIFT},      /* % */
+{0x24, KEY_SHIFT},      /* & */
+{0x34, 0},          /* ' */
+{0x26, KEY_SHIFT},      /* ( */
+{0x27, KEY_SHIFT},      /* ) */
+{0x25, KEY_SHIFT},      /* * */
+{0x2e, KEY_SHIFT},      /* + */
+{0x36, 0},          /* , */
+{0x2d, 0},          /* - */
+{0x37, 0},          /* . */
+{0x38, 0},          /* / */
+{0x27, 0},          /* 0 */
+{0x1e, 0},          /* 1 */
+{0x1f, 0},          /* 2 */
+{0x20, 0},          /* 3 */
+{0x21, 0},          /* 4 */
+{0x22, 0},          /* 5 */
+{0x23, 0},          /* 6 */
+{0x24, 0},          /* 7 */
+{0x25, 0},          /* 8 */
+{0x26, 0},          /* 9 */
+{0x33, KEY_SHIFT},      /* : */
+{0x33, 0},          /* ; */
+{0x36, KEY_SHIFT},      /* < */
+{0x2e, 0},          /* = */
+{0x37, KEY_SHIFT},      /* > */
+{0x38, KEY_SHIFT},      /* ? */
+{0x34, KEY_SHIFT},      /* @ */
+{0x04, KEY_SHIFT},      /* A */
+{0x05, KEY_SHIFT},      /* B */
+{0x06, KEY_SHIFT},      /* C */
+{0x07, KEY_SHIFT},      /* D */
+{0x08, KEY_SHIFT},      /* E */
+{0x09, KEY_SHIFT},      /* F */
+{0x0a, KEY_SHIFT},      /* G */
+{0x0b, KEY_SHIFT},      /* H */
+{0x0c, KEY_SHIFT},      /* I */
+{0x0d, KEY_SHIFT},      /* J */
+{0x0e, KEY_SHIFT},      /* K */
+{0x0f, KEY_SHIFT},      /* L */
+{0x10, KEY_SHIFT},      /* M */
+{0x11, KEY_SHIFT},      /* N */
+{0x12, KEY_SHIFT},      /* O */
+{0x13, KEY_SHIFT},      /* P */
+{0x14, KEY_SHIFT},      /* Q */
+{0x15, KEY_SHIFT},      /* R */
+{0x16, KEY_SHIFT},      /* S */
+{0x17, KEY_SHIFT},      /* T */
+{0x18, KEY_SHIFT},      /* U */
+{0x19, KEY_SHIFT},      /* V */
+{0x1a, KEY_SHIFT},      /* W */
+{0x1b, KEY_SHIFT},      /* X */
+{0x1c, KEY_SHIFT},      /* Y */
+{0x1d, KEY_SHIFT},      /* Z */
+{0x2f, 0},          /* [ */
+{0x64, 0},          /* \ */
+{0x30, 0},          /* ] */
+{0x23, KEY_SHIFT},      /* ^ */
+{0x2d, KEY_SHIFT},      /* _ */
+{0x35, 0},          /* ` */
+{0x04, 0},          /* a */
+{0x05, 0},          /* b */
+{0x06, 0},          /* c */
+{0x07, 0},          /* d */
+{0x08, 0},          /* e */
+{0x09, 0},          /* f */
+{0x0a, 0},          /* g */
+{0x0b, 0},          /* h */
+{0x0c, 0},          /* i */
+{0x0d, 0},          /* j */
+{0x0e, 0},          /* k */
+{0x0f, 0},          /* l */
+{0x10, 0},          /* m */
+{0x11, 0},          /* n */
+{0x12, 0},          /* o */
+{0x13, 0},          /* p */
+{0x14, 0},          /* q */
+{0x15, 0},          /* r */
+{0x16, 0},          /* s */
+{0x17, 0},          /* t */
+{0x18, 0},          /* u */
+{0x19, 0},          /* v */
+{0x1a, 0},          /* w */
+{0x1b, 0},          /* x */
+{0x1c, 0},          /* y */
+{0x1d, 0},          /* z */
+{0x2f, KEY_SHIFT},      /* { */
+{0x64, KEY_SHIFT},      /* | */
+{0x30, KEY_SHIFT},      /* } */
+{0x32, KEY_SHIFT},      /* ~ */
+{0,0},             /* DEL */
+
+{0x3a, 0},          /* F1 */
+{0x3b, 0},          /* F2 */
+{0x3c, 0},          /* F3 */
+{0x3d, 0},          /* F4 */
+{0x3e, 0},          /* F5 */
+{0x3f, 0},          /* F6 */
+{0x40, 0},          /* F7 */
+{0x41, 0},          /* F8 */
+{0x42, 0},          /* F9 */
+{0x43, 0},          /* F10 */
+{0x44, 0},          /* F11 */
+{0x45, 0},          /* F12 */
+
+{0x46, 0},          /* PRINT_SCREEN */
+{0x49, 0},          /* INSERT */
+{0x4a, 0},          /* HOME */
+{0x4b, 0},          /* PAGE_UP */
+{0x4e, 0},          /* PAGE_DOWN */
+};
+#endif
+
+uint8_t * USBMouseKeyboard::reportDesc() {
+    if (mouse_type == REL_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+                // Keyboard
+                USAGE_PAGE(1),      0x01,
+                USAGE(1),           0x06,
+                COLLECTION(1),      0x01,
+                REPORT_ID(1),       REPORT_ID_KEYBOARD,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0xE0,
+                USAGE_MAXIMUM(1),       0xE7,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(1),     0x01,
+                REPORT_SIZE(1),     0x01,
+                REPORT_COUNT(1),    0x08,
+                INPUT(1),           0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x08,
+                INPUT(1),           0x01,
+                REPORT_COUNT(1),    0x05,
+                REPORT_SIZE(1),     0x01,
+                USAGE_PAGE(1),      0x08,
+                USAGE_MINIMUM(1),       0x01,
+                USAGE_MAXIMUM(1),       0x05,
+                OUTPUT(1),          0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x03,
+                OUTPUT(1),          0x01,
+                REPORT_COUNT(1),    0x06,
+                REPORT_SIZE(1),     0x08,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(2),     0xff, 0x00,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0x00,
+                USAGE_MAXIMUM(2),       0xff, 0x00,
+                INPUT(1),           0x00,
+                END_COLLECTION(0),
+
+                // Mouse
+                USAGE_PAGE(1),      0x01,           // Generic Desktop
+                USAGE(1),           0x02,           // Mouse
+                COLLECTION(1),      0x01,           // Application
+                USAGE(1),           0x01,           // Pointer
+                COLLECTION(1),      0x00,           // Physical
+                REPORT_ID(1),       REPORT_ID_MOUSE,
+                REPORT_COUNT(1),    0x03,
+                REPORT_SIZE(1),     0x01,
+                USAGE_PAGE(1),      0x09,           // Buttons
+                USAGE_MINIMUM(1),       0x1,
+                USAGE_MAXIMUM(1),       0x3,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(1),     0x01,
+                INPUT(1),           0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x05,
+                INPUT(1),           0x01,
+                REPORT_COUNT(1),    0x03,
+                REPORT_SIZE(1),     0x08,
+                USAGE_PAGE(1),      0x01,
+                USAGE(1),           0x30,           // X
+                USAGE(1),           0x31,           // Y
+                USAGE(1),           0x38,           // scroll
+                LOGICAL_MINIMUM(1),     0x81,
+                LOGICAL_MAXIMUM(1),     0x7f,
+                INPUT(1),           0x06,
+                END_COLLECTION(0),
+                END_COLLECTION(0),
+
+
+                // Media Control
+                USAGE_PAGE(1), 0x0C,
+                USAGE(1), 0x01,
+                COLLECTION(1), 0x01,
+                REPORT_ID(1), REPORT_ID_VOLUME,
+                USAGE_PAGE(1), 0x0C,
+                LOGICAL_MINIMUM(1), 0x00,
+                LOGICAL_MAXIMUM(1), 0x01,
+                REPORT_SIZE(1), 0x01,
+                REPORT_COUNT(1), 0x07,
+                USAGE(1), 0xB5,             // Next Track
+                USAGE(1), 0xB6,             // Previous Track
+                USAGE(1), 0xB7,             // Stop
+                USAGE(1), 0xCD,             // Play / Pause
+                USAGE(1), 0xE2,             // Mute
+                USAGE(1), 0xE9,             // Volume Up
+                USAGE(1), 0xEA,             // Volume Down
+                INPUT(1), 0x02,             // Input (Data, Variable, Absolute)
+                REPORT_COUNT(1), 0x01,
+                INPUT(1), 0x01,
+                END_COLLECTION(0),
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    } else if (mouse_type == ABS_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+
+                // Keyboard
+                USAGE_PAGE(1),      0x01,
+                USAGE(1),           0x06,
+                COLLECTION(1),      0x01,
+                REPORT_ID(1),       REPORT_ID_KEYBOARD,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0xE0,
+                USAGE_MAXIMUM(1),       0xE7,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(1),     0x01,
+                REPORT_SIZE(1),     0x01,
+                REPORT_COUNT(1),    0x08,
+                INPUT(1),           0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x08,
+                INPUT(1),           0x01,
+                REPORT_COUNT(1),    0x05,
+                REPORT_SIZE(1),     0x01,
+                USAGE_PAGE(1),      0x08,
+                USAGE_MINIMUM(1),       0x01,
+                USAGE_MAXIMUM(1),       0x05,
+                OUTPUT(1),          0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x03,
+                OUTPUT(1),          0x01,
+                REPORT_COUNT(1),    0x06,
+                REPORT_SIZE(1),     0x08,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(2),     0xff, 0x00,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0x00,
+                USAGE_MAXIMUM(2),       0xff, 0x00,
+                INPUT(1),           0x00,
+                END_COLLECTION(0),
+
+                // Mouse
+                USAGE_PAGE(1), 0x01,               // Generic Desktop
+                USAGE(1), 0x02,                    // Mouse
+                COLLECTION(1), 0x01,               // Application
+                USAGE(1), 0x01,                    // Pointer
+                COLLECTION(1), 0x00,               // Physical
+                REPORT_ID(1),       REPORT_ID_MOUSE,
+
+                USAGE_PAGE(1), 0x01,                // Generic Desktop
+                USAGE(1), 0x30,                     // X
+                USAGE(1), 0x31,                     // Y
+                LOGICAL_MINIMUM(1), 0x00,           // 0
+                LOGICAL_MAXIMUM(2), 0xff, 0x7f,     // 32767
+                REPORT_SIZE(1), 0x10,
+                REPORT_COUNT(1), 0x02,
+                INPUT(1), 0x02,                     // Data, Variable, Absolute
+
+                USAGE_PAGE(1), 0x01,                // Generic Desktop
+                USAGE(1), 0x38,                     // scroll
+                LOGICAL_MINIMUM(1), 0x81,           // -127
+                LOGICAL_MAXIMUM(1), 0x7f,           // 127
+                REPORT_SIZE(1), 0x08,
+                REPORT_COUNT(1), 0x01,
+                INPUT(1), 0x06,                     // Data, Variable, Relative
+
+                USAGE_PAGE(1), 0x09,                // Buttons
+                USAGE_MINIMUM(1), 0x01,
+                USAGE_MAXIMUM(1), 0x03,
+                LOGICAL_MINIMUM(1), 0x00,           // 0
+                LOGICAL_MAXIMUM(1), 0x01,           // 1
+                REPORT_COUNT(1), 0x03,
+                REPORT_SIZE(1), 0x01,
+                INPUT(1), 0x02,                     // Data, Variable, Absolute
+                REPORT_COUNT(1), 0x01,
+                REPORT_SIZE(1), 0x05,
+                INPUT(1), 0x01,                     // Constant
+
+                END_COLLECTION(0),
+                END_COLLECTION(0),
+
+                // Media Control
+                USAGE_PAGE(1), 0x0C,
+                USAGE(1), 0x01,
+                COLLECTION(1), 0x01,
+                REPORT_ID(1), REPORT_ID_VOLUME,
+                USAGE_PAGE(1), 0x0C,
+                LOGICAL_MINIMUM(1), 0x00,
+                LOGICAL_MAXIMUM(1), 0x01,
+                REPORT_SIZE(1), 0x01,
+                REPORT_COUNT(1), 0x07,
+                USAGE(1), 0xB5,             // Next Track
+                USAGE(1), 0xB6,             // Previous Track
+                USAGE(1), 0xB7,             // Stop
+                USAGE(1), 0xCD,             // Play / Pause
+                USAGE(1), 0xE2,             // Mute
+                USAGE(1), 0xE9,             // Volume Up
+                USAGE(1), 0xEA,             // Volume Down
+                INPUT(1), 0x02,             // Input (Data, Variable, Absolute)
+                REPORT_COUNT(1), 0x01,
+                INPUT(1), 0x01,
+                END_COLLECTION(0),
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    }
+
+    return NULL;
+}
+
+bool USBMouseKeyboard::update(int16_t x, int16_t y, uint8_t button, int8_t z) {
+    switch (mouse_type) {
+    case REL_MOUSE:
+        while (x > 127) {
+            if (!mouseSend(127, 0, button, z)) return false;
+            x = x - 127;
+        }
+        while (x < -128) {
+            if (!mouseSend(-128, 0, button, z)) return false;
+            x = x + 128;
+        }
+        while (y > 127) {
+            if (!mouseSend(0, 127, button, z)) return false;
+            y = y - 127;
+        }
+        while (y < -128) {
+            if (!mouseSend(0, -128, button, z)) return false;
+            y = y + 128;
+        }
+        return mouseSend(x, y, button, z);
+    case ABS_MOUSE:
+        HID_REPORT report;
+
+        report.data[0] = REPORT_ID_MOUSE;
+        report.data[1] = x & 0xff;
+        report.data[2] = (x >> 8) & 0xff;
+        report.data[3] = y & 0xff;
+        report.data[4] = (y >> 8) & 0xff;
+        report.data[5] = -z;
+        report.data[6] = button & 0x07;
+
+        report.length = 7;
+
+        return send(&report);
+    default:
+        return false;
+    }
+}
+
+bool USBMouseKeyboard::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) {
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_MOUSE;
+    report.data[1] = buttons & 0x07;
+    report.data[2] = x;
+    report.data[3] = y;
+    report.data[4] = -z; // >0 to scroll down, <0 to scroll up
+
+    report.length = 5;
+
+    return send(&report);
+}
+
+bool USBMouseKeyboard::move(int16_t x, int16_t y) {
+    return update(x, y, button, 0);
+}
+
+bool USBMouseKeyboard::scroll(int8_t z) {
+    return update(0, 0, button, z);
+}
+
+bool USBMouseKeyboard::doubleClick() {
+    if (!click(MOUSE_LEFT))
+        return false;
+    wait(0.1);
+    return click(MOUSE_LEFT);
+}
+
+bool USBMouseKeyboard::click(uint8_t button) {
+    if (!update(0, 0, button, 0))
+        return false;
+    wait(0.01);
+    return update(0, 0, 0, 0);
+}
+
+bool USBMouseKeyboard::press(uint8_t button_) {
+    button = button_ & 0x07;
+    return update(0, 0, button, 0);
+}
+
+bool USBMouseKeyboard::release(uint8_t button_) {
+    button = (button & (~button_)) & 0x07;
+    return update(0, 0, button, 0);
+}
+
+int USBMouseKeyboard::_putc(int c) {
+    return keyCode(c, keymap[c].modifier);
+}
+
+bool USBMouseKeyboard::keyCode(uint8_t key, uint8_t modifier) {
+    // Send a simulated keyboard keypress. Returns true if successful.
+
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+
+    report.length = 9;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    return true;
+
+}
+
+
+bool USBMouseKeyboard::mediaControl(MEDIA_KEY key) {
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = (1 << key) & 0x7f;
+
+    report.length = 2;
+
+    send(&report);
+    
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+
+    report.length = 2;
+
+    return send(&report);
+}
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HID/USBMouseKeyboard.h	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,185 @@
+/* USBMouseKeyboard.h */
+/* USB device example: Keyboard with a relative mouse */
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+
+#ifndef USBMOUSEKEYBOARD_H
+#define USBMOUSEKEYBOARD_H
+
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_MOUSE 2
+#define REPORT_ID_VOLUME 3
+
+#include "USBMouse.h"
+#include "USBKeyboard.h"
+#include "Stream.h"
+#include "USBHID.h"
+
+/** 
+ * USBMouseKeyboard example
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBMouseKeyboard.h"
+ *
+ * USBMouseKeyboard key_mouse;
+ *
+ * int main(void)
+ * {
+ *   while(1)
+ *   {
+ *       key_mouse.move(20, 0);
+ *       key_mouse.puts("Hello From MBED\r\n");
+ *       wait(1);
+ *   }
+ * }
+ * @endcode
+ *
+ *
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBMouseKeyboard.h"
+ *
+ * USBMouseKeyboard key_mouse(ABS_MOUSE);
+ *
+ * int main(void)
+ * {
+ *   while(1)
+ *   {
+ *       key_mouse.move(X_MAX_ABS/2, Y_MAX_ABS/2);
+ *       key_mouse.puts("Hello from MBED\r\n");
+ *       wait(1);
+ *   }
+ * }
+ * @endcode
+ */
+class USBMouseKeyboard: public USBHID, public Stream
+{
+    public:
+    
+        /**
+        *   Constructor
+        *
+        * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE)
+        * @param vendor_id Your vendor_id (default: 0x1234)
+        * @param product_id Your product_id (default: 0x0001)
+        * @param product_release Your preoduct_release (default: 0x0001)
+        *
+        */
+        USBMouseKeyboard(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0010, uint16_t product_release = 0x0001): 
+            USBHID(vendor_id, product_id, product_release)
+            {
+                button = 0;
+                this->mouse_type = mouse_type;
+            };
+        
+        
+        /**
+        * Write a state of the mouse
+        *
+        * @param x x-axis position
+        * @param y y-axis position
+        * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE)
+        * @param z wheel state (>0 to scroll down, <0 to scroll up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z);
+        
+        
+        /**
+        * Move the cursor to (x, y)
+        *
+        * @param x x-axis position
+        * @param y y-axis position
+        * @returns true if there is no error, false otherwise
+        */
+        bool move(int16_t x, int16_t y);
+        
+        /**
+        * Press one or several buttons
+        *
+        * @param button button state (ex: press(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool press(uint8_t button);
+        
+        /**
+        * Release one or several buttons
+        *
+        * @param button button state (ex: release(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool release(uint8_t button);
+        
+        /**
+        * Double click (MOUSE_LEFT)
+        *
+        * @returns true if there is no error, false otherwise
+        */
+        bool doubleClick();
+        
+        /**
+        * Click
+        *
+        * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool click(uint8_t button); 
+        
+        /**
+        * Scrolling
+        *
+        * @param z value of the wheel (>0 to go down, <0 to go up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool scroll(int8_t z);
+
+        /**
+        * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key
+        *
+        * @code
+        * //To send CTRL + s (save)
+        *  keyboard.keyCode('s', KEY_CTRL);
+        * @endcode
+        *
+        * @param modifier bit 0: CTRL, bit 1: SHIFT, bit 2: ALT (default: 0)
+        * @param key character to send
+        * @returns true if there is no error, false otherwise
+        */
+        bool keyCode(uint8_t key, uint8_t modifier = 0);
+        
+        /**
+        * Send a character
+        *
+        * @param c character to be sent
+        * @returns true if there is no error, false otherwise
+        */
+        virtual int _putc(int c);
+        
+        /**
+        * Control media keys
+        *
+        * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN)
+        * @returns true if there is no error, false otherwise
+        */
+        bool mediaControl(MEDIA_KEY key);
+        
+        /**
+        * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+        *
+        * @returns pointer to the report descriptor
+        */
+        virtual uint8_t * reportDesc();
+        
+        
+    private:
+        bool mouseWrite(int8_t x, int8_t y, uint8_t buttons, int8_t z);
+        MOUSE_TYPE mouse_type;
+        uint8_t button;
+        bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
+        
+        //dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
+        virtual int _getc() { return -1;}
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,89 @@
+#include "mbed.h"
+#include "USBHID.h"
+/*
+DigitalOut myled1(LED1);
+DigitalOut myled2(LED2);
+DigitalOut myled3(LED3);
+DigitalOut myled4(LED4);
+*/
+BusOut leds(LED1,LED2,LED3,LED4);
+AnalogIn PortA (p20);
+AnalogIn PortB (p19);
+AnalogIn PortC (p18);
+AnalogIn PortD (p17);
+
+int a, x, t, k;
+int An_a, An_b, An_c, An_d;
+
+#define HID_MessageSize 18
+
+//This report will contain data to be sent
+HID_REPORT send_report;
+HID_REPORT recv;
+
+//We declare a USBHID device
+USBHID hid_A (HID_MessageSize, HID_MessageSize,0xcbc,0x123,5);     // In Length, Out Length, VID, PID, Release
+//USBHID hid_B (HID_MessageSize, HID_MessageSize,0xcbc,0x123,6);
+
+
+// Strings are in "USBDevice.cpp"
+
+
+//BusOut leds(LED1,LED2,LED3,LED4);
+
+int main(void) {
+
+    //Fill the report
+    for (int i = 0; i < HID_MessageSize; i++)
+        send_report.data[i] = i;
+    send_report.length = HID_MessageSize;
+    
+    //jjhhggrr
+
+    while (1) 
+    {
+        //Send the report
+
+//        if (hid_A.readNB(&recv)) 
+        {
+            leds = recv.data[0];
+            send_report.data[1]++;
+            
+            // just a test to see how fast send could be ..
+            
+            for (x=0; x<200;x++)
+            {
+              
+                An_a = PortA.read_u16();
+                An_b = PortB.read_u16();
+                An_c = PortC.read_u16();
+                An_d = PortD.read_u16();
+                
+                send_report.data[3] = An_a & 0xff;
+                send_report.data[2] = An_a >>8;
+                
+                send_report.data[5] = An_b & 0xff;
+                send_report.data[4] = An_b >>8;
+                
+                send_report.data[7] = An_c & 0xff;
+                send_report.data[6] = An_c >>8;
+                
+                send_report.data[9] = An_d & 0xff;
+                send_report.data[8] = An_d >>8;;  
+                
+                send_report.data[11] = k & 0xff;
+                send_report.data[10] = k >>8;    
+                
+                k++;                                          
+                
+                send_report.data[16] = x;
+                hid_A.send(&send_report);            
+            }
+            
+
+        }
+        send_report.data[HID_MessageSize-2]++;
+        hid_A.send(&send_report);
+        wait(0.5);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Nov 19 22:54:22 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912