Add simple USB CDC task.
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/FreeRTOSConfig.h b/Demo/CORTEX_LPC1768_GCC_Rowley/FreeRTOSConfig.h
index a879348..f0d90fd 100644
--- a/Demo/CORTEX_LPC1768_GCC_Rowley/FreeRTOSConfig.h
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/FreeRTOSConfig.h
@@ -64,7 +64,7 @@
 #define configUSE_IDLE_HOOK			0

 #define configMAX_PRIORITIES		( ( unsigned portBASE_TYPE ) 5 )

 #define configUSE_TICK_HOOK			1

-#define configCPU_CLOCK_HZ			( ( unsigned portLONG ) 64000000 )

+#define configCPU_CLOCK_HZ			( ( unsigned portLONG ) 99000000 )

 #define configTICK_RATE_HZ			( ( portTickType ) 1000 )

 #define configMINIMAL_STACK_SIZE	( ( unsigned portSHORT ) 80 )

 #define configTOTAL_HEAP_SIZE		( ( size_t ) ( 19 * 1024 ) )

@@ -133,9 +133,12 @@
 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( 5 << (8 - configPRIO_BITS) )

 

 /* Priorities passed to NVIC_SetPriority() do not require shifting as the

-function does the shifting itself. */

+function does the shifting itself.  Note these priorities need to be equal to

+or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the numeric

+value needs to be equal to or greater than 5 (on the Cortex M3 the lower the

+numeric value the higher the interrupt priority). */

 #define configEMAC_INTERRUPT_PRIORITY		5

-

+#define configUSB_INTERRUPT_PRIORITY		6

 

 

 

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/USB_CDC.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/USB_CDC.c
new file mode 100644
index 0000000..8b88bef
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/USB_CDC.c
@@ -0,0 +1,459 @@
+/*

+	LPCUSB, an USB device driver for LPC microcontrollers	

+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)

+

+	Redistribution and use in source and binary forms, with or without

+	modification, are permitted provided that the following conditions are met:

+

+	1. Redistributions of source code must retain the above copyright

+	   notice, this list of conditions and the following disclaimer.

+	2. Redistributions in binary form must reproduce the above copyright

+	   notice, this list of conditions and the following disclaimer in the

+	   documentation and/or other materials provided with the distribution.

+	3. The name of the author may not be used to endorse or promote products

+	   derived from this software without specific prior written permission.

+

+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR

+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.

+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 

+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+*/

+

+/*

+	Minimal implementation of a USB serial port, using the CDC class.

+	This example application simply echoes everything it receives right back

+	to the host.

+

+	Windows:

+	Extract the usbser.sys file from .cab file in C:\WINDOWS\Driver Cache\i386

+	and store it somewhere (C:\temp is a good place) along with the usbser.inf

+	file. Then plug in the LPC176x and direct windows to the usbser driver.

+	Windows then creates an extra COMx port that you can open in a terminal

+	program, like hyperterminal. [Note for FreeRTOS users - the required .inf

+	file is included in the project directory.]

+

+	Linux:

+	The device should be recognised automatically by the cdc_acm driver,

+	which creates a /dev/ttyACMx device file that acts just like a regular

+	serial port.

+

+*/

+

+#include "FreeRTOS.h"

+#include "queue.h"

+

+#include <stdio.h>

+#include <string.h>

+

+#include "usbapi.h"

+#include "usbdebug.h"

+#include "usbstruct.h"

+

+#include "LPC17xx.h"

+

+#define usbMAX_SEND_BLOCK		( 20 / portTICK_RATE_MS )

+#define usbBUFFER_LEN			( 20 )

+

+#define INCREMENT_ECHO_BY 1

+#define BAUD_RATE	115200

+

+#define INT_IN_EP		0x81

+#define BULK_OUT_EP		0x05

+#define BULK_IN_EP		0x82

+

+#define MAX_PACKET_SIZE	64

+

+#define LE_WORD(x)		((x)&0xFF),((x)>>8)

+

+// CDC definitions

+#define CS_INTERFACE			0x24

+#define CS_ENDPOINT				0x25

+

+#define	SET_LINE_CODING			0x20

+#define	GET_LINE_CODING			0x21

+#define	SET_CONTROL_LINE_STATE	0x22

+

+// data structure for GET_LINE_CODING / SET_LINE_CODING class requests

+typedef struct {

+	unsigned long		dwDTERate;

+	unsigned char		bCharFormat;

+	unsigned char		bParityType;

+	unsigned char		bDataBits;

+} TLineCoding;

+

+static TLineCoding LineCoding = {115200, 0, 0, 8};

+static unsigned char abBulkBuf[64];

+static unsigned char abClassReqData[8];

+

+static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;

+

+// forward declaration of interrupt handler

+void USBIntHandler(void);

+

+static const unsigned char abDescriptors[] = {

+

+// device descriptor

+	0x12,

+	DESC_DEVICE,

+	LE_WORD(0x0101),			// bcdUSB

+	0x02,						// bDeviceClass

+	0x00,						// bDeviceSubClass

+	0x00,						// bDeviceProtocol

+	MAX_PACKET_SIZE0,			// bMaxPacketSize

+	LE_WORD(0xFFFF),			// idVendor

+	LE_WORD(0x0005),			// idProduct

+	LE_WORD(0x0100),			// bcdDevice

+	0x01,						// iManufacturer

+	0x02,						// iProduct

+	0x03,						// iSerialNumber

+	0x01,						// bNumConfigurations

+

+// configuration descriptor

+	0x09,

+	DESC_CONFIGURATION,

+	LE_WORD(67),				// wTotalLength

+	0x02,						// bNumInterfaces

+	0x01,						// bConfigurationValue

+	0x00,						// iConfiguration

+	0xC0,						// bmAttributes

+	0x32,						// bMaxPower

+// control class interface

+	0x09,

+	DESC_INTERFACE,

+	0x00,						// bInterfaceNumber

+	0x00,						// bAlternateSetting

+	0x01,						// bNumEndPoints

+	0x02,						// bInterfaceClass

+	0x02,						// bInterfaceSubClass

+	0x01,						// bInterfaceProtocol, linux requires value of 1 for the cdc_acm module

+	0x00,						// iInterface

+// header functional descriptor

+	0x05,

+	CS_INTERFACE,

+	0x00,

+	LE_WORD(0x0110),

+// call management functional descriptor

+	0x05,

+	CS_INTERFACE,

+	0x01,

+	0x01,						// bmCapabilities = device handles call management

+	0x01,						// bDataInterface

+// ACM functional descriptor

+	0x04,

+	CS_INTERFACE,

+	0x02,

+	0x02,						// bmCapabilities

+// union functional descriptor

+	0x05,

+	CS_INTERFACE,

+	0x06,

+	0x00,						// bMasterInterface

+	0x01,						// bSlaveInterface0

+// notification EP

+	0x07,

+	DESC_ENDPOINT,

+	INT_IN_EP,					// bEndpointAddress

+	0x03,						// bmAttributes = intr

+	LE_WORD(8),					// wMaxPacketSize

+	0x0A,						// bInterval

+// data class interface descriptor

+	0x09,

+	DESC_INTERFACE,

+	0x01,						// bInterfaceNumber

+	0x00,						// bAlternateSetting

+	0x02,						// bNumEndPoints

+	0x0A,						// bInterfaceClass = data

+	0x00,						// bInterfaceSubClass

+	0x00,						// bInterfaceProtocol

+	0x00,						// iInterface

+// data EP OUT

+	0x07,

+	DESC_ENDPOINT,

+	BULK_OUT_EP,				// bEndpointAddress

+	0x02,						// bmAttributes = bulk

+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize

+	0x00,						// bInterval

+// data EP in

+	0x07,

+	DESC_ENDPOINT,

+	BULK_IN_EP,					// bEndpointAddress

+	0x02,						// bmAttributes = bulk

+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize

+	0x00,						// bInterval

+	

+	// string descriptors

+	0x04,

+	DESC_STRING,

+	LE_WORD(0x0409),

+

+	0x0E,

+	DESC_STRING,

+	'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,

+

+	0x14,

+	DESC_STRING,

+	'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,

+

+	0x12,

+	DESC_STRING,

+	'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,

+

+// terminating zero

+	0

+};

+

+

+/**

+	Local function to handle incoming bulk data

+		

+	@param [in] bEP

+	@param [in] bEPStatus

+ */

+static void BulkOut(unsigned char bEP, unsigned char bEPStatus)

+{

+	int i, iLen;

+	long lHigherPriorityTaskWoken = pdFALSE;

+

+	( void ) bEPStatus;

+	

+	// get data from USB into intermediate buffer

+	iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));

+	for (i = 0; i < iLen; i++) {

+		// put into queue

+		xQueueSendFromISR( xRxedChars, &( abBulkBuf[ i ] ), &lHigherPriorityTaskWoken ); 

+	}

+	

+	portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );

+}

+

+

+/**

+	Local function to handle outgoing bulk data

+		

+	@param [in] bEP

+	@param [in] bEPStatus

+ */

+static void BulkIn(unsigned char bEP, unsigned char bEPStatus)

+{

+	int i, iLen;

+	long lHigherPriorityTaskWoken = pdFALSE;

+

+	( void ) bEPStatus;

+	

+	if (uxQueueMessagesWaitingFromISR( xCharsForTx ) == 0) {

+		// no more data, disable further NAK interrupts until next USB frame

+		USBHwNakIntEnable(0);

+		return;

+	}

+

+	// get bytes from transmit FIFO into intermediate buffer

+	for (i = 0; i < MAX_PACKET_SIZE; i++) {

+		if( xQueueReceiveFromISR( xCharsForTx, ( &abBulkBuf[i] ), &lHigherPriorityTaskWoken ) != pdPASS )

+		{

+			break;

+		}

+	}

+	iLen = i;

+	

+	// send over USB

+	if (iLen > 0) {

+		USBHwEPWrite(bEP, abBulkBuf, iLen);

+	}

+	

+	portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );

+}

+

+

+/**

+	Local function to handle the USB-CDC class requests

+		

+	@param [in] pSetup

+	@param [out] piLen

+	@param [out] ppbData

+ */

+static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)

+{

+	switch (pSetup->bRequest) {

+

+	// set line coding

+	case SET_LINE_CODING:

+DBG("SET_LINE_CODING\n");

+		memcpy((unsigned char *)&LineCoding, *ppbData, 7);

+		*piLen = 7;

+DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",

+	LineCoding.dwDTERate,

+	LineCoding.bCharFormat,

+	LineCoding.bParityType,

+	LineCoding.bDataBits);

+		break;

+

+	// get line coding

+	case GET_LINE_CODING:

+DBG("GET_LINE_CODING\n");

+		*ppbData = (unsigned char *)&LineCoding;

+		*piLen = 7;

+		break;

+

+	// set control line state

+	case SET_CONTROL_LINE_STATE:

+		// bit0 = DTR, bit = RTS

+DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);

+		break;

+

+	default:

+		return FALSE;

+	}

+	return TRUE;

+}

+

+

+/**

+	Writes one character to VCOM port

+	

+	@param [in] c character to write

+	@returns character written, or EOF if character could not be written

+ */

