VCOM_lib1.3
This commit is contained in:
parent
2aed667897
commit
99a520a442
6
VCOM_lib/intenable.c
Normal file
6
VCOM_lib/intenable.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "LPC17xx.h"
|
||||||
|
|
||||||
|
void enable_USB_interrupts(void)
|
||||||
|
{
|
||||||
|
NVIC_EnableIRQ(USB_IRQn);
|
||||||
|
}
|
68
VCOM_lib/lpcusb_type.h
Normal file
68
VCOM_lib/lpcusb_type.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
primitive types used in the USB stack
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ***********************************************
|
||||||
|
// Code Red Technologies - port to RDB1768 board
|
||||||
|
// In order to avoid clashing with the NXP-produced type.h file, this
|
||||||
|
// one has been renamed to lpcusb_type.h, the NXP-produced type.h has
|
||||||
|
// been included, and the duplicate contents of this file commented out.
|
||||||
|
// ***********************************************
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _LPCUSB_TYPE_H_
|
||||||
|
#define _LPCUSB_TYPE_H_
|
||||||
|
|
||||||
|
// CodeRed - include NXP-produced type.h file
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
typedef unsigned char U8; /**< unsigned 8-bit */
|
||||||
|
typedef unsigned short int U16; /**< unsigned 16-bit */
|
||||||
|
typedef unsigned int U32; /**< unsigned 32-bit */
|
||||||
|
|
||||||
|
|
||||||
|
// CodeRed - comment out defines duplicated in NXP type.h
|
||||||
|
|
||||||
|
//typedef int BOOL; /**< #TRUE or #FALSE */
|
||||||
|
|
||||||
|
//#define TRUE 1 /**< TRUE */
|
||||||
|
//#define FALSE 0 /**< FALSE */
|
||||||
|
|
||||||
|
//#ifndef NULL
|
||||||
|
//#define NULL ((void*)0) /**< NULL pointer */
|
||||||
|
//#endif
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
/* some other useful macros */
|
||||||
|
#define MIN(x,y) ((x)<(y)?(x):(y)) /**< MIN */
|
||||||
|
#define MAX(x,y) ((x)>(y)?(x):(y)) /**< MAX */
|
||||||
|
|
||||||
|
#endif /* _LPCUSB_TYPE_H_ */
|
||||||
|
|
87
VCOM_lib/serial_fifo.c
Normal file
87
VCOM_lib/serial_fifo.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
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 - LPCUSB type.h renamed
|
||||||
|
//#include "type.h"
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
#include "serial_fifo.h"
|
||||||
|
|
||||||
|
void fifo_init(fifo_t *fifo, U8 *buf)
|
||||||
|
{
|
||||||
|
fifo->head = 0;
|
||||||
|
fifo->tail = 0;
|
||||||
|
fifo->buf = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL fifo_put(fifo_t *fifo, U8 c)
|
||||||
|
{
|
||||||
|
int next;
|
||||||
|
|
||||||
|
// check if FIFO has room
|
||||||
|
next = (fifo->head + 1) % VCOM_FIFO_SIZE;
|
||||||
|
if (next == fifo->tail) {
|
||||||
|
// full
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fifo->buf[fifo->head] = c;
|
||||||
|
fifo->head = next;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL fifo_get(fifo_t *fifo, U8 *pc)
|
||||||
|
{
|
||||||
|
int next;
|
||||||
|
|
||||||
|
// check if FIFO has data
|
||||||
|
if (fifo->head == fifo->tail) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
next = (fifo->tail + 1) % VCOM_FIFO_SIZE;
|
||||||
|
|
||||||
|
*pc = fifo->buf[fifo->tail];
|
||||||
|
fifo->tail = next;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int fifo_avail(fifo_t *fifo)
|
||||||
|
{
|
||||||
|
return (VCOM_FIFO_SIZE + fifo->head - fifo->tail) % VCOM_FIFO_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int fifo_free(fifo_t *fifo)
|
||||||
|
{
|
||||||
|
return (VCOM_FIFO_SIZE - 1 - fifo_avail(fifo));
|
||||||
|
}
|
||||||
|
|
42
VCOM_lib/serial_fifo.h
Normal file
42
VCOM_lib/serial_fifo.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
#define VCOM_FIFO_SIZE 512
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int head;
|
||||||
|
int tail;
|
||||||
|
U8 *buf;
|
||||||
|
} fifo_t;
|
||||||
|
|
||||||
|
void fifo_init(fifo_t *fifo, U8 *buf);
|
||||||
|
BOOL fifo_put(fifo_t *fifo, U8 c);
|
||||||
|
BOOL fifo_get(fifo_t *fifo, U8 *pc);
|
||||||
|
int fifo_avail(fifo_t *fifo);
|
||||||
|
int fifo_free(fifo_t *fifo);
|
628
VCOM_lib/usbSerial.c
Normal file
628
VCOM_lib/usbSerial.c
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
//#define POLLED_USBSERIAL TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Modified by Sagar G V, Feb 2011
|
||||||
|
Used the USB CDC example to create a library. Added the following functions
|
||||||
|
|
||||||
|
void VCOM_puts(const char* str); //writes a null terminated string.
|
||||||
|
void VCOM_putc(char c); // writes a character.
|
||||||
|
void VCOM_putHex(uint8_t hex); // writes 0x.. hex value on the terminal.
|
||||||
|
char VCOM_getc(); // returns character entered in the terminal. blocking function
|
||||||
|
void VCOM_gets(char* str); // returns a string. '\r' or '\n' will terminate character collection.
|
||||||
|
char VCOM_getc_echo(); // returns character entered and echoes the same back.
|
||||||
|
void VCOM_gets_echo(char *str); // gets string terminated in '\r' or '\n' and echoes back the same.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "usbSerial.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
|
||||||
|
typedef struct {
|
||||||
|
U32 dwDTERate;
|
||||||
|
U8 bCharFormat;
|
||||||
|
U8 bParityType;
|
||||||
|
U8 bDataBits;
|
||||||
|
} TLineCoding;
|
||||||
|
|
||||||
|
static TLineCoding LineCoding = {115200, 0, 0, 8};
|
||||||
|
static U8 abBulkBuf[64];
|
||||||
|
static U8 abClassReqData[8];
|
||||||
|
|
||||||
|
static U8 txdata[VCOM_FIFO_SIZE];
|
||||||
|
static U8 rxdata[VCOM_FIFO_SIZE];
|
||||||
|
|
||||||
|
static fifo_t txfifo;
|
||||||
|
static fifo_t rxfifo;
|
||||||
|
|
||||||
|
// forward declaration of interrupt handler
|
||||||
|
void USBIntHandler(void);
|
||||||
|
|
||||||
|
static const U8 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(U8 bEP, U8 bEPStatus)
|
||||||
|
{
|
||||||
|
int i, iLen;
|
||||||
|
bEPStatus = bEPStatus;
|
||||||
|
if (fifo_free(&rxfifo) < MAX_PACKET_SIZE) {
|
||||||
|
// may not fit into fifo
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get data from USB into intermediate buffer
|
||||||
|
iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
|
||||||
|
for (i = 0; i < iLen; i++) {
|
||||||
|
// put into FIFO
|
||||||
|
if (!fifo_put(&rxfifo, abBulkBuf[i])) {
|
||||||
|
// overflow... :(
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Local function to handle outgoing bulk data
|
||||||
|
|
||||||
|
@param [in] bEP
|
||||||
|
@param [in] bEPStatus
|
||||||
|
*/
|
||||||
|
static void BulkIn(U8 bEP, U8 bEPStatus)
|
||||||
|
{
|
||||||
|
int i, iLen;
|
||||||
|
bEPStatus = bEPStatus;
|
||||||
|
if (fifo_avail(&txfifo) == 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 (!fifo_get(&txfifo, &abBulkBuf[i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iLen = i;
|
||||||
|
|
||||||
|
// send over USB
|
||||||
|
if (iLen > 0) {
|
||||||
|
USBHwEPWrite(bEP, abBulkBuf, iLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
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, U8 **ppbData)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
switch (pSetup->bRequest) {
|
||||||
|
|
||||||
|
// set line coding
|
||||||
|
case SET_LINE_CODING:
|
||||||
|
|
||||||
|
//memcpy((U8 *)&LineCoding, *ppbData, 7);
|
||||||
|
*piLen = 7;
|
||||||
|
for(i=0;i<7;i++)
|
||||||
|
((U8 *)&LineCoding)[i] = (*ppbData)[i];
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// get line coding
|
||||||
|
case GET_LINE_CODING:
|
||||||
|
|
||||||
|
*ppbData = (U8 *)&LineCoding;
|
||||||
|
*piLen = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// set control line state
|
||||||
|
case SET_CONTROL_LINE_STATE:
|
||||||
|
// bit0 = DTR, bit = RTS
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialises the VCOM port.
|
||||||
|
Call this function before using VCOM_puttchar or VCOM_getchar
|
||||||
|
*/
|
||||||
|
void VCOM_init(void)
|
||||||
|
{
|
||||||
|
fifo_init(&txfifo, txdata);
|
||||||
|
fifo_init(&rxfifo, rxdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return fifo_put(&txfifo, c) ? c : EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads one character from VCOM port
|
||||||
|
|
||||||
|
@returns character read, or EOF if character could not be read
|
||||||
|
*/
|
||||||
|
int VCOM_getchar(void)
|
||||||
|
{
|
||||||
|
U8 c;
|
||||||
|
|
||||||
|
return fifo_get(&rxfifo, &c) ? c : EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Interrupt handler
|
||||||
|
|
||||||
|
Simply calls the USB ISR
|
||||||
|
*/
|
||||||
|
//void USBIntHandler(void)
|
||||||
|
void USB_IRQHandler(void)
|
||||||
|
{
|
||||||
|
USBHwISR();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void USBFrameHandler(U16 wFrame)
|
||||||
|
{
|
||||||
|
wFrame = wFrame;
|
||||||
|
if (fifo_avail(&txfifo) > 0) {
|
||||||
|
// data available, enable NAK interrupt on bulk in
|
||||||
|
USBHwNakIntEnable(INACK_BI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_USB_interrupts(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
main
|
||||||
|
====
|
||||||
|
**************************************************************************/
|
||||||
|
int usbSerialInit()
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// initialise VCOM
|
||||||
|
VCOM_init();
|
||||||
|
|
||||||
|
|
||||||
|
/* CodeRed - comment out original interrupt setup code
|
||||||
|
// set up USB interrupt
|
||||||
|
VICIntSelect &= ~(1<<22); // select IRQ for USB
|
||||||
|
VICIntEnable |= (1<<22);
|
||||||
|
|
||||||
|
(*(&VICVectCntl0+INT_VECT_NUM)) = 0x20 | 22; // choose highest priority ISR slot
|
||||||
|
(*(&VICVectAddr0+INT_VECT_NUM)) = (int)USBIntHandler;
|
||||||
|
|
||||||
|
enableIRQ();
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - add in interrupt setup code for RDB1768
|
||||||
|
|
||||||
|
#ifndef POLLED_USBSERIAL
|
||||||
|
//enable_USB_interrupts();
|
||||||
|
NVIC_EnableIRQ(USB_IRQn);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// connect to bus
|
||||||
|
|
||||||
|
|
||||||
|
USBHwConnect(TRUE);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void VCOM_puts(const char* str)
|
||||||
|
{
|
||||||
|
while(*str != '\0')
|
||||||
|
{
|
||||||
|
VCOM_putchar(*str++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VCOM_putc(char c)
|
||||||
|
{
|
||||||
|
while(VCOM_putchar(c) == EOF);
|
||||||
|
}
|
||||||
|
char VCOM_getc()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
c = EOF;
|
||||||
|
while(c == EOF)
|
||||||
|
{
|
||||||
|
c = VCOM_getchar();
|
||||||
|
}
|
||||||
|
return (char)c;
|
||||||
|
}
|
||||||
|
void VCOM_putHex(uint8_t hex)
|
||||||
|
{
|
||||||
|
uint8_t temp;
|
||||||
|
VCOM_puts("0x");
|
||||||
|
|
||||||
|
temp = ((hex >> 4) & 0x0F) + 0x30;// add 0x30 to get ASCII value
|
||||||
|
if(temp > 0x39)
|
||||||
|
temp += 7; // alphabet, not numeral
|
||||||
|
VCOM_putc((char)temp);
|
||||||
|
|
||||||
|
temp = ((hex) & 0x0F) + 0x30;
|
||||||
|
if(temp > 0x39)
|
||||||
|
temp += 7;
|
||||||
|
|
||||||
|
VCOM_putc((char)temp);
|
||||||
|
}
|
||||||
|
void VCOM_gets(char* str)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
c = VCOM_getc();
|
||||||
|
while((c != '\n') && (c != '\r'))
|
||||||
|
{
|
||||||
|
*str++ = c;
|
||||||
|
c = VCOM_getc();
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
}
|
||||||
|
char VCOM_getc_echo()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
c = VCOM_getc();
|
||||||
|
VCOM_putc(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
void VCOM_gets_echo(char *str)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
c = VCOM_getc_echo();
|
||||||
|
while((c != '\n') && (c != '\r'))
|
||||||
|
{
|
||||||
|
*str++ = c;
|
||||||
|
c = VCOM_getc_echo();
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Original code by ELM_ChaN. Modified by Martin Thomas */
|
||||||
|
int xatoi (char **str, long *res)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
uint8_t c, radix, s = 0;
|
||||||
|
|
||||||
|
|
||||||
|
while ((c = **str) == ' ') (*str)++;
|
||||||
|
if (c == '-') {
|
||||||
|
s = 1;
|
||||||
|
c = *(++(*str));
|
||||||
|
}
|
||||||
|
if (c == '0') {
|
||||||
|
c = *(++(*str));
|
||||||
|
if (c <= ' ') {
|
||||||
|
*res = 0; return 1;
|
||||||
|
}
|
||||||
|
if (c == 'x') {
|
||||||
|
radix = 16;
|
||||||
|
c = *(++(*str));
|
||||||
|
} else {
|
||||||
|
if (c == 'b') {
|
||||||
|
radix = 2;
|
||||||
|
c = *(++(*str));
|
||||||
|
} else {
|
||||||
|
if ((c >= '0')&&(c <= '9'))
|
||||||
|
radix = 8;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((c < '1')||(c > '9'))
|
||||||
|
return 0;
|
||||||
|
radix = 10;
|
||||||
|
}
|
||||||
|
val = 0;
|
||||||
|
while (c > ' ') {
|
||||||
|
if (c >= 'a') c -= 0x20;
|
||||||
|
c -= '0';
|
||||||
|
if (c >= 17) {
|
||||||
|
c -= 7;
|
||||||
|
if (c <= 9) return 0;
|
||||||
|
}
|
||||||
|
if (c >= radix) return 0;
|
||||||
|
val = val * radix + c;
|
||||||
|
c = *(++(*str));
|
||||||
|
}
|
||||||
|
if (s) val = -val;
|
||||||
|
*res = val;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void xitoa (long val, int radix, int len)
|
||||||
|
{
|
||||||
|
uint8_t c, r, sgn = 0, pad = ' ';
|
||||||
|
uint8_t s[20], i = 0;
|
||||||
|
uint32_t v;
|
||||||
|
|
||||||
|
|
||||||
|
if (radix < 0) {
|
||||||
|
radix = -radix;
|
||||||
|
if (val < 0) {
|
||||||
|
val = -val;
|
||||||
|
sgn = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v = val;
|
||||||
|
r = radix;
|
||||||
|
if (len < 0) {
|
||||||
|
len = -len;
|
||||||
|
pad = '0';
|
||||||
|
}
|
||||||
|
if (len > 20) return;
|
||||||
|
do {
|
||||||
|
c = (uint8_t)(v % r);
|
||||||
|
if (c >= 10) c += 7;
|
||||||
|
c += '0';
|
||||||
|
s[i++] = c;
|
||||||
|
v /= r;
|
||||||
|
} while (v);
|
||||||
|
if (sgn) s[i++] = sgn;
|
||||||
|
while (i < len)
|
||||||
|
s[i++] = pad;
|
||||||
|
do
|
||||||
|
VCOM_putc(s[--i]);
|
||||||
|
while (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VCOM_printf (const char* str, ...)
|
||||||
|
{
|
||||||
|
va_list arp;
|
||||||
|
int d, r, w, s, l;
|
||||||
|
|
||||||
|
|
||||||
|
va_start(arp, str);
|
||||||
|
|
||||||
|
while ((d = *str++) != 0) {
|
||||||
|
if (d != '%') {
|
||||||
|
VCOM_putc(d); continue;
|
||||||
|
}
|
||||||
|
d = *str++; w = r = s = l = 0;
|
||||||
|
if (d == '0') {
|
||||||
|
d = *str++; s = 1;
|
||||||
|
}
|
||||||
|
while ((d >= '0')&&(d <= '9')) {
|
||||||
|
w += w * 10 + (d - '0');
|
||||||
|
d = *str++;
|
||||||
|
}
|
||||||
|
if (s) w = -w;
|
||||||
|
if (d == 'l') {
|
||||||
|
l = 1;
|
||||||
|
d = *str++;
|
||||||
|
}
|
||||||
|
if (!d) break;
|
||||||
|
if (d == 's') {
|
||||||
|
VCOM_puts(va_arg(arp, char*));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (d == 'c') {
|
||||||
|
VCOM_putc((char)va_arg(arp, int));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (d == 'u') r = 10;
|
||||||
|
if (d == 'd') r = -10;
|
||||||
|
if (d == 'X' || d == 'x') r = 16; // 'x' added by mthomas in increase compatibility
|
||||||
|
if (d == 'b') r = 2;
|
||||||
|
if (!r) break;
|
||||||
|
if (l) {
|
||||||
|
xitoa((long)va_arg(arp, long), r, w);
|
||||||
|
} else {
|
||||||
|
if (r > 0)
|
||||||
|
xitoa((unsigned long)va_arg(arp, int), r, w);
|
||||||
|
else
|
||||||
|
xitoa((long)va_arg(arp, int), r, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(arp);
|
||||||
|
}
|
129
VCOM_lib/usbSerial.h
Normal file
129
VCOM_lib/usbSerial.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//#define POLLED_USBSERIAL TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Modified by Sagar G V, Feb 2011
|
||||||
|
Used the USB CDC example to create a library. Added the following functions
|
||||||
|
|
||||||
|
void VCOM_puts(const char* str); //writes a null terminated string.
|
||||||
|
void VCOM_putc(char c); // writes a character.
|
||||||
|
void VCOM_putHex(uint8_t hex); // writes 0x.. hex value on the terminal.
|
||||||
|
char VCOM_getc(); // returns character entered in the terminal. blocking function
|
||||||
|
void VCOM_gets(char* str); // returns a string. '\r' or '\n' will terminate character collection.
|
||||||
|
char VCOM_getc_echo(); // returns character entered and echoes the same back.
|
||||||
|
void VCOM_gets_echo(char *str); // gets string terminated in '\r' or '\n' and echoes back the same.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USB_SERIAL_H__
|
||||||
|
#define __USB_SERIAL_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "LPC17xx.h"
|
||||||
|
|
||||||
|
#include "usbapi.h"
|
||||||
|
#include "usbdebug.h"
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
#include "serial_fifo.h"
|
||||||
|
|
||||||
|
int usbSerialInit(); // run once in main b4 main loop starts.
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads one character from VCOM port
|
||||||
|
|
||||||
|
@returns character read, or EOF if character could not be read
|
||||||
|
*/
|
||||||
|
int VCOM_getchar(void);
|
||||||
|
|
||||||
|
void VCOM_puts(const char* str); //writes a null terminated string.
|
||||||
|
void VCOM_putc(char c); // writes a character.
|
||||||
|
void VCOM_putHex(uint8_t hex); // writes 0x.. hex value on the terminal.
|
||||||
|
char VCOM_getc(); // returns character entered in the terminal. blocking function
|
||||||
|
void VCOM_gets(char* str); // returns a string. '\r' or '\n' will terminate character collection.
|
||||||
|
char VCOM_getc_echo(); // returns character entered and echoes the same back.
|
||||||
|
void VCOM_gets_echo(char *str); // gets string terminated in '\r' or '\n' and echoes back the same.
|
||||||
|
|
||||||
|
void VCOM_printf(const char* str, ...); // Original code by Elm_CHaN. Modified by Martin Thomas
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
121
VCOM_lib/usbapi.h
Normal file
121
VCOM_lib/usbapi.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - include the LPCUSB type.h file rather than NXP one directly
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
#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 (U8 bIntBits);
|
||||||
|
|
||||||
|
void USBHwConnect (BOOL fConnect);
|
||||||
|
|
||||||
|
void USBHwSetAddress (U8 bAddr);
|
||||||
|
void USBHwConfigDevice (BOOL fConfigured);
|
||||||
|
|
||||||
|
// endpoint operations
|
||||||
|
void USBHwEPConfig (U8 bEP, U16 wMaxPacketSize);
|
||||||
|
int USBHwEPRead (U8 bEP, U8 *pbBuf, int iMaxLen);
|
||||||
|
int USBHwEPWrite (U8 bEP, U8 *pbBuf, int iLen);
|
||||||
|
void USBHwEPStall (U8 bEP, BOOL fStall);
|
||||||
|
U8 USBHwEPGetStatus (U8 bEP);
|
||||||
|
|
||||||
|
/** Endpoint interrupt handler callback */
|
||||||
|
typedef void (TFnEPIntHandler) (U8 bEP, U8 bEPStatus);
|
||||||
|
void USBHwRegisterEPIntHandler (U8 bEP, TFnEPIntHandler *pfnHandler);
|
||||||
|
|
||||||
|
/** Device status handler callback */
|
||||||
|
typedef void (TFnDevIntHandler) (U8 bDevStatus);
|
||||||
|
void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler);
|
||||||
|
|
||||||
|
/** Frame event handler callback */
|
||||||
|
typedef void (TFnFrameHandler)(U16 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, U8 **ppbData);
|
||||||
|
void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, U8 *pbDataStore);
|
||||||
|
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler);
|
||||||
|
|
||||||
|
/** Descriptor handler callback */
|
||||||
|
typedef BOOL (TFnGetDescriptor)(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData);
|
||||||
|
|
||||||
|
/** Default standard request handler */
|
||||||
|
BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData);
|
||||||
|
|
||||||
|
/** Default EP0 handler */
|
||||||
|
void USBHandleControlTransfer(U8 bEP, U8 bEPStat);
|
||||||
|
|
||||||
|
/** Descriptor handling */
|
||||||
|
void USBRegisterDescriptors(const U8 *pabDescriptors);
|
||||||
|
BOOL USBGetDescriptor(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData);
|
234
VCOM_lib/usbcontrol.c
Normal file
234
VCOM_lib/usbcontrol.c
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - include the LPCUSB type.h file rather than NXP one directly
|
||||||
|
//#include "type.h"
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
#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 U8 *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 U8 *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, U8 **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(U8 bEPStat)
|
||||||
|
{
|
||||||
|
U8 *pb;
|
||||||
|
int i;
|
||||||
|
bEPStat = bEPStat;
|
||||||
|
USBHwEPStall(0x80, TRUE);
|
||||||
|
|
||||||
|
// dump setup packet
|
||||||
|
DBG("STALL on [");
|
||||||
|
pb = (U8 *)&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;
|
||||||
|
|
||||||
|
iChunk = MIN(MAX_PACKET_SIZE0, 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(U8 bEP, U8 bEPStat)
|
||||||
|
{
|
||||||
|
int iChunk, iType;
|
||||||
|
|
||||||
|
if (bEP == 0x00) {
|
||||||
|
// OUT transfer
|
||||||
|
if (bEPStat & EP_STATUS_SETUP) {
|
||||||
|
// setup packet, reset request message state machine
|
||||||
|
USBHwEPRead(0x00, (U8 *)&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
|
||||||
|
iResidue = MIN(iLen, 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, U8 *pbDataStore)
|
||||||
|
{
|
||||||
|
ASSERT(iType >= 0);
|
||||||
|
ASSERT(iType < 4);
|
||||||
|
apfnReqHandlers[iType] = pfnHandler;
|
||||||
|
apbDataStore[iType] = pbDataStore;
|
||||||
|
}
|
||||||
|
|
44
VCOM_lib/usbdebug.h
Normal file
44
VCOM_lib/usbdebug.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
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>
|
||||||
|
|
||||||
|
// CodeRed - added DEBUG_MESSAGES, so still get output for Release builds
|
||||||
|
//#define DEBUG_MESSAGES 1
|
||||||
|
//#ifdef DEBUG
|
||||||
|
#ifdef DEBUG_MESSAGES
|
||||||
|
#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
|
||||||
|
|
627
VCOM_lib/usbhw_lpc.c
Normal file
627
VCOM_lib/usbhw_lpc.c
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - include the LPCUSB type.h file rather than NXP one directly
|
||||||
|
//#include "type.h"
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
#include "usbdebug.h"
|
||||||
|
#include "usbhw_lpc.h"
|
||||||
|
#include "usbapi.h"
|
||||||
|
// Configure LED pin functions
|
||||||
|
//
|
||||||
|
// LED pin functions
|
||||||
|
//
|
||||||
|
// Function Pin Port Bits Pin Select Register
|
||||||
|
// ------------------- --- ----- ---- -------------------
|
||||||
|
// P2.0 GPIO Port 2.0 xx P2.0 1:0 PINSEL4
|
||||||
|
// P2.1 GPIO Port 2.1 xx P2.1 3:2 PINSEL4
|
||||||
|
// P2.2 GPIO Port 2.2 xx P2.2 5:4 PINSEL4
|
||||||
|
// P2.3 GPIO Port 2.3 xx P2.3 7:6 PINSEL4
|
||||||
|
// P2.4 GPIO Port 2.4 xx P2.4 9:8 PINSEL4
|
||||||
|
// P2.5 GPIO Port 2.5 xx P2.5 11:10 PINSEL4
|
||||||
|
// P2.6 GPIO Port 2.6 xx P2.6 13:12 PINSEL4
|
||||||
|
// P2.7 GPIO Port 2.7 xx P2.7 15:14 PINSEL4
|
||||||
|
//
|
||||||
|
// OFF - LED state 0
|
||||||
|
// ON - LED state 1
|
||||||
|
//
|
||||||
|
// '*' as GPIO
|
||||||
|
|
||||||
|
#define NO_LEDS 8
|
||||||
|
|
||||||
|
#define LED_0 (1 << 0)
|
||||||
|
#define LED_1 (1 << 1)
|
||||||
|
#define LED_2 (1 << 2)
|
||||||
|
#define LED_3 (1 << 3)
|
||||||
|
#define LED_4 (1 << 4)
|
||||||
|
#define LED_5 (1 << 5)
|
||||||
|
#define LED_6 (1 << 6)
|
||||||
|
#define LED_7 (1 << 7)
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// comment out the following line if you don't want to use debug LEDs
|
||||||
|
//#define DEBUG_LED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_LED
|
||||||
|
#define DEBUG_LED_ON(x) FIO2SET = (1 << x);
|
||||||
|
#define DEBUG_LED_OFF(x) FIO2CLR = (1 << x);
|
||||||
|
#define DEBUG_LED_INIT(x) PINSEL2 &= ~(0x3 << (2*x)); FIO2DIR |= (1 << x); DEBUG_LED_OFF(x);
|
||||||
|
#else
|
||||||
|
#define DEBUG_LED_INIT(x) /**< LED initialisation macro */
|
||||||
|
#define DEBUG_LED_ON(x) /**< turn LED on */
|
||||||
|
#define DEBUG_LED_OFF(x) /**< turn LED off */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** 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(U32 dwIntr)
|
||||||
|
{
|
||||||
|
// wait for specific interrupt
|
||||||
|
while ((LPC_USB->USBDevIntSt & dwIntr) != dwIntr);
|
||||||
|
// clear the interrupt bits
|
||||||
|
LPC_USB->USBDevIntClr = dwIntr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Local function to send a command to the USB protocol engine
|
||||||
|
|
||||||
|
@param [in] bCmd Command to send
|
||||||
|
*/
|
||||||
|
static void USBHwCmd(U8 bCmd)
|
||||||
|
{
|
||||||
|
// clear CDFULL/CCEMTY
|
||||||
|
LPC_USB->USBDevIntClr = CDFULL | CCEMTY;
|
||||||
|
// write command code
|
||||||
|
LPC_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(U8 bCmd, U16 bData)
|
||||||
|
{
|
||||||
|
// write command code
|
||||||
|
USBHwCmd(bCmd);
|
||||||
|
|
||||||
|
// write command data
|
||||||
|
LPC_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 U8 USBHwCmdRead(U8 bCmd)
|
||||||
|
{
|
||||||
|
// write command code
|
||||||
|
USBHwCmd(bCmd);
|
||||||
|
|
||||||
|
// get data
|
||||||
|
LPC_USB->USBCmdCode = 0x00000200 | (bCmd << 16);
|
||||||
|
Wait4DevInt(CDFULL);
|
||||||
|
return LPC_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, U16 wMaxPSize)
|
||||||
|
{
|
||||||
|
LPC_USB->USBReEP |= (1 << idx);
|
||||||
|
LPC_USB->USBEpInd = idx;
|
||||||
|
LPC_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(U8 bEP, U16 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(U8 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 */
|
||||||
|
LPC_USB->USBEpIntEn |= (1 << idx);
|
||||||
|
LPC_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
|
||||||
|
LPC_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
|
||||||
|
LPC_USB->USBDevIntEn |= FRAME;
|
||||||
|
|
||||||
|
DBG("Registered handler for frame\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the USB address.
|
||||||
|
|
||||||
|
@param [in] bAddr Device address to set
|
||||||
|
*/
|
||||||
|
void USBHwSetAddress(U8 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(U8 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)
|
||||||
|
*/
|
||||||
|
U8 USBHwEPGetStatus(U8 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(U8 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(U8 bEP, U8 *pbBuf, int iLen)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = EP2IDX(bEP);
|
||||||
|
|
||||||
|
// set write enable for specific endpoint
|
||||||
|
LPC_USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);
|
||||||
|
|
||||||
|
// set packet length
|
||||||
|
LPC_USB->USBTxPLen = iLen;
|
||||||
|
|
||||||
|
// write data
|
||||||
|
while (LPC_USB->USBCtrl & WR_EN) {
|
||||||
|
LPC_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(U8 bEP, U8 *pbBuf, int iMaxLen)
|
||||||
|
{
|
||||||
|
int i, idx;
|
||||||
|
U32 dwData, dwLen;
|
||||||
|
|
||||||
|
idx = EP2IDX(bEP);
|
||||||
|
|
||||||
|
// set read enable bit for specific endpoint
|
||||||
|
LPC_USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);
|
||||||
|
|
||||||
|
// wait for PKT_RDY
|
||||||
|
do {
|
||||||
|
dwLen = LPC_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 < (int)dwLen; i++) {
|
||||||
|
if ((i % 4) == 0) {
|
||||||
|
dwData = LPC_USB->USBRxData;
|
||||||
|
}
|
||||||
|
if ((pbBuf != NULL) && (i < iMaxLen)) {
|
||||||
|
pbBuf[i] = dwData & 0xFF;
|
||||||
|
}
|
||||||
|
dwData >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure RD_EN is clear
|
||||||
|
LPC_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)
|
||||||
|
{
|
||||||
|
U32 dwStatus;
|
||||||
|
U32 dwIntBit;
|
||||||
|
U8 bEPStat, bDevStat, bStat;
|
||||||
|
int i;
|
||||||
|
U16 wFrame;
|
||||||
|
|
||||||
|
// LED9 monitors total time in interrupt routine
|
||||||
|
DEBUG_LED_ON(6);
|
||||||
|
|
||||||
|
// handle device interrupts
|
||||||
|
dwStatus = LPC_USB->USBDevIntSt;
|
||||||
|
|
||||||
|
// frame interrupt
|
||||||
|
if (dwStatus & FRAME) {
|
||||||
|
// clear int
|
||||||
|
LPC_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.
|
||||||
|
*/
|
||||||
|
LPC_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) {
|
||||||
|
DEBUG_LED_ON(5);
|
||||||
|
_pfnDevIntHandler(bStat);
|
||||||
|
DEBUG_LED_OFF(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endpoint interrupt
|
||||||
|
if (dwStatus & EP_SLOW) {
|
||||||
|
// clear EP_SLOW
|
||||||
|
LPC_USB->USBDevIntClr = EP_SLOW;
|
||||||
|
// check all endpoints
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
dwIntBit = (1 << i);
|
||||||
|
if (LPC_USB->USBEpIntSt & dwIntBit) {
|
||||||
|
// clear int (and retrieve status)
|
||||||
|
LPC_USB->USBEpIntClr = dwIntBit;
|
||||||
|
Wait4DevInt(CDFULL);
|
||||||
|
bEPStat = LPC_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) {
|
||||||
|
DEBUG_LED_ON(7);
|
||||||
|
_apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);
|
||||||
|
DEBUG_LED_OFF(7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LED_OFF(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialises the USB hardware
|
||||||
|
|
||||||
|
This function assumes that the hardware is connected as shown in
|
||||||
|
section 10.1 of the LPC2148 data sheet:
|
||||||
|
* P0.31 controls a switch to connect a 1.5k pull-up to D+ if low.
|
||||||
|
* P0.23 is connected to USB VCC.
|
||||||
|
|
||||||
|
Embedded artists board: make sure to disconnect P0.23 LED as it
|
||||||
|
acts as a pull-up and so prevents detection of USB disconnect.
|
||||||
|
|
||||||
|
@return TRUE if the hardware was successfully initialised
|
||||||
|
*/
|
||||||
|
BOOL USBHwInit(void)
|
||||||
|
{
|
||||||
|
/* CodeRed - comment out original code
|
||||||
|
*
|
||||||
|
// configure P0.23 for Vbus sense
|
||||||
|
PINSEL1 = (PINSEL1 & ~(3 << 14)) | (1 << 14); // P0.23
|
||||||
|
// configure P0.31 for CONNECT
|
||||||
|
PINSEL1 = (PINSEL1 & ~(3 << 30)) | (2 << 30); // P0.31
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - set up USB pins
|
||||||
|
|
||||||
|
// P2.9 -> USB_CONNECT
|
||||||
|
LPC_PINCON->PINSEL4 &= ~0x000C0000;
|
||||||
|
LPC_PINCON->PINSEL4 |= 0x00040000;
|
||||||
|
|
||||||
|
// P1.18 -> USB_UP_LED
|
||||||
|
// P1.30 -> VBUS
|
||||||
|
LPC_PINCON->PINSEL3 &= ~0x30000030;
|
||||||
|
LPC_PINCON->PINSEL3 |= 0x20000010;
|
||||||
|
|
||||||
|
// P0.29 -> USB_D+
|
||||||
|
// P0.30 -> USB_D-
|
||||||
|
LPC_PINCON->PINSEL1 &= ~0x3C000000;
|
||||||
|
LPC_PINCON->PINSEL1 |= 0x14000000;
|
||||||
|
|
||||||
|
|
||||||
|
// enable PUSB
|
||||||
|
LPC_SC->PCONP |= (1 << 31);
|
||||||
|
|
||||||
|
/* CodeRed - Comment out original PLL code
|
||||||
|
* PLL now set up by NXP code in target.c within example projects
|
||||||
|
*
|
||||||
|
// initialise PLL
|
||||||
|
PLL1CON = 1; // enable PLL
|
||||||
|
PLL1CFG = (1 << 5) | 3; // P = 2, M = 4
|
||||||
|
PLL1FEED = 0xAA;
|
||||||
|
PLL1FEED = 0x55;
|
||||||
|
while ((PLL1STAT & (1 << 10)) == 0);
|
||||||
|
|
||||||
|
PLL1CON = 3; // enable and connect
|
||||||
|
PLL1FEED = 0xAA;
|
||||||
|
PLL1FEED = 0x55;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// AWB added USB clock enable
|
||||||
|
// These are actually the USBClkCtrl and USBClkSt registers
|
||||||
|
// OTG_CLK_CTRL = 0x12; /* Dev clock, AHB clock enable */
|
||||||
|
// while ((OTG_CLK_STAT & 0x12) != 0x12);
|
||||||
|
|
||||||
|
LPC_USB->USBClkCtrl = 0x1A; /* Dev clock, AHB clock enable */
|
||||||
|
while ((LPC_USB->USBClkSt & 0x1A) != 0x1A);
|
||||||
|
|
||||||
|
|
||||||
|
// disable/clear all interrupts for now
|
||||||
|
LPC_USB->USBDevIntEn = 0;
|
||||||
|
LPC_USB->USBDevIntClr = 0xFFFFFFFF;
|
||||||
|
LPC_USB->USBDevIntPri = 0;
|
||||||
|
|
||||||
|
LPC_USB->USBEpIntEn = 0;
|
||||||
|
LPC_USB->USBEpIntClr = 0xFFFFFFFF;
|
||||||
|
LPC_USB->USBEpIntPri = 0;
|
||||||
|
|
||||||
|
// by default, only ACKs generate interrupts
|
||||||
|
USBHwNakIntEnable(0);
|
||||||
|
|
||||||
|
// CodeRed - commented out LEDs - not used by current port
|
||||||
|
// init debug leds
|
||||||
|
/*
|
||||||
|
DEBUG_LED_INIT(5);
|
||||||
|
DEBUG_LED_INIT(6);
|
||||||
|
DEBUG_LED_INIT(7);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
148
VCOM_lib/usbhw_lpc.h
Normal file
148
VCOM_lib/usbhw_lpc.h
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
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 "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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
85
VCOM_lib/usbinit.c
Normal file
85
VCOM_lib/usbinit.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - include the LPCUSB type.h file rather than NXP one directly
|
||||||
|
//#include "type.h"
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
#include "usbdebug.h"
|
||||||
|
#include "usbapi.h"
|
||||||
|
|
||||||
|
|
||||||
|
/** data storage area for standard requests */
|
||||||
|
static U8 abStdReqData[8];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
USB reset handler
|
||||||
|
|
||||||
|
@param [in] bDevStatus Device status
|
||||||
|
*/
|
||||||
|
static void HandleUsbReset(U8 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;
|
||||||
|
}
|
||||||
|
|
32
VCOM_lib/usbser.inf
Normal file
32
VCOM_lib/usbser.inf
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
[Version]
|
||||||
|
Signature="$Windows NT$"
|
||||||
|
Class=Ports
|
||||||
|
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
|
||||||
|
Provider=%CodeRed%
|
||||||
|
DriverVer=05/20/2010,1.0.0.0
|
||||||
|
|
||||||
|
[MANUFACTURER]
|
||||||
|
%ProviderName%=DeviceList, NTx86, NTamd64
|
||||||
|
|
||||||
|
[DeviceList.NTx86]
|
||||||
|
%RDB1768CDC%=DriverInstall,USB\VID_FFFF&PID_0005
|
||||||
|
|
||||||
|
[DeviceList.NTamd64]
|
||||||
|
%RDB1768CDC%=DriverInstall,USB\VID_FFFF&PID_0005
|
||||||
|
|
||||||
|
[DriverInstall]
|
||||||
|
include=mdmcpq.inf
|
||||||
|
CopyFiles=FakeModemCopyFileSection
|
||||||
|
AddReg=LowerFilterAddReg,SerialPropPageAddReg
|
||||||
|
|
||||||
|
[DriverInstall.Services]
|
||||||
|
include = mdmcpq.inf
|
||||||
|
AddService = usbser, 0x00000002, LowerFilter_Service_Inst
|
||||||
|
|
||||||
|
; This adds the serial port property tab to the device properties dialog
|
||||||
|
[SerialPropPageAddReg]
|
||||||
|
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
||||||
|
|
||||||
|
[Strings]
|
||||||
|
ProviderName = "CDC Driver"
|
||||||
|
RDB1768CDC = "LPCUSB Virtual Com Port
|
434
VCOM_lib/usbstdreq.c
Normal file
434
VCOM_lib/usbstdreq.c
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CodeRed - include the LPCUSB type.h file rather than NXP one directly
|
||||||
|
//#include "type.h"
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
#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 U8 bConfiguration = 0;
|
||||||
|
/** Installed custom request handler */
|
||||||
|
static TFnHandleRequest *pfnHandleCustomReq = NULL;
|
||||||
|
/** Pointer to registered descriptors */
|
||||||
|
static const U8 *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 U8 *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(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData)
|
||||||
|
{
|
||||||
|
U8 bType, bIndex;
|
||||||
|
U8 *pab;
|
||||||
|
int iCurIndex;
|
||||||
|
wLangID = wLangID;
|
||||||
|
ASSERT(pabDescrip != NULL);
|
||||||
|
|
||||||
|
bType = GET_DESC_TYPE(wTypeIndex);
|
||||||
|
bIndex = GET_DESC_INDEX(wTypeIndex);
|
||||||
|
|
||||||
|
pab = (U8 *)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(U8 bConfigIndex, U8 bAltSetting)
|
||||||
|
{
|
||||||
|
U8 *pab;
|
||||||
|
U8 bCurConfig, bCurAltSetting;
|
||||||
|
U8 bEP;
|
||||||
|
U16 wMaxPktSize;
|
||||||
|
|
||||||
|
ASSERT(pabDescrip != NULL);
|
||||||
|
|
||||||
|
if (bConfigIndex == 0) {
|
||||||
|
// unconfigure device
|
||||||
|
USBHwConfigDevice(FALSE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// configure endpoints for this configuration/altsetting
|
||||||
|
pab = (U8 *)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, U8 **ppbData)
|
||||||
|
{
|
||||||
|
U8 *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, U8 **ppbData)
|
||||||
|
{
|
||||||
|
U8 *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, U8 **ppbData)
|
||||||
|
{
|
||||||
|
U8 *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, U8 **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;
|
||||||
|
}
|
||||||
|
|
121
VCOM_lib/usbstruct.h
Normal file
121
VCOM_lib/usbstruct.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
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"
|
||||||
|
#include "lpcusb_type.h"
|
||||||
|
|
||||||
|
|
||||||
|
/** setup packet definitions */
|
||||||
|
typedef struct {
|
||||||
|
U8 bmRequestType; /**< characteristics of the specific request */
|
||||||
|
U8 bRequest; /**< specific request */
|
||||||
|
U16 wValue; /**< request specific parameter */
|
||||||
|
U16 wIndex; /**< request specific parameter */
|
||||||
|
U16 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 {
|
||||||
|
U8 bLength; /**< descriptor length */
|
||||||
|
U8 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_ */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user