VCOM_lib1.3

This commit is contained in:
Todd Fleming 2017-01-09 18:47:25 -05:00
parent 2aed667897
commit 99a520a442
15 changed files with 2806 additions and 0 deletions

6
VCOM_lib/intenable.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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_ */