+int VCOM_putchar(int c)

+{

+char cc = ( char ) c;

+

+	if( xQueueSend( xCharsForTx, &cc, usbMAX_SEND_BLOCK ) == pdPASS )

+	{

+		return c;

+	}

+	else

+	{

+		return EOF;

+	}

+}

+

+

+/**

+	Reads one character from VCOM port

+	

+	@returns character read, or EOF if character could not be read

+ */

+int VCOM_getchar(void)

+{

+	unsigned char c;

+	

+	/* Block the task until a character is available. */

+	xQueueReceive( xRxedChars, &c, portMAX_DELAY );

+	return c;

+}

+

+

+/**

+	Interrupt handler

+	

+	Simply calls the USB ISR

+ */

+//void USBIntHandler(void)

+void USB_IRQHandler(void)

+{

+	USBHwISR();

+}

+

+

+static void USBFrameHandler(unsigned short wFrame)

+{

+	( void ) wFrame;

+	

+	if( uxQueueMessagesWaitingFromISR( xCharsForTx ) > 0 )

+	{

+		// data available, enable NAK interrupt on bulk in

+		USBHwNakIntEnable(INACK_BI);

+	}

+}

+

+// CodeRed - added CPUcpsie

+

+unsigned long CPUcpsie(void)

+{

+    unsigned long ulRet;

+

+    //

+    // Read PRIMASK and enable interrupts.

+    //

+    __asm("    mrs     %0, PRIMASK\n"

+          "    cpsie   i\n"

+          "    bx      lr\n"

+          : "=r" (ulRet));

+

+    //

+    // The return is handled in the inline assembly, but the compiler will

+    // still complain if there is not an explicit return here (despite the fact

+    // that this does not result in any code being produced because of the

+    // naked attribute).

+    //

+    return(ulRet);

+}

+

+void vUSBTask( void *pvParameters )

+{

+	int c;

+	

+	/* Just to prevent compiler warnings about the unused parameter. */

+	( void ) pvParameters;

+	DBG("Initialising USB stack\n");

+

+	xRxedChars = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );

+	xCharsForTx = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );

+

+	if( ( xRxedChars == NULL ) || ( xCharsForTx == NULL ) )

+	{

+		/* Not enough heap available to create the buffer queues, can't do

+		anything so just delete ourselves. */

+		vTaskDelete( NULL );

+	}

+	

+	

+	// initialise stack

+	USBInit();

+

+	// register descriptors

+	USBRegisterDescriptors(abDescriptors);

+

+	// register class request handler

+	USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);

+

+	// register endpoint handlers

+	USBHwRegisterEPIntHandler(INT_IN_EP, NULL);

+	USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);

+	USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);

+	

+	// register frame handler

+	USBHwRegisterFrameHandler(USBFrameHandler);

+

+	// enable bulk-in interrupts on NAKs

+	USBHwNakIntEnable(INACK_BI);

+

+	DBG("Starting USB communication\n");

+

+	NVIC_SetPriority( USB_IRQn, configUSB_INTERRUPT_PRIORITY );

+	NVIC_EnableIRQ( USB_IRQn );

+		

+	// connect to bus

+		

+	DBG("Connecting to USB bus\n");

+	USBHwConnect(TRUE);

+

+	// echo any character received (do USB stuff in interrupt)

+	for( ;; )

+	{

+		c = VCOM_getchar();

+		if (c != EOF) 

+		{

+			// Echo character back with INCREMENT_ECHO_BY offset, so for example if

+			// INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.

+			VCOM_putchar(c + INCREMENT_ECHO_BY );

+		}

+	}

+}

+

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/type.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/type.h
new file mode 100644
index 0000000..89d3685
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/type.h
@@ -0,0 +1,38 @@
+/*****************************************************************************

+ *   type.h:  Type definition Header file for NXP LPC17xx Family 

+ *   Microprocessors

+ *

+ *   Copyright(C) 2008, NXP Semiconductor

+ *   All rights reserved.

+ *

+ *   History

+ *   2008.08.21  ver 1.00    Prelimnary version, first Release

+ *

+******************************************************************************/

+#ifndef __TYPE_H__

+#define __TYPE_H__

+

+#ifndef NULL

+#define NULL    ((void *)0)

+#endif

+

+#ifndef FALSE

+#define FALSE   (0)

+#endif

+

+#ifndef TRUE

+#define TRUE    (1)

+#endif

+

+typedef unsigned char  BYTE;

+typedef unsigned short WORD;

+typedef unsigned long  DWORD;

+typedef unsigned int   BOOL;

+

+typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;

+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;

+

+/* Pointer to Function returning Void (any number of parameters) */

+typedef void (*PFV)();

+

+#endif  /* __TYPE_H__ */

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbapi.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbapi.h
new file mode 100644
index 0000000..050f0d9
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbapi.h
@@ -0,0 +1,118 @@
+/*

+	LPCUSB, an USB device driver for LPC microcontrollers	

+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)

+

+	Redistribution and use in source and binary forms, with or without

+	modification, are permitted provided that the following conditions are met:

+

+	1. Redistributions of source code must retain the above copyright

+	   notice, this list of conditions and the following disclaimer.

+	2. Redistributions in binary form must reproduce the above copyright

+	   notice, this list of conditions and the following disclaimer in the

+	   documentation and/or other materials provided with the distribution.

+	3. The name of the author may not be used to endorse or promote products

+	   derived from this software without specific prior written permission.

+

+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR

+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.

+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 

+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+*/

+

+/**

+	@file

+*/

+

+#include "usbstruct.h"		// for TSetupPacket

+

+/*************************************************************************

+	USB configuration

+**************************************************************************/

+

+#define MAX_PACKET_SIZE0	64		/**< maximum packet size for EP 0 */

+

+/*************************************************************************

+	USB hardware interface

+**************************************************************************/

+

+// endpoint status sent through callback

+#define EP_STATUS_DATA		(1<<0)		/**< EP has data */

+#define EP_STATUS_STALLED	(1<<1)		/**< EP is stalled */

+#define EP_STATUS_SETUP		(1<<2)		/**< EP received setup packet */

+#define EP_STATUS_ERROR		(1<<3)		/**< EP data was overwritten by setup packet */

+#define EP_STATUS_NACKED	(1<<4)		/**< EP sent NAK */

+

+// device status sent through callback

+#define DEV_STATUS_CONNECT		(1<<0)	/**< device just got connected */

+#define DEV_STATUS_SUSPEND		(1<<2)	/**< device entered suspend state */

+#define DEV_STATUS_RESET		(1<<4)	/**< device just got reset */

+

+// interrupt bits for NACK events in USBHwNakIntEnable

+// (these bits conveniently coincide with the LPC176x USB controller bit)

+#define INACK_CI		(1<<1)			/**< interrupt on NACK for control in */

+#define INACK_CO		(1<<2)			/**< interrupt on NACK for control out */

+#define INACK_II		(1<<3)			/**< interrupt on NACK for interrupt in */

+#define INACK_IO		(1<<4)			/**< interrupt on NACK for interrupt out */

+#define INACK_BI		(1<<5)			/**< interrupt on NACK for bulk in */

+#define INACK_BO		(1<<6)			/**< interrupt on NACK for bulk out */

+

+BOOL USBHwInit			(void);

+void USBHwISR			(void);

+

+void USBHwNakIntEnable	(unsigned char bIntBits);

+

+void USBHwConnect		(BOOL fConnect);

+

+void USBHwSetAddress	(unsigned char bAddr);

+void USBHwConfigDevice	(BOOL fConfigured);

+

+// endpoint operations

+void USBHwEPConfig		(unsigned char bEP, unsigned short wMaxPacketSize);

+int  USBHwEPRead		(unsigned char bEP, unsigned char *pbBuf, int iMaxLen);

+int	 USBHwEPWrite		(unsigned char bEP, unsigned char *pbBuf, int iLen);

+void USBHwEPStall		(unsigned char bEP, BOOL fStall);

+unsigned char   USBHwEPGetStatus	(unsigned char bEP);

+

+/** Endpoint interrupt handler callback */

+typedef void (TFnEPIntHandler)	(unsigned char bEP, unsigned char bEPStatus);

+void USBHwRegisterEPIntHandler	(unsigned char bEP, TFnEPIntHandler *pfnHandler);

+

+/** Device status handler callback */

+typedef void (TFnDevIntHandler)	(unsigned char bDevStatus);

+void USBHwRegisterDevIntHandler	(TFnDevIntHandler *pfnHandler);

+

+/** Frame event handler callback */

+typedef void (TFnFrameHandler)(unsigned short wFrame);

+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler);

+

+

+/*************************************************************************

+	USB application interface

+**************************************************************************/

+

+// initialise the complete stack, including HW

+BOOL USBInit(void);

+

+/** Request handler callback (standard, vendor, class) */

+typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);

+void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore);

+void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler);

+

+/** Descriptor handler callback */

+typedef BOOL (TFnGetDescriptor)(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);

+

+/** Default standard request handler */

+BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);

+

+/** Default EP0 handler */

+void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat);

+

+/** Descriptor handling */

+void USBRegisterDescriptors(const unsigned char *pabDescriptors);

+BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbcontrol.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbcontrol.c
new file mode 100644
index 0000000..18ff180
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbcontrol.c
@@ -0,0 +1,246 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers	
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+	Control transfer handler.
+	
+	This module handles control transfers and is normally installed on the
+	endpoint 0 callback.
+	
+	Control transfers can be of the following type:
+	0 Standard;
+	1 Class;
+	2 Vendor;
+	3 Reserved.
+
+	A callback can be installed for each of these control transfers using
+	USBRegisterRequestHandler.
+	When an OUT request arrives, data is collected in the data store provided
+	with the USBRegisterRequestHandler call. When the transfer is done, the
+	callback is called.
+	When an IN request arrives, the callback is called immediately to either
+	put the control transfer data in the data store, or to get a pointer to
+	control transfer data. The data is then packetised and sent to the host.
+*/
+
+#include "usbdebug.h"
+
+#include "usbstruct.h"
+#include "usbapi.h"
+
+
+
+#define	MAX_CONTROL_SIZE	128	/**< maximum total size of control transfer data */
+#define	MAX_REQ_HANDLERS	4	/**< standard, class, vendor, reserved */
+
+static TSetupPacket		Setup;	/**< setup packet */
+
+static unsigned char				*pbData;	/**< pointer to data buffer */
+static int				iResidue;	/**< remaining bytes in buffer */
+static int				iLen;		/**< total length of control transfer */
+
+/** Array of installed request handler callbacks */
+static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL};
+/** Array of installed request data pointers */
+static unsigned char				*apbDataStore[4] = {NULL, NULL, NULL, NULL};
+
+/**
+	Local function to handle a request by calling one of the installed
+	request handlers.
+		
+	In case of data going from host to device, the data is at *ppbData.
+	In case of data going from device to host, the handler can either
+	choose to write its data at *ppbData or update the data pointer.
+		
+	@param [in]		pSetup		The setup packet
+	@param [in,out]	*piLen		Pointer to data length
+	@param [in,out]	ppbData		Data buffer.
+
+	@return TRUE if the request was handles successfully
+ */
+static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
+{
+	TFnHandleRequest *pfnHandler;
+	int iType;
+	
+	iType = REQTYPE_GET_TYPE(pSetup->bmRequestType);
+	pfnHandler = apfnReqHandlers[iType];
+	if (pfnHandler == NULL) {
+		DBG("No handler for reqtype %d\n", iType);
+		return FALSE;
+	}
+
+	return pfnHandler(pSetup, piLen, ppbData);
+}
+
+
+/**
+	Local function to stall the control endpoint
+	
+	@param [in]	bEPStat	Endpoint status
+ */
+static void StallControlPipe(unsigned char bEPStat)
+{
+	unsigned char	*pb;
+	int	i;
+
+	USBHwEPStall(0x80, TRUE);
+
+// dump setup packet
+	DBG("STALL on [");
+	pb = (unsigned char *)&Setup;
+	for (i = 0; i < 8; i++) {
+		DBG(" %02x", *pb++);
+	}
+	DBG("] stat=%x\n", bEPStat);
+}
+
+
+/**
+	Sends next chunk of data (possibly 0 bytes) to host
+ */
+static void DataIn(void)
+{
+	int iChunk;
+
+	if( MAX_PACKET_SIZE0 < iResidue )
+	{
+		iChunk = MAX_PACKET_SIZE0;
+	}
+	else
+	{
+		iChunk = iResidue;
+	}
+
+	USBHwEPWrite(0x80, pbData, iChunk);
+	pbData += iChunk;
+	iResidue -= iChunk;
+}
+
+
+/**
+ *	Handles IN/OUT transfers on EP0
+ *
+ *	@param [in]	bEP		Endpoint address
+ *	@param [in]	bEPStat	Endpoint status
+ */
+void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat)
+{
+	int iChunk, iType;
+
+	if (bEP == 0x00) {
+		// OUT transfer
+		if (bEPStat & EP_STATUS_SETUP) {
+			// setup packet, reset request message state machine
+			USBHwEPRead(0x00, (unsigned char *)&Setup, sizeof(Setup));
+			DBG("S%x", Setup.bRequest);
+
+			// defaults for data pointer and residue
+			iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
+			pbData = apbDataStore[iType];
+			iResidue = Setup.wLength;
+			iLen = Setup.wLength;
+
+			if ((Setup.wLength == 0) ||
+				(REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) {
+				// ask installed handler to process request
+				if (!_HandleRequest(&Setup, &iLen, &pbData)) {
+					DBG("_HandleRequest1 failed\n");
+					StallControlPipe(bEPStat);
+					return;
+				}
+				// send smallest of requested and offered length
+				if( iLen < Setup.wLength )
+				{
+					iResidue = iLen;
+				}
+				else
+				{
+					iResidue = Setup.wLength;
+				}
+
+				// send first part (possibly a zero-length status message)
+				DataIn();
+			}
+		}
+		else {		
+			if (iResidue > 0) {
+				// store data
+				iChunk = USBHwEPRead(0x00, pbData, iResidue);
+				if (iChunk < 0) {
+					StallControlPipe(bEPStat);
+					return;
+				}
+				pbData += iChunk;
+				iResidue -= iChunk;
+				if (iResidue == 0) {
+					// received all, send data to handler
+					iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
+					pbData = apbDataStore[iType];
+					if (!_HandleRequest(&Setup, &iLen, &pbData)) {
+						DBG("_HandleRequest2 failed\n");
+						StallControlPipe(bEPStat);
+						return;
+					}
+					// send status to host
+					DataIn();
+				}
+			}
+			else {
+				// absorb zero-length status message
+				iChunk = USBHwEPRead(0x00, NULL, 0);
+				DBG(iChunk > 0 ? "?" : "");
+			}
+		}
+	}
+	else if (bEP == 0x80) {
+		// IN transfer
+		// send more data if available (possibly a 0-length packet)
+		DataIn();
+	}
+	else {
+		ASSERT(FALSE);
+	}
+}
+
+
+/**
+	Registers a callback for handling requests
+		
+	@param [in]	iType			Type of request, e.g. REQTYPE_TYPE_STANDARD
+	@param [in]	*pfnHandler		Callback function pointer
+	@param [in]	*pbDataStore	Data storage area for this type of request
+ */
+void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore)
+{
+	ASSERT(iType >= 0);
+	ASSERT(iType < 4);
+	apfnReqHandlers[iType] = pfnHandler;
+	apbDataStore[iType] = pbDataStore;
+}
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbdebug.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbdebug.h
new file mode 100644
index 0000000..4a14862
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbdebug.h
@@ -0,0 +1,41 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers	
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// CodeRed - comment out this printf, as will use real one from stdio.h
+// to implement output via semihosting
+
+//int printf(const char *format, ...);
+# include <stdio.h>
+
+#ifdef _DEBUG
+#define DBG	printf
+#define ASSERT(x)	if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);}
+#else
+#define DBG(x ...)
+#define ASSERT(x)
+#endif
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c
new file mode 100644
index 0000000..e9bd460
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c
@@ -0,0 +1,521 @@
+/*

+	LPCUSB, an USB device driver for LPC microcontrollers

+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)

+

+	Redistribution and use in source and binary forms, with or without

+	modification, are permitted provided that the following conditions are met:

+

+	1. Redistributions of source code must retain the above copyright

+	   notice, this list of conditions and the following disclaimer.

+	2. Redistributions in binary form must reproduce the above copyright

+	   notice, this list of conditions and the following disclaimer in the

+	   documentation and/or other materials provided with the distribution.

+	3. The name of the author may not be used to endorse or promote products

+	   derived from this software without specific prior written permission.

+

+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR

+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.

+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,

+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+*/

+

+

+/** @file

+	USB hardware layer

+ */

+

+

+#include "usbdebug.h"

+#include "usbhw_lpc.h"

+#include "usbapi.h"

+

+/** Installed device interrupt handler */

+static TFnDevIntHandler *_pfnDevIntHandler = NULL;

+/** Installed endpoint interrupt handlers */

+static TFnEPIntHandler	*_apfnEPIntHandlers[16];

+/** Installed frame interrupt handlers */

+static TFnFrameHandler	*_pfnFrameHandler = NULL;

+

+/** convert from endpoint address to endpoint index */

+#define EP2IDX(bEP)	((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))

+/** convert from endpoint index to endpoint address */

+#define IDX2EP(idx)	((((idx)<<7)&0x80)|(((idx)>>1)&0xF))

+

+

+

+/**

+	Local function to wait for a device interrupt (and clear it)

+

+	@param [in]	dwIntr		Bitmask of interrupts to wait for

+ */

+static void Wait4DevInt(unsigned long dwIntr)

+{

+	// wait for specific interrupt

+	while ((USB->USBDevIntSt & dwIntr) != dwIntr);

+	// clear the interrupt bits

+	USB->USBDevIntClr = dwIntr;

+}

+

+

+/**

+	Local function to send a command to the USB protocol engine

+

+	@param [in]	bCmd		Command to send

+ */

+static void USBHwCmd(unsigned char bCmd)

+{

+	// clear CDFULL/CCEMTY

+	USB->USBDevIntClr = CDFULL | CCEMTY;

+	// write command code

+	USB->USBCmdCode = 0x00000500 | (bCmd << 16);

+	Wait4DevInt(CCEMTY);

+}

+

+

+/**

+	Local function to send a command + data to the USB protocol engine

+

+	@param [in]	bCmd		Command to send

+	@param [in]	bData		Data to send

+ */

+static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData)

+{

+	// write command code

+	USBHwCmd(bCmd);

+

+	// write command data

+	USB->USBCmdCode = 0x00000100 | (bData << 16);

+	Wait4DevInt(CCEMTY);

+}

+

+

+/**

+	Local function to send a command to the USB protocol engine and read data

+

+	@param [in]	bCmd		Command to send

+

+	@return the data

+ */

+static unsigned char USBHwCmdRead(unsigned char bCmd)

+{

+	// write command code

+	USBHwCmd(bCmd);

+

+	// get data

+	USB->USBCmdCode = 0x00000200 | (bCmd << 16);

+	Wait4DevInt(CDFULL);

+	return USB->USBCmdData;

+}

+

+

+/**

+	'Realizes' an endpoint, meaning that buffer space is reserved for

+	it. An endpoint needs to be realised before it can be used.

+

+	From experiments, it appears that a USB reset causes USBReEP to

+	re-initialise to 3 (= just the control endpoints).

+	However, a USB bus reset does not disturb the USBMaxPSize settings.

+

+	@param [in]	idx			Endpoint index

+	@param [in] wMaxPSize	Maximum packet size for this endpoint

+ */

+static void USBHwEPRealize(int idx, unsigned short wMaxPSize)

+{

+	USB->USBReEP |= (1 << idx);

+	USB->USBEpInd = idx;

+	USB->USBMaxPSize = wMaxPSize;

+	Wait4DevInt(EP_RLZED);

+}

+

+

+/**

+	Enables or disables an endpoint

+

+	@param [in]	idx		Endpoint index

+	@param [in]	fEnable	TRUE to enable, FALSE to disable

+ */

+static void USBHwEPEnable(int idx, BOOL fEnable)

+{

+	USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);

+}

+

+

+/**

+	Configures an endpoint and enables it

+

+	@param [in]	bEP				Endpoint number

+	@param [in]	wMaxPacketSize	Maximum packet size for this EP

+ */

+void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize)

+{

+	int idx;

+

+	idx = EP2IDX(bEP);

+

+	// realise EP

+	USBHwEPRealize(idx, wMaxPacketSize);

+

+	// enable EP

+	USBHwEPEnable(idx, TRUE);

+}

+

+

+/**

+	Registers an endpoint event callback

+

+	@param [in]	bEP				Endpoint number

+	@param [in]	pfnHandler		Callback function

+ */

+void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler)

+{

+	int idx;

+

+	idx = EP2IDX(bEP);

+

+	ASSERT(idx<32);

+

+	/* add handler to list of EP handlers */

+	_apfnEPIntHandlers[idx / 2] = pfnHandler;

+

+	/* enable EP interrupt */

+	USB->USBEpIntEn |= (1 << idx);

+	USB->USBDevIntEn |= EP_SLOW;

+

+	DBG("Registered handler for EP 0x%x\n", bEP);

+}

+

+

+/**

+	Registers an device status callback

+

+	@param [in]	pfnHandler	Callback function

+ */

+void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)

+{

+	_pfnDevIntHandler = pfnHandler;

+

+	// enable device interrupt

+	USB->USBDevIntEn |= DEV_STAT;

+

+	DBG("Registered handler for device status\n");

+}

+

+

+/**

+	Registers the frame callback

+

+	@param [in]	pfnHandler	Callback function

+ */

+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)

+{

+	_pfnFrameHandler = pfnHandler;

+

+	// enable device interrupt

+	USB->USBDevIntEn |= FRAME;

+

+	DBG("Registered handler for frame\n");

+}

+

+

+/**

+	Sets the USB address.

+

+	@param [in]	bAddr		Device address to set

+ */

+void USBHwSetAddress(unsigned char bAddr)

+{

+	USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);

+}

+

+

+/**

+	Connects or disconnects from the USB bus

+

+	@param [in]	fConnect	If TRUE, connect, otherwise disconnect

+ */

+void USBHwConnect(BOOL fConnect)

+{

+	USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);

+}

+

+

+/**

+	Enables interrupt on NAK condition

+

+	For IN endpoints a NAK is generated when the host wants to read data

+	from the device, but none is available in the endpoint buffer.

+	For OUT endpoints a NAK is generated when the host wants to write data

+	to the device, but the endpoint buffer is still full.

+

+	The endpoint interrupt handlers can distinguish regular (ACK) interrupts

+	from NAK interrupt by checking the bits in their bEPStatus argument.

+

+	@param [in]	bIntBits	Bitmap indicating which NAK interrupts to enable

+ */

+void USBHwNakIntEnable(unsigned char bIntBits)

+{

+	USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);

+}

+

+

+/**

+	Gets the status from a specific endpoint.

+

+	@param [in]	bEP		Endpoint number

+	@return Endpoint status byte (containing EP_STATUS_xxx bits)

+ */

+unsigned char	USBHwEPGetStatus(unsigned char bEP)

+{

+	int idx = EP2IDX(bEP);

+

+	return USBHwCmdRead(CMD_EP_SELECT | idx);

+}

+

+

+/**

+	Sets the stalled property of an endpoint

+

+	@param [in]	bEP		Endpoint number

+	@param [in]	fStall	TRUE to stall, FALSE to unstall

+ */

+void USBHwEPStall(unsigned char bEP, BOOL fStall)

+{

+	int idx = EP2IDX(bEP);

+

+	USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);

+}

+

+

+/**

+	Writes data to an endpoint buffer

+

+	@param [in]	bEP		Endpoint number

+	@param [in]	pbBuf	Endpoint data

+	@param [in]	iLen	Number of bytes to write

+

+	@return TRUE if the data was successfully written or <0 in case of error.

+*/

+int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen)

+{

+	int idx;

+

+	idx = EP2IDX(bEP);

+

+	// set write enable for specific endpoint

+	USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);

+

+	// set packet length

+	USB->USBTxPLen = iLen;

+

+	// write data

+	while (USB->USBCtrl & WR_EN) {

+		USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];

+		pbBuf += 4;

+	}

+

+	// select endpoint and validate buffer

+	USBHwCmd(CMD_EP_SELECT | idx);

+	USBHwCmd(CMD_EP_VALIDATE_BUFFER);

+

+	return iLen;

+}

+

+

+/**

+	Reads data from an endpoint buffer

+

+	@param [in]	bEP		Endpoint number

+	@param [in]	pbBuf	Endpoint data

+	@param [in]	iMaxLen	Maximum number of bytes to read

+

+	@return the number of bytes available in the EP (possibly more than iMaxLen),

+	or <0 in case of error.

+ */

+int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen)

+{

+	unsigned int i, idx;

+	unsigned long	dwData, dwLen;

+

+	idx = EP2IDX(bEP);

+

+	// set read enable bit for specific endpoint

+	USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);

+

+	// wait for PKT_RDY

+	do {

+		dwLen = USB->USBRxPLen;

+	} while ((dwLen & PKT_RDY) == 0);

+

+	// packet valid?

+	if ((dwLen & DV) == 0) {

+		return -1;

+	}

+

+	// get length

+	dwLen &= PKT_LNGTH_MASK;

+

+	// get data

+	dwData = 0;

+	for (i = 0; i < dwLen; i++) {

+		if ((i % 4) == 0) {

+			dwData = USB->USBRxData;

+		}

+		if ((pbBuf != NULL) && ((int)i < iMaxLen)) {

+			pbBuf[i] = dwData & 0xFF;

+		}

+		dwData >>= 8;

+	}

+

+	// make sure RD_EN is clear

+	USB->USBCtrl = 0;

+

+	// select endpoint and clear buffer

+	USBHwCmd(CMD_EP_SELECT | idx);

+	USBHwCmd(CMD_EP_CLEAR_BUFFER);

+

+	return dwLen;

+}

+

+

+/**

+	Sets the 'configured' state.

+

+	All registered endpoints are 'realised' and enabled, and the

+	'configured' bit is set in the device status register.

+

+	@param [in]	fConfigured	If TRUE, configure device, else unconfigure

+ */

+void USBHwConfigDevice(BOOL fConfigured)

+{

+	// set configured bit

+	USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);

+}

+

+

+/**

+	USB interrupt handler

+

+	@todo Get all 11 bits of frame number instead of just 8

+

+	Endpoint interrupts are mapped to the slow interrupt

+ */

+void USBHwISR(void)

+{

+	unsigned long	dwStatus;

+	unsigned long dwIntBit;

+	unsigned char	bEPStat, bDevStat, bStat;

+	int i;

+	unsigned short	wFrame;

+

+	// handle device interrupts

+	dwStatus = USB->USBDevIntSt;

+

+	// frame interrupt

+	if (dwStatus & FRAME) {

+		// clear int

+		USB->USBDevIntClr = FRAME;

+		// call handler

+		if (_pfnFrameHandler != NULL) {

+			wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);

+			_pfnFrameHandler(wFrame);

+		}

+	}

+

+	// device status interrupt

+	if (dwStatus & DEV_STAT) {

+		/*	Clear DEV_STAT interrupt before reading DEV_STAT register.

+			This prevents corrupted device status reads, see

+			LPC2148 User manual revision 2, 25 july 2006.

+		*/

+		USB->USBDevIntClr = DEV_STAT;

+		bDevStat = USBHwCmdRead(CMD_DEV_STATUS);

+		if (bDevStat & (CON_CH | SUS_CH | RST)) {

+			// convert device status into something HW independent

+			bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |

+					((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |

+					((bDevStat & RST) ? DEV_STATUS_RESET : 0);

+			// call handler

+			if (_pfnDevIntHandler != NULL) {

+				_pfnDevIntHandler(bStat);

+			}

+		}

+	}

+

+	// endpoint interrupt

+	if (dwStatus & EP_SLOW) {

+		// clear EP_SLOW

+		USB->USBDevIntClr = EP_SLOW;

+		// check all endpoints

+		for (i = 0; i < 32; i++) {

+			dwIntBit = (1 << i);

+			if (USB->USBEpIntSt & dwIntBit) {

+				// clear int (and retrieve status)

+				USB->USBEpIntClr = dwIntBit;

+				Wait4DevInt(CDFULL);

+				bEPStat = USB->USBCmdData;

+				// convert EP pipe stat into something HW independent

+				bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |

+						((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |

+						((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |

+						((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |

+						((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);

+				// call handler

+				if (_apfnEPIntHandlers[i / 2] != NULL) {

+					_apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);

+				}

+			}

+		}

+	}

+}

+

+

+

+/**

+	Initialises the USB hardware

+

+

+	@return TRUE if the hardware was successfully initialised

+ */

+BOOL USBHwInit(void)

+{

+	// P2.9 -> USB_CONNECT

+	PINCON->PINSEL4 &= ~0x000C0000;

+	PINCON->PINSEL4 |= 0x00040000;

+

+	// P1.18 -> USB_UP_LED

+	// P1.30 -> VBUS

+	PINCON->PINSEL3 &= ~0x30000030;

+	PINCON->PINSEL3 |= 0x20000010;

+

+	// P0.29 -> USB_D+

+	// P0.30 -> USB_D-

+	PINCON->PINSEL1 &= ~0x3C000000;

+	PINCON->PINSEL1 |= 0x14000000;

+

+	// enable PUSB

+	SC->PCONP |= (1 << 31);

+

+	USB->OTGClkCtrl = 0x12;	                  /* Dev clock, AHB clock enable  */

+	while ((USB->OTGClkSt & 0x12) != 0x12);

+

+	// disable/clear all interrupts for now

+	USB->USBDevIntEn = 0;

+	USB->USBDevIntClr = 0xFFFFFFFF;

+	USB->USBDevIntPri = 0;

+

+	USB->USBEpIntEn = 0;

+	USB->USBEpIntClr = 0xFFFFFFFF;

+	USB->USBEpIntPri = 0;

+

+	// by default, only ACKs generate interrupts

+	USBHwNakIntEnable(0);

+

+	return TRUE;

+}

+

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c.bak b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c.bak
new file mode 100644
index 0000000..29de3de
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c.bak
@@ -0,0 +1,521 @@
+/*

+	LPCUSB, an USB device driver for LPC microcontrollers

+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)

+

+	Redistribution and use in source and binary forms, with or without

+	modification, are permitted provided that the following conditions are met:

+

+	1. Redistributions of source code must retain the above copyright

+	   notice, this list of conditions and the following disclaimer.

+	2. Redistributions in binary form must reproduce the above copyright

+	   notice, this list of conditions and the following disclaimer in the

+	   documentation and/or other materials provided with the distribution.

+	3. The name of the author may not be used to endorse or promote products

+	   derived from this software without specific prior written permission.

+

+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR

+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.

+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,

+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+*/

+

+

+/** @file

+	USB hardware layer

+ */

+

+

+#include "usbdebug.h"

+#include "usbhw_lpc.h"

+#include "usbapi.h"

+

+/** Installed device interrupt handler */

+static TFnDevIntHandler *_pfnDevIntHandler = NULL;

+/** Installed endpoint interrupt handlers */

+static TFnEPIntHandler	*_apfnEPIntHandlers[16];

+/** Installed frame interrupt handlers */

+static TFnFrameHandler	*_pfnFrameHandler = NULL;

+

+/** convert from endpoint address to endpoint index */

+#define EP2IDX(bEP)	((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))

+/** convert from endpoint index to endpoint address */

+#define IDX2EP(idx)	((((idx)<<7)&0x80)|(((idx)>>1)&0xF))

+

+

+

+/**

+	Local function to wait for a device interrupt (and clear it)

+

+	@param [in]	dwIntr		Bitmask of interrupts to wait for

+ */

+static void Wait4DevInt(unsigned long dwIntr)

+{

+	// wait for specific interrupt

+	while ((USB->USBDevIntSt & dwIntr) != dwIntr);

+	// clear the interrupt bits

+	USB->USBDevIntClr = dwIntr;

+}

+

+

+/**

+	Local function to send a command to the USB protocol engine

+

+	@param [in]	bCmd		Command to send

+ */

+static void USBHwCmd(unsigned char bCmd)

+{

+	// clear CDFULL/CCEMTY

+	USB->USBDevIntClr = CDFULL | CCEMTY;

+	// write command code

+	USB->USBCmdCode = 0x00000500 | (bCmd << 16);

+	Wait4DevInt(CCEMTY);

+}

+

+

+/**

+	Local function to send a command + data to the USB protocol engine

+

+	@param [in]	bCmd		Command to send

+	@param [in]	bData		Data to send

+ */

+static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData)

+{

+	// write command code

+	USBHwCmd(bCmd);

+

+	// write command data

+	USB->USBCmdCode = 0x00000100 | (bData << 16);

+	Wait4DevInt(CCEMTY);

+}

+

+

+/**

+	Local function to send a command to the USB protocol engine and read data

+

+	@param [in]	bCmd		Command to send

+

+	@return the data

+ */

+static unsigned char USBHwCmdRead(unsigned char bCmd)

+{

+	// write command code

+	USBHwCmd(bCmd);

+

+	// get data

+	USB->USBCmdCode = 0x00000200 | (bCmd << 16);

+	Wait4DevInt(CDFULL);

+	return USB->USBCmdData;

+}

+

+

+/**

+	'Realizes' an endpoint, meaning that buffer space is reserved for

+	it. An endpoint needs to be realised before it can be used.

+

+	From experiments, it appears that a USB reset causes USBReEP to

+	re-initialise to 3 (= just the control endpoints).

+	However, a USB bus reset does not disturb the USBMaxPSize settings.

+

+	@param [in]	idx			Endpoint index

+	@param [in] wMaxPSize	Maximum packet size for this endpoint

+ */

+static void USBHwEPRealize(int idx, unsigned short wMaxPSize)

+{

+	USB->USBReEP |= (1 << idx);

+	USB->USBEpInd = idx;

+	USB->USBMaxPSize = wMaxPSize;

+	Wait4DevInt(EP_RLZED);

+}

+

+

+/**

+	Enables or disables an endpoint

+

+	@param [in]	idx		Endpoint index

+	@param [in]	fEnable	TRUE to enable, FALSE to disable

+ */

+static void USBHwEPEnable(int idx, BOOL fEnable)

+{

+	USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);

+}

+

+

+/**

+	Configures an endpoint and enables it

+

+	@param [in]	bEP				Endpoint number

+	@param [in]	wMaxPacketSize	Maximum packet size for this EP

+ */

+void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize)

+{

+	int idx;

+

+	idx = EP2IDX(bEP);

+

+	// realise EP

+	USBHwEPRealize(idx, wMaxPacketSize);

+

+	// enable EP

+	USBHwEPEnable(idx, TRUE);

+}

+

+

+/**

+	Registers an endpoint event callback

+

+	@param [in]	bEP				Endpoint number

+	@param [in]	pfnHandler		Callback function

+ */

+void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler)

+{

+	int idx;

+

+	idx = EP2IDX(bEP);

+

+	ASSERT(idx<32);

+

+	/* add handler to list of EP handlers */

+	_apfnEPIntHandlers[idx / 2] = pfnHandler;

+

+	/* enable EP interrupt */

+	USB->USBEpIntEn |= (1 << idx);

+	USB->USBDevIntEn |= EP_SLOW;

+

+	DBG("Registered handler for EP 0x%x\n", bEP);

+}

+

+

+/**

+	Registers an device status callback

+

+	@param [in]	pfnHandler	Callback function

+ */

+void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)

+{

+	_pfnDevIntHandler = pfnHandler;

+

+	// enable device interrupt

+	USB->USBDevIntEn |= DEV_STAT;

+

+	DBG("Registered handler for device status\n");

+}

+

+

+/**

+	Registers the frame callback

+

+	@param [in]	pfnHandler	Callback function

+ */

+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)

+{

+	_pfnFrameHandler = pfnHandler;

+

+	// enable device interrupt

+	USB->USBDevIntEn |= FRAME;

+

+	DBG("Registered handler for frame\n");

+}

+

+

+/**

+	Sets the USB address.

+

+	@param [in]	bAddr		Device address to set

+ */

+void USBHwSetAddress(unsigned char bAddr)

+{

+	USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);

+}

+

+

+/**

+	Connects or disconnects from the USB bus

+

+	@param [in]	fConnect	If TRUE, connect, otherwise disconnect

+ */

+void USBHwConnect(BOOL fConnect)

+{

+	USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);

+}

+

+

+/**

+	Enables interrupt on NAK condition

+

+	For IN endpoints a NAK is generated when the host wants to read data

+	from the device, but none is available in the endpoint buffer.

+	For OUT endpoints a NAK is generated when the host wants to write data

+	to the device, but the endpoint buffer is still full.

+

+	The endpoint interrupt handlers can distinguish regular (ACK) interrupts

+	from NAK interrupt by checking the bits in their bEPStatus argument.

+

+	@param [in]	bIntBits	Bitmap indicating which NAK interrupts to enable

+ */

+void USBHwNakIntEnable(unsigned char bIntBits)

+{

+	USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);

+}

+

+

+/**

+	Gets the status from a specific endpoint.

+

+	@param [in]	bEP		Endpoint number

+	@return Endpoint status byte (containing EP_STATUS_xxx bits)

+ */

+unsigned char	USBHwEPGetStatus(unsigned char bEP)

+{

+	int idx = EP2IDX(bEP);

+

+	return USBHwCmdRead(CMD_EP_SELECT | idx);

+}

+

+

+/**

+	Sets the stalled property of an endpoint

+

+	@param [in]	bEP		Endpoint number

+	@param [in]	fStall	TRUE to stall, FALSE to unstall

+ */

+void USBHwEPStall(unsigned char bEP, BOOL fStall)

+{

+	int idx = EP2IDX(bEP);

+

+	USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);

+}

+

+

+/**

+	Writes data to an endpoint buffer

+

+	@param [in]	bEP		Endpoint number

+	@param [in]	pbBuf	Endpoint data

+	@param [in]	iLen	Number of bytes to write

+

+	@return TRUE if the data was successfully written or <0 in case of error.

+*/

+int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen)

+{

+	int idx;

+

+	idx = EP2IDX(bEP);

+

+	// set write enable for specific endpoint

+	USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);

+

+	// set packet length

+	USB->USBTxPLen = iLen;

+

+	// write data

+	while (USB->USBCtrl & WR_EN) {

+		USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];

+		pbBuf += 4;

+	}

+

+	// select endpoint and validate buffer

+	USBHwCmd(CMD_EP_SELECT | idx);

+	USBHwCmd(CMD_EP_VALIDATE_BUFFER);

+

+	return iLen;

+}

+

+

+/**

+	Reads data from an endpoint buffer

+

+	@param [in]	bEP		Endpoint number

+	@param [in]	pbBuf	Endpoint data

+	@param [in]	iMaxLen	Maximum number of bytes to read

+

+	@return the number of bytes available in the EP (possibly more than iMaxLen),

+	or <0 in case of error.

+ */

+int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen)

+{

+	unsigned int i, idx;

+	unsigned long	dwData, dwLen;

+

+	idx = EP2IDX(bEP);

+

+	// set read enable bit for specific endpoint

+	USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);

+

+	// wait for PKT_RDY

+	do {

+		dwLen = USB->USBRxPLen;

+	} while ((dwLen & PKT_RDY) == 0);

+

+	// packet valid?

+	if ((dwLen & DV) == 0) {

+		return -1;

+	}

+

+	// get length

+	dwLen &= PKT_LNGTH_MASK;

+

+	// get data

+	dwData = 0;

+	for (i = 0; i < dwLen; i++) {

+		if ((i % 4) == 0) {

+			dwData = USB->USBRxData;

+		}

+		if ((pbBuf != NULL) && (i < iMaxLen)) {

+			pbBuf[i] = dwData & 0xFF;

+		}

+		dwData >>= 8;

+	}

+

+	// make sure RD_EN is clear

+	USB->USBCtrl = 0;

+

+	// select endpoint and clear buffer

+	USBHwCmd(CMD_EP_SELECT | idx);

+	USBHwCmd(CMD_EP_CLEAR_BUFFER);

+

+	return dwLen;

+}

+

+

+/**

+	Sets the 'configured' state.

+

+	All registered endpoints are 'realised' and enabled, and the

+	'configured' bit is set in the device status register.

+

+	@param [in]	fConfigured	If TRUE, configure device, else unconfigure

+ */

+void USBHwConfigDevice(BOOL fConfigured)

+{

+	// set configured bit

+	USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);

+}

+

+

+/**

+	USB interrupt handler

+

+	@todo Get all 11 bits of frame number instead of just 8

+

+	Endpoint interrupts are mapped to the slow interrupt

+ */

+void USBHwISR(void)

+{

+	unsigned long	dwStatus;

+	unsigned long dwIntBit;

+	unsigned char	bEPStat, bDevStat, bStat;

+	int i;

+	unsigned short	wFrame;

+

+	// handle device interrupts

+	dwStatus = USB->USBDevIntSt;

+

+	// frame interrupt

+	if (dwStatus & FRAME) {

+		// clear int

+		USB->USBDevIntClr = FRAME;

+		// call handler

+		if (_pfnFrameHandler != NULL) {

+			wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);

+			_pfnFrameHandler(wFrame);

+		}

+	}

+

+	// device status interrupt

+	if (dwStatus & DEV_STAT) {

+		/*	Clear DEV_STAT interrupt before reading DEV_STAT register.

+			This prevents corrupted device status reads, see

+			LPC2148 User manual revision 2, 25 july 2006.

+		*/

+		USB->USBDevIntClr = DEV_STAT;

+		bDevStat = USBHwCmdRead(CMD_DEV_STATUS);

+		if (bDevStat & (CON_CH | SUS_CH | RST)) {

+			// convert device status into something HW independent

+			bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |

+					((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |

+					((bDevStat & RST) ? DEV_STATUS_RESET : 0);

+			// call handler

+			if (_pfnDevIntHandler != NULL) {

+				_pfnDevIntHandler(bStat);

+			}

+		}

+	}

+

+	// endpoint interrupt

+	if (dwStatus & EP_SLOW) {

+		// clear EP_SLOW

+		USB->USBDevIntClr = EP_SLOW;

+		// check all endpoints

+		for (i = 0; i < 32; i++) {

+			dwIntBit = (1 << i);

+			if (USB->USBEpIntSt & dwIntBit) {

+				// clear int (and retrieve status)

+				USB->USBEpIntClr = dwIntBit;

+				Wait4DevInt(CDFULL);

+				bEPStat = USB->USBCmdData;

+				// convert EP pipe stat into something HW independent

+				bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |

+						((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |

+						((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |

+						((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |

+						((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);

+				// call handler

+				if (_apfnEPIntHandlers[i / 2] != NULL) {

+					_apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);

+				}

+			}

+		}

+	}

+}

+

+

+

+/**

+	Initialises the USB hardware

+

+

+	@return TRUE if the hardware was successfully initialised

+ */

+BOOL USBHwInit(void)

+{

+	// P2.9 -> USB_CONNECT

+	PINCON->PINSEL4 &= ~0x000C0000;

+	PINCON->PINSEL4 |= 0x00040000;

+

+	// P1.18 -> USB_UP_LED

+	// P1.30 -> VBUS

+	PINCON->PINSEL3 &= ~0x30000030;

+	PINCON->PINSEL3 |= 0x20000010;

+

+	// P0.29 -> USB_D+

+	// P0.30 -> USB_D-

+	PINCON->PINSEL1 &= ~0x3C000000;

+	PINCON->PINSEL1 |= 0x14000000;

+

+	// enable PUSB

+	SC->PCONP |= (1 << 31);

+

+	USB->OTGClkCtrl = 0x12;	                  /* Dev clock, AHB clock enable  */

+	while ((USB->OTGClkSt & 0x12) != 0x12);

+

+	// disable/clear all interrupts for now

+	USB->USBDevIntEn = 0;

+	USB->USBDevIntClr = 0xFFFFFFFF;

+	USB->USBDevIntPri = 0;

+

+	USB->USBEpIntEn = 0;

+	USB->USBEpIntClr = 0xFFFFFFFF;

+	USB->USBEpIntPri = 0;

+

+	// by default, only ACKs generate interrupts

+	USBHwNakIntEnable(0);

+

+	return TRUE;

+}

+

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.h
new file mode 100644
index 0000000..2a4de79
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.h
@@ -0,0 +1,149 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers	
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/**
+	Hardware definitions for the LPC176x USB controller
+
+	These are private to the usbhw module
+*/
+
+// CodeRed - pull in defines from NXP header file
+//#include "NXP\LPC17xx\LPC17xx.h"
+#include "LPC17xx.h"
+
+
+// CodeRed - these registers have been renamed on LPC176x
+#define USBReEP USBReEp
+#define OTG_CLK_CTRL USBClkCtrl
+#define OTG_CLK_STAT USBClkSt
+
+/* USBIntSt bits */
+#define USB_INT_REQ_LP				(1<<0)
+#define USB_INT_REQ_HP				(1<<1)
+#define USB_INT_REQ_DMA				(1<<2)
+#define USB_need_clock				(1<<8)
+#define EN_USB_BITS					(1<<31)
+
+/* USBDevInt... bits */
+#define FRAME						(1<<0)
+#define EP_FAST						(1<<1)
+#define EP_SLOW						(1<<2)
+#define DEV_STAT					(1<<3)
+#define CCEMTY						(1<<4)
+#define CDFULL						(1<<5)
+#define RxENDPKT					(1<<6)
+#define TxENDPKT					(1<<7)
+#define EP_RLZED					(1<<8)
+#define ERR_INT						(1<<9)
+
+/* USBRxPLen bits */
+#define PKT_LNGTH					(1<<0)
+#define PKT_LNGTH_MASK				0x3FF
+#define DV							(1<<10)
+#define PKT_RDY						(1<<11)
+
+/* USBCtrl bits */
+#define RD_EN						(1<<0)
+#define WR_EN						(1<<1)
+#define LOG_ENDPOINT				(1<<2)
+
+/* protocol engine command codes */
+	/* device commands */
+#define CMD_DEV_SET_ADDRESS			0xD0
+#define CMD_DEV_CONFIG				0xD8
+#define CMD_DEV_SET_MODE			0xF3
+#define CMD_DEV_READ_CUR_FRAME_NR	0xF5
+#define CMD_DEV_READ_TEST_REG		0xFD
+#define CMD_DEV_STATUS				0xFE		/* read/write */
+#define CMD_DEV_GET_ERROR_CODE		0xFF
+#define CMD_DEV_READ_ERROR_STATUS	0xFB
+	/* endpoint commands */
+#define CMD_EP_SELECT				0x00
+#define CMD_EP_SELECT_CLEAR			0x40
+#define CMD_EP_SET_STATUS			0x40
+#define CMD_EP_CLEAR_BUFFER			0xF2
+#define CMD_EP_VALIDATE_BUFFER		0xFA
+
+/* set address command */
+#define DEV_ADDR					(1<<0)
+#define DEV_EN						(1<<7)
+
+/* configure device command */
+#define CONF_DEVICE					(1<<0)
+
+/* set mode command */
+#define AP_CLK						(1<<0)
+#define INAK_CI						(1<<1)
+#define INAK_CO						(1<<2)
+#define INAK_II						(1<<3)
+#define INAK_IO						(1<<4)
+#define INAK_BI						(1<<5)
+#define INAK_BO						(1<<6)
+
+/* set get device status command */
+#define CON							(1<<0)
+#define CON_CH						(1<<1)
+#define SUS							(1<<2)
+#define SUS_CH						(1<<3)
+#define RST							(1<<4)
+
+/* get error code command */
+// ...
+
+/* Select Endpoint command read bits */
+#define EPSTAT_FE					(1<<0)
+#define EPSTAT_ST					(1<<1)
+#define EPSTAT_STP					(1<<2)
+#define EPSTAT_PO					(1<<3)
+#define EPSTAT_EPN					(1<<4)
+#define EPSTAT_B1FULL				(1<<5)
+#define EPSTAT_B2FULL				(1<<6)
+
+/* CMD_EP_SET_STATUS command */
+#define EP_ST						(1<<0)
+#define EP_DA						(1<<5)
+#define EP_RF_MO					(1<<6)
+#define EP_CND_ST					(1<<7)
+
+/* read error status command */
+#define PID_ERR						(1<<0)
+#define UEPKT						(1<<1)
+#define DCRC						(1<<2)
+#define TIMEOUT						(1<<3)
+#define EOP							(1<<4)
+#define B_OVRN						(1<<5)
+#define BTSTF						(1<<6)
+#define TGL_ERR						(1<<7)
+
+
+
+
+
+
+
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbinit.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbinit.c
new file mode 100644
index 0000000..8bb7183
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbinit.c
@@ -0,0 +1,82 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers	
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+	USB stack initialisation
+ */
+
+
+#include "usbdebug.h"
+#include "usbapi.h"
+
+
+/** data storage area for standard requests */
+static unsigned char	abStdReqData[8];
+
+
+/**
+	USB reset handler
+	
+	@param [in] bDevStatus	Device status
+ */
+static void HandleUsbReset(unsigned char bDevStatus)
+{
+	if (bDevStatus & DEV_STATUS_RESET) {
+		DBG("\n!");
+	}
+}
+
+
+/**
+	Initialises the USB hardware and sets up the USB stack by
+	installing default callbacks.
+	
+	@return TRUE if initialisation was successful
+ */
+BOOL USBInit(void)
+{
+	// init hardware
+	USBHwInit();
+	
+	// register bus reset handler
+	USBHwRegisterDevIntHandler(HandleUsbReset);
+	
+	// register control transfer handler on EP0
+	USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer);
+	USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer);
+	
+	// setup control endpoints
+	USBHwEPConfig(0x00, MAX_PACKET_SIZE0);
+	USBHwEPConfig(0x80, MAX_PACKET_SIZE0);
+	
+	// register standard request handler
+	USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData);
+
+	return TRUE;
+}
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstdreq.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstdreq.c
new file mode 100644
index 0000000..05e58b4
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstdreq.c
@@ -0,0 +1,430 @@
+/*

+	LPCUSB, an USB device driver for LPC microcontrollers	

+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)

+

+	Redistribution and use in source and binary forms, with or without

+	modification, are permitted provided that the following conditions are met:

+

+	1. Redistributions of source code must retain the above copyright

+	   notice, this list of conditions and the following disclaimer.

+	2. Redistributions in binary form must reproduce the above copyright

+	   notice, this list of conditions and the following disclaimer in the

+	   documentation and/or other materials provided with the distribution.

+	3. The name of the author may not be used to endorse or promote products

+	   derived from this software without specific prior written permission.

+

+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR

+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.

+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 

+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+*/

+

+

+/** @file

+	Standard request handler.

+	

+	This modules handles the 'chapter 9' processing, specifically the

+	standard device requests in table 9-3 from the universal serial bus

+	specification revision 2.0

+	

+	Specific types of devices may specify additional requests (for example

+	HID devices add a GET_DESCRIPTOR request for interfaces), but they

+	will not be part of this module.

+

+	@todo some requests have to return a request error if device not configured:

+	@todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME

+	@todo this applies to the following if endpoint != 0:

+	@todo SET_FEATURE, GET_FEATURE 

+*/

+

+#include "usbdebug.h"

+#include "usbstruct.h"

+#include "usbapi.h"

+

+#define MAX_DESC_HANDLERS	4		/**< device, interface, endpoint, other */

+

+

+/* general descriptor field offsets */

+#define DESC_bLength					0	/**< length offset */

+#define DESC_bDescriptorType			1	/**< descriptor type offset */	

+

+/* config descriptor field offsets */

+#define CONF_DESC_wTotalLength			2	/**< total length offset */

+#define CONF_DESC_bConfigurationValue	5	/**< configuration value offset */	

+#define CONF_DESC_bmAttributes			7	/**< configuration characteristics */

+

+/* interface descriptor field offsets */

+#define INTF_DESC_bAlternateSetting		3	/**< alternate setting offset */

+

+/* endpoint descriptor field offsets */

+#define ENDP_DESC_bEndpointAddress		2	/**< endpoint address offset */

+#define ENDP_DESC_wMaxPacketSize		4	/**< maximum packet size offset */

+

+

+/** Currently selected configuration */

+static unsigned char				bConfiguration = 0;

+/** Installed custom request handler */

+static TFnHandleRequest	*pfnHandleCustomReq = NULL;

+/** Pointer to registered descriptors */

+static const unsigned char			*pabDescrip = NULL;

+

+

+/**

+	Registers a pointer to a descriptor block containing all descriptors

+	for the device.

+

+	@param [in]	pabDescriptors	The descriptor byte array

+ */

+void USBRegisterDescriptors(const unsigned char *pabDescriptors)

+{

+	pabDescrip = pabDescriptors;

+}

+

+

+/**

+	Parses the list of installed USB descriptors and attempts to find

+	the specified USB descriptor.

+		

+	@param [in]		wTypeIndex	Type and index of the descriptor

+	@param [in]		wLangID		Language ID of the descriptor (currently unused)

+	@param [out]	*piLen		Descriptor length

+	@param [out]	*ppbData	Descriptor data

+	

+	@return TRUE if the descriptor was found, FALSE otherwise

+ */

+BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData)

+{

+	unsigned char	bType, bIndex;

+	unsigned char	*pab;

+	int iCurIndex;

+	

+	ASSERT(pabDescrip != NULL);

+

+	bType = GET_DESC_TYPE(wTypeIndex);

+	bIndex = GET_DESC_INDEX(wTypeIndex);

+	

+	pab = (unsigned char *)pabDescrip;

+	iCurIndex = 0;

+	

+	while (pab[DESC_bLength] != 0) {

+		if (pab[DESC_bDescriptorType] == bType) {

+			if (iCurIndex == bIndex) {

+				// set data pointer

+				*ppbData = pab;

+				// get length from structure

+				if (bType == DESC_CONFIGURATION) {

+					// configuration descriptor is an exception, length is at offset 2 and 3

+					*piLen =	(pab[CONF_DESC_wTotalLength]) |

+								(pab[CONF_DESC_wTotalLength + 1] << 8);

+				}

+				else {

+					// normally length is at offset 0

+					*piLen = pab[DESC_bLength];

+				}

+				return TRUE;

+			}

+			iCurIndex++;

+		}

+		// skip to next descriptor

+		pab += pab[DESC_bLength];

+	}

+	// nothing found

+	DBG("Desc %x not found!\n", wTypeIndex);

+	return FALSE;

+}

+

+

+/**

+	Configures the device according to the specified configuration index and

+	alternate setting by parsing the installed USB descriptor list.

+	A configuration index of 0 unconfigures the device.

+		

+	@param [in]		bConfigIndex	Configuration index

+	@param [in]		bAltSetting		Alternate setting number

+	

+	@todo function always returns TRUE, add stricter checking?

+	

+	@return TRUE if successfully configured, FALSE otherwise

+ */

+static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting)

+{

+	unsigned char	*pab;

+	unsigned char	bCurConfig, bCurAltSetting;

+	unsigned char	bEP;

+	unsigned short	wMaxPktSize;

+	

+	ASSERT(pabDescrip != NULL);

+

+	if (bConfigIndex == 0) {

+		// unconfigure device

+		USBHwConfigDevice(FALSE);

+	}

+	else {

+		// configure endpoints for this configuration/altsetting

+		pab = (unsigned char *)pabDescrip;

+		bCurConfig = 0xFF;

+		bCurAltSetting = 0xFF;

+

+		while (pab[DESC_bLength] != 0) {

+

+			switch (pab[DESC_bDescriptorType]) {

+

+			case DESC_CONFIGURATION:

+				// remember current configuration index

+				bCurConfig = pab[CONF_DESC_bConfigurationValue];

+				break;

+

+			case DESC_INTERFACE:

+				// remember current alternate setting

+				bCurAltSetting = pab[INTF_DESC_bAlternateSetting];

+				break;

+

+			case DESC_ENDPOINT:

+				if ((bCurConfig == bConfigIndex) &&

+					(bCurAltSetting == bAltSetting)) {

+					// endpoint found for desired config and alternate setting

+					bEP = pab[ENDP_DESC_bEndpointAddress];

+					wMaxPktSize = 	(pab[ENDP_DESC_wMaxPacketSize]) |

+									(pab[ENDP_DESC_wMaxPacketSize + 1] << 8);

+					// configure endpoint

+					USBHwEPConfig(bEP, wMaxPktSize);

+				}

+				break;

+

+			default:

+				break;

+			}

+			// skip to next descriptor

+			pab += pab[DESC_bLength];

+		}

+		

+		// configure device

+		USBHwConfigDevice(TRUE);

+	}

+

+	return TRUE;

+}

+

+

+/**

+	Local function to handle a standard device request

+		

+	@param [in]		pSetup		The setup packet

+	@param [in,out]	*piLen		Pointer to data length

+	@param [in,out]	ppbData		Data buffer.

+

+	@return TRUE if the request was handled successfully

+ */

+static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)

+{

+	unsigned char	*pbData = *ppbData;

+

+	switch (pSetup->bRequest) {

+	

+	case REQ_GET_STATUS:

+		// bit 0: self-powered

+		// bit 1: remote wakeup = not supported

+		pbData[0] = 0;

+		pbData[1] = 0;

+		*piLen = 2;

+		break;

+		

+	case REQ_SET_ADDRESS:

+		USBHwSetAddress(pSetup->wValue);

+		break;

+

+	case REQ_GET_DESCRIPTOR:

+		DBG("D%x", pSetup->wValue);

+		return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);

+

+	case REQ_GET_CONFIGURATION:

+		// indicate if we are configured

+		pbData[0] = bConfiguration;

+		*piLen = 1;

+		break;

+

+	case REQ_SET_CONFIGURATION:

+		if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {

+			DBG("USBSetConfiguration failed!\n");

+			return FALSE;

+		}

+		// configuration successful, update current configuration

+		bConfiguration = pSetup->wValue & 0xFF;	

+		break;

+

+	case REQ_CLEAR_FEATURE:

+	case REQ_SET_FEATURE:

+		if (pSetup->wValue == FEA_REMOTE_WAKEUP) {

+			// put DEVICE_REMOTE_WAKEUP code here

+		}

+		if (pSetup->wValue == FEA_TEST_MODE) {

+			// put TEST_MODE code here

+		}

+		return FALSE;

+

+	case REQ_SET_DESCRIPTOR:

+		DBG("Device req %d not implemented\n", pSetup->bRequest);

+		return FALSE;

+

+	default:

+		DBG("Illegal device req %d\n", pSetup->bRequest);

+		return FALSE;

+	}

+	

+	return TRUE;

+}

+

+

+/**

+	Local function to handle a standard interface request

+		

+	@param [in]		pSetup		The setup packet

+	@param [in,out]	*piLen		Pointer to data length

+	@param [in]		ppbData		Data buffer.

+

+	@return TRUE if the request was handled successfully

+ */

+static BOOL HandleStdInterfaceReq(TSetupPacket	*pSetup, int *piLen, unsigned char **ppbData)

+{

+	unsigned char	*pbData = *ppbData;

+

+	switch (pSetup->bRequest) {

+

+	case REQ_GET_STATUS:

+		// no bits specified

+		pbData[0] = 0;

+		pbData[1] = 0;

+		*piLen = 2;

+		break;

+

+	case REQ_CLEAR_FEATURE:

+	case REQ_SET_FEATURE:

+		// not defined for interface

+		return FALSE;

+	

+	case REQ_GET_INTERFACE:	// TODO use bNumInterfaces

+        // there is only one interface, return n-1 (= 0)

+		pbData[0] = 0;

+		*piLen = 1;

+		break;

+	

+	case REQ_SET_INTERFACE:	// TODO use bNumInterfaces

+		// there is only one interface (= 0)

+		if (pSetup->wValue != 0) {

+			return FALSE;

+		}

+		*piLen = 0;

+		break;

+

+	default:

+		DBG("Illegal interface req %d\n", pSetup->bRequest);

+		return FALSE;

+	}

+

+	return TRUE;

+}

+

+

+/**

+	Local function to handle a standard endpoint request

+		

+	@param [in]		pSetup		The setup packet

+	@param [in,out]	*piLen		Pointer to data length

+	@param [in]		ppbData		Data buffer.

+

+	@return TRUE if the request was handled successfully

+ */

+static BOOL HandleStdEndPointReq(TSetupPacket	*pSetup, int *piLen, unsigned char **ppbData)

+{

+	unsigned char	*pbData = *ppbData;

+

+	switch (pSetup->bRequest) {

+	case REQ_GET_STATUS:

+		// bit 0 = endpointed halted or not

+		pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;

+		pbData[1] = 0;

+		*piLen = 2;

+		break;

+		

+	case REQ_CLEAR_FEATURE:

+		if (pSetup->wValue == FEA_ENDPOINT_HALT) {

+			// clear HALT by unstalling

+			USBHwEPStall(pSetup->wIndex, FALSE);

+			break;

+		}

+		// only ENDPOINT_HALT defined for endpoints

+		return FALSE;

+	

+	case REQ_SET_FEATURE:

+		if (pSetup->wValue == FEA_ENDPOINT_HALT) {

+			// set HALT by stalling

+			USBHwEPStall(pSetup->wIndex, TRUE);

+			break;

+		}

+		// only ENDPOINT_HALT defined for endpoints

+		return FALSE;

+

+	case REQ_SYNCH_FRAME:

+		DBG("EP req %d not implemented\n", pSetup->bRequest);

+		return FALSE;

+

+	default:

+		DBG("Illegal EP req %d\n", pSetup->bRequest);

+		return FALSE;

+	}

+	

+	return TRUE;

+}

+

+

+/**

+	Default handler for standard ('chapter 9') requests

+	

+	If a custom request handler was installed, this handler is called first.

+		

+	@param [in]		pSetup		The setup packet

+	@param [in,out]	*piLen		Pointer to data length

+	@param [in]		ppbData		Data buffer.

+

+	@return TRUE if the request was handled successfully

+ */

+BOOL USBHandleStandardRequest(TSetupPacket	*pSetup, int *piLen, unsigned char **ppbData)

+{

+	// try the custom request handler first

+	if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {

+		return TRUE;

+	}

+	

+	switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {

+	case REQTYPE_RECIP_DEVICE:		return HandleStdDeviceReq(pSetup, piLen, ppbData);

+	case REQTYPE_RECIP_INTERFACE:	return HandleStdInterfaceReq(pSetup, piLen, ppbData);

+	case REQTYPE_RECIP_ENDPOINT: 	return HandleStdEndPointReq(pSetup, piLen, ppbData);

+	default: 						return FALSE;

+	}

+}

+

+

+/**

+	Registers a callback for custom device requests

+	

+	In USBHandleStandardRequest, the custom request handler gets a first

+	chance at handling the request before it is handed over to the 'chapter 9'

+	request handler.

+	

+	This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR

+	request is sent to an interface, which is not covered by the 'chapter 9'

+	specification.

+		

+	@param [in]	pfnHandler	Callback function pointer

+ */

+void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)

+{

+	pfnHandleCustomReq = pfnHandler;

+}

+

diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstruct.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstruct.h
new file mode 100644
index 0000000..113e2fe
--- /dev/null
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstruct.h
@@ -0,0 +1,119 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers	
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/**
+	Definitions of structures of standard USB packets
+*/
+
+#ifndef _USBSTRUCT_H_
+#define _USBSTRUCT_H_
+
+// CodeRed - include the LPCUSB type.h file rather than NXP one directly
+#include "type.h"
+
+/** setup packet definitions */
+typedef struct {
+	unsigned char	bmRequestType;			/**< characteristics of the specific request */
+	unsigned char	bRequest;				/**< specific request */
+	unsigned short	wValue;					/**< request specific parameter */
+	unsigned short	wIndex;					/**< request specific parameter */
+	unsigned short	wLength;				/**< length of data transfered in data phase */
+} TSetupPacket;
+
+
+#define REQTYPE_GET_DIR(x)		(((x)>>7)&0x01)
+#define REQTYPE_GET_TYPE(x)		(((x)>>5)&0x03)
+#define REQTYPE_GET_RECIP(x)	((x)&0x1F)
+
+#define REQTYPE_DIR_TO_DEVICE	0
+#define REQTYPE_DIR_TO_HOST		1
+
+#define REQTYPE_TYPE_STANDARD	0
+#define REQTYPE_TYPE_CLASS		1
+#define REQTYPE_TYPE_VENDOR		2
+#define REQTYPE_TYPE_RESERVED	3
+
+#define REQTYPE_RECIP_DEVICE	0
+#define REQTYPE_RECIP_INTERFACE	1
+#define REQTYPE_RECIP_ENDPOINT	2
+#define REQTYPE_RECIP_OTHER		3
+
+/* standard requests */
+#define	REQ_GET_STATUS			0x00
+#define REQ_CLEAR_FEATURE		0x01
+#define REQ_SET_FEATURE			0x03
+#define REQ_SET_ADDRESS			0x05
+#define REQ_GET_DESCRIPTOR		0x06
+#define REQ_SET_DESCRIPTOR		0x07
+#define REQ_GET_CONFIGURATION	0x08
+#define REQ_SET_CONFIGURATION	0x09
+#define REQ_GET_INTERFACE		0x0A
+#define REQ_SET_INTERFACE		0x0B
+#define REQ_SYNCH_FRAME			0x0C
+
+/* class requests HID */
+#define HID_GET_REPORT			0x01
+#define HID_GET_IDLE			0x02
+#define HID_GET_PROTOCOL	 	0x03
+#define HID_SET_REPORT			0x09
+#define HID_SET_IDLE			0x0A
+#define HID_SET_PROTOCOL		0x0B
+
+/* feature selectors */
+#define FEA_ENDPOINT_HALT		0x00
+#define FEA_REMOTE_WAKEUP		0x01
+#define FEA_TEST_MODE			0x02
+
+/*
+	USB descriptors
+*/
+
+/** USB descriptor header */
+typedef struct {
+	unsigned char	bLength;			/**< descriptor length */
+	unsigned char	bDescriptorType;	/**< descriptor type */
+} TUSBDescHeader;
+
+#define DESC_DEVICE				1
+#define DESC_CONFIGURATION		2
+#define DESC_STRING				3
+#define DESC_INTERFACE			4
+#define DESC_ENDPOINT			5
+#define DESC_DEVICE_QUALIFIER	6
+#define DESC_OTHER_SPEED		7
+#define DESC_INTERFACE_POWER	8
+
+#define DESC_HID_HID			0x21
+#define DESC_HID_REPORT			0x22
+#define DESC_HID_PHYSICAL		0x23
+
+#define GET_DESC_TYPE(x)		(((x)>>8)&0xFF)
+#define GET_DESC_INDEX(x)		((x)&0xFF)
+
+#endif /* _USBSTRUCT_H_ */
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzp b/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzp
index 3b534ea..d7e1a85 100644
--- a/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzp
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzp
@@ -1,7 +1,7 @@
 <!DOCTYPE CrossStudio_Project_File>
 <solution Name="RTOSDemo" version="2">
   <project Name="RTOSDemo">
-    <configuration Name="Common" Target="LPC1768" arm_architecture="v7M" arm_core_type="Cortex-M3" arm_linker_heap_size="128" arm_linker_process_stack_size="0" arm_linker_stack_size="128" arm_simulator_memory_simulation_filename="$(TargetsDir)/LPC1000/LPC1000SimulatorMemory.dll" arm_simulator_memory_simulation_parameter="0x80000;0x8000;0x8000" arm_target_debug_interface_type="ADIv5" arm_target_loader_parameter="12000000" c_enforce_ansi_checking="No" c_only_additional_options="-Wall;-Wextra" c_preprocessor_definitions="PACK_STRUCT_END=__attribute((packed));ALIGN_STRUCT_END=__attribute((aligned(4)))" c_user_include_directories="$(TargetsDir)/LPC1000/include;../../Source/include;../Common/include;../../Source/portable/GCC/ARM_CM3;../Common/ethernet/uIP/uip-1.0/uip;.;./webserver;./USBHost/Include" link_include_startup_code="No" linker_additional_files="$(TargetsDir)/LPC1000/lib/liblpc1000$(LibExt)$(LIB);$(TargetsDir)/LPC1000/lib/cmsis$(LibExt)$(LIB)" linker_memory_map_file="$(TargetsDir)/LPC1000/LPC1768_MemoryMap.xml" linker_printf_fmt_level="int" linker_printf_width_precision_supported="No" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" oscillator_frequency="12MHz" project_directory="" project_type="Executable" property_groups_file_path="$(TargetsDir)/LPC1000/propertyGroups.xml"/>
+    <configuration Name="Common" Target="LPC1768" arm_architecture="v7M" arm_core_type="Cortex-M3" arm_linker_heap_size="128" arm_linker_process_stack_size="0" arm_linker_stack_size="128" arm_simulator_memory_simulation_filename="$(TargetsDir)/LPC1000/LPC1000SimulatorMemory.dll" arm_simulator_memory_simulation_parameter="0x80000;0x8000;0x8000" arm_target_debug_interface_type="ADIv5" arm_target_loader_parameter="12000000" c_enforce_ansi_checking="No" c_only_additional_options="-Wall;-Wextra" c_preprocessor_definitions="PACK_STRUCT_END=__attribute((packed));ALIGN_STRUCT_END=__attribute((aligned(4)));CONFIGURE_USB;FULL_SPEED" c_user_include_directories="$(TargetsDir)/LPC1000/include;../../Source/include;../Common/include;../../Source/portable/GCC/ARM_CM3;../Common/ethernet/uIP/uip-1.0/uip;.;./webserver;./LPCUSB" link_include_startup_code="No" linker_additional_files="$(TargetsDir)/LPC1000/lib/liblpc1000$(LibExt)$(LIB);$(TargetsDir)/LPC1000/lib/cmsis$(LibExt)$(LIB)" linker_memory_map_file="$(TargetsDir)/LPC1000/LPC1768_MemoryMap.xml" linker_printf_fmt_level="int" linker_printf_width_precision_supported="No" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" oscillator_frequency="12MHz" project_directory="" project_type="Executable" property_groups_file_path="$(TargetsDir)/LPC1000/propertyGroups.xml"/>
     <configuration Name="RAM" Placement="RAM" linker_section_placement_file="$(StudioDir)/targets/Cortex_M/ram_placement.xml" target_reset_script="SRAMReset()"/>
     <configuration Name="Flash" Placement="Flash" arm_target_flash_loader_file_path="$(TargetsDir)/LPC1000/Release/Loader_rpc.elf" arm_target_flash_loader_type="LIBMEM RPC Loader" linker_patch_build_command="$(StudioDir)/bin/crossscript &quot;load(\&quot;$(TargetsDir)/LPC1000/LPC1000_LinkPatch.js\&quot;);patch(\&quot;$(TargetPath)\&quot;);&quot;" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" target_reset_script="FLASHReset()"/>
     <folder Name="Source Files">
@@ -41,6 +41,13 @@
       </folder>
       <file file_name="ParTest.c"/>
       <file file_name="printf-stdarg.c"/>
+      <folder Name="LPCUSB">
+        <file file_name="LPCUSB/usbstdreq.c"/>
+        <file file_name="LPCUSB/USB_CDC.c"/>
+        <file file_name="LPCUSB/usbcontrol.c"/>
+        <file file_name="LPCUSB/usbhw_lpc.c"/>
+        <file file_name="LPCUSB/usbinit.c"/>
+      </folder>
     </folder>
     <folder Name="System Files">
       <file file_name="$(StudioDir)/source/thumb_crt0.s"/>
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzs b/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzs
index feca371..5cc8dae 100644
--- a/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzs
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzs
@@ -22,6 +22,9 @@
   <ProjectSessionItem path="RTOSDemo" name="unnamed" />
   <ProjectSessionItem path="RTOSDemo;RTOSDemo" name="unnamed" />
   <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;FreeRTOS" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;LPCUSB" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;System Files" name="unnamed" />
  </Project>
  <Register1>
   <RegisterWindow openNodes="CPU;CPU/xPSR;CPU/CFBP;CPU/CFBP/CONTROL[0];CPU/CFBP/CONTROL[1]" binaryNodes="" unsignedNodes="" visibleGroups="CPU" decimalNodes="" octalNodes="" asciiNodes="" />
@@ -52,7 +55,7 @@
   <Watches active="0" update="Never" />
  </Watch4>
  <Files>
-  <SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="10" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" y="304" path="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" left="0" selected="1" name="unnamed" top="0" />
+  <SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" y="141" path="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" left="0" selected="1" name="unnamed" top="138" />
  </Files>
- <ARMCrossStudioWindow activeProject="RTOSDemo" autoConnectTarget="USB CrossConnect for ARM" debugSearchFileMap="" fileDialogInitialDirectory="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\UsbHost\Uart" fileDialogDefaultFilter="*.*" autoConnectCapabilities="388991" debugSearchPath="" buildConfiguration="THUMB Flash Debug" />
+ <ARMCrossStudioWindow activeProject="RTOSDemo" autoConnectTarget="USB CrossConnect for ARM" debugSearchFileMap="" fileDialogInitialDirectory="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\LPCUSB" fileDialogDefaultFilter="*.*" autoConnectCapabilities="388991" debugSearchPath="" buildConfiguration="THUMB Flash Debug" />
 </session>
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/main.c b/Demo/CORTEX_LPC1768_GCC_Rowley/main.c
index c8c8a2b..529b498 100644
--- a/Demo/CORTEX_LPC1768_GCC_Rowley/main.c
+++ b/Demo/CORTEX_LPC1768_GCC_Rowley/main.c
@@ -62,6 +62,11 @@
  *

  * "uIP" task -  This is the task that handles the uIP stack.  All TCP/IP

  * processing is performed in this task.

+ * 

+ * "USB" task - Enumerates the USB device as a CDC class, then echoes back all

+ * received characters with a configurable offset (for example, if the offset

+ * is 1 and 'A' is received then 'B' will be sent back).  A dumb terminal such

+ * as Hyperterminal can be used to talk to the USB task.

  */

 

 /* Scheduler includes. */

@@ -117,6 +122,11 @@
 extern void vuIP_Task( void *pvParameters );

 

 /*

+ * The task that handles the USB stack.

+ */

+extern void vUSBTask( void *pvParameters );

+

+/*

  * Simply returns the current status message for display on served WEB pages.

  */

 char *pcGetTaskStatusMessage( void );

@@ -145,6 +155,9 @@
     vStartRecursiveMutexTasks();

 	vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );

 

+    /* Create the USB task. */

+    xTaskCreate( vUSBTask, ( signed char * ) "USB", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );

+	

 	/* Create the uIP task.  The WEB server runs in this task. */

     xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL );

 

@@ -228,49 +241,6 @@
 	/* Disable TPIU. */

 	PINCON->PINSEL10 = 0;

 

-	/* Disconnect the main PLL. */

-	SC->PLL0CON &= ~PLLCON_PLLC;

-	SC->PLL0FEED = PLLFEED_FEED1;

-	SC->PLL0FEED = PLLFEED_FEED2;

-	while ((SC->PLL0STAT & PLLSTAT_PLLC) != 0);

-

-	/* Turn off the main PLL. */

-	SC->PLL0CON &= ~PLLCON_PLLE;

-	SC->PLL0FEED = PLLFEED_FEED1;

-	SC->PLL0FEED = PLLFEED_FEED2;

-	while ((SC->PLL0STAT & PLLSTAT_PLLE) != 0);

-

-	/* No CPU clock divider. */

-	SC->CCLKCFG = 0;

-

-	/* OSCEN. */

-	SC->SCS = 0x20;

-	while ((SC->SCS & 0x40) == 0);

-

-	/* Use main oscillator. */

-	SC->CLKSRCSEL = 1;

-	SC->PLL0CFG = (PLLCFG_MUL16 | PLLCFG_DIV1);

-

-	SC->PLL0FEED = PLLFEED_FEED1;

-	SC->PLL0FEED = PLLFEED_FEED2;

-

-	/*  Activate the PLL by turning it on then feeding the correct

-	sequence of bytes. */

-	SC->PLL0CON  = PLLCON_PLLE;

-	SC->PLL0FEED = PLLFEED_FEED1;

-	SC->PLL0FEED = PLLFEED_FEED2;

-

-	/* 6x CPU clock divider (64 MHz) */

-	SC->CCLKCFG = 5;

-

-	/*  Wait for the PLL to lock. */

-	while ((SC->PLL0STAT & PLLSTAT_PLOCK) == 0);

-

-	/*  Connect the PLL. */

-	SC->PLL0CON  = PLLCON_PLLC | PLLCON_PLLE;

-	SC->PLL0FEED = PLLFEED_FEED1;

-	SC->PLL0FEED = PLLFEED_FEED2;

-

 	/*  Setup the peripheral bus to be the same as the PLL output (64 MHz). */

 	SC->PCLKSEL0 = 0x05555555;