📄 upsd_usb.c
字号:
/////////////////////////////////////////////////////////////////////////////
// upsd_usb.c
//
// USB driver module for uPSD3000 chip.
//
// Author: Jon Moore
//
// Revision History:
//
// 07/22/02 (JAM) Initial coding.
// 01/21/03 (JAM) V1.0.7 - Fixed '0 length packet' bug.
/*---------------------------------------------------------------------------
Copyright (c) 2002 ST Microelectronics
This example demo code is provided as is and has no warranty,
implied or otherwise. You are free to use/modify any of the provided
code at your own risk in your applications with the expressed limitation
of liability (see below) so long as your product using the code contains
at least one uPSD products (device).
LIMITATION OF LIABILITY: NEITHER STMicroelectronics NOR ITS VENDORS OR
AGENTS SHALL BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
--------------------------------------------------------------------------*/
#include "general.h"
#include "upsd3200.h"
#include "upsd_xreg.h"
#include "upsd_usb.h"
//-- Variables ---------------------------------------------------------------
#define HID_DEVICE 1
// Constant Variables for USB configuration
extern const uchar code cUSCL_value;
// Constant Variables for USB Descriptors
extern const device_descriptor code deviceDesc;
extern const configuration_descriptor code configDesc;
extern const uchar code string0Desc[];
extern const uchar code string1Desc[];
extern const uchar code string2Desc[];
extern const uchar * const code stringDescTable[];
#if HID_DEVICE
extern const uchar code hidClassDesc[];
extern const uchar code hidClassDescSize;
extern const uchar code reportDesc[];
extern const uchar code reportDescSize;
#endif
volatile uchar idata usbState;
volatile uchar idata SuspendCounter;
setup_buffer setupPacket;
static uchar* pTransmitBufferEP0;
static int bytesToTransmitEP0;
static BOOL shortTransfer;
extern void OnDeviceConfigured();
/////////////////// UsbInitialize()
//
// USB driver module initialization routine.
void UsbInitialize()
{
pTransmitBufferEP0 = NULL;
bytesToTransmitEP0 = 0;
// Set USB clock prescaler
USCL = cUSCL_value;
// Reset EP0 and arm it for receiving only
UCON0 = uTX0E | uRX0E | 8;
UCON0 = uRX0E | 8;
// Enable ep1
UCON2 = uEP1E | uEP2E;
UCON1 = uTX1E | 8;
UDT1 = 0xBA;
UDT1 = 0xBE;
UCON1 = uTX1E | 2;
// Enable all USB interrupts except uMCUR (MCU reset on USB reset)
UIEN = ~uMCUR;
// Enable USB with default address 0
UADR = uUSBEN + 0;
// Enable USB interrupts
UISTA = 0;
IEA |= bEUSB;
}
/////////////////// OnClearFeature()
//
// Handler for CLEAR_FEATURE control requests.
static void OnClearFeature()
{
// No features currently implemented, so stall EP0
// UCON0 |= uSTALL0; problems, so try 0 length packet instead
UCON0 = uTSEQ0 | uRX0E | uTX0E;
}
/////////////////// OnSetAddress()
//
// Handler for SET_ADDRESS SETUP packets.
static void OnSetAddress()
{
// Send back 0 length DATA1 packet
UCON0 = uTSEQ0 | uRX0E | uTX0E;
}
/////////////////// OnSetConfiguration()
//
// Handler for SET_CONFIGURATION SETUP requests.
static void OnSetConfiguration()
{
if (setupPacket.wValue.lo > 0)
{
usbState = US_CONFIGURED;
OnDeviceConfigured();
}
else
{
usbState = US_ADDRESSED;
}
// Send back 0 length DATA1 packet
UCON0 = uTSEQ0 | uRX0E | uTX0E;
}
/////////////////// TransmitBufferEP0()
//
// Transmits next segment of descriptor buffer (pTransmitBufferEP0).
static BOOL TransmitBufferEP0()
{
int i;
int nBytes;
// If there is data going out...
if (pTransmitBufferEP0)
{
// If data has already been sent...
if (!bytesToTransmitEP0)
{
// Transmit 0 length packet
UCON0 = ((UCON0 ^ uTSEQ0) & uTSEQ0) | uRX0E | uTX0E;
pTransmitBufferEP0 = NULL;
}
else
{
// Transmit next chunk of data
nBytes = bytesToTransmitEP0;
if (nBytes > 8)
nBytes = 8;
UCON0 = ((UCON0 ^ uTSEQ0) & uTSEQ0) | uRX0E | uTX0E | nBytes;
for (i = 0; i < nBytes; i++)
{
UDT0 = *pTransmitBufferEP0++;
}
if ((bytesToTransmitEP0 -= nBytes) == 0)
{
// For short transfers, we need a 0 length terminator
if (!shortTransfer || (nBytes < 8))
{
pTransmitBufferEP0 = NULL;
}
}
}
return TRUE;
}
// No descriptor data going out
UCON0 = uTSEQ0 | uRX0E;
return FALSE;
}
/////////////////// TransmitDataEP0()
//
// Load and arm EP0 to transmit data.
void TransmitDataEP0(uchar* pData, int nBytes)
{
if (nBytes > EP0_SIZE)
nBytes = EP0_SIZE;
UCON0 = ((UCON0 ^ uTSEQ0) & uTSEQ0) | uRX0E | uTX0E | nBytes;
while (nBytes--)
{
UDT0 = *pData++;
}
}
/////////////////// TransmitDataEPx()
//
// Loads and arms EP1 or EP2 transmit FIFO.
void TransmitDataEPx(int x, uchar* pData, int nBytes)
{
int i;
// Reset FIFO
UCON1 |= (uTX1E | 8);
if ((x == 1) && (nBytes > 8))
{
nBytes = 8;
}
else if ((x == 2) && (nBytes > 8))
{
nBytes = 8;
}
// Load data
for (i = 0; i < nBytes; i++)
{
UDT1 = *pData++;
}
// Arm endpoint
UCON1 = ((UCON1 ^ uTSEQ1) & uTSEQ1)
| uTX1E | ((x == 2) ? uEP12SEL : 0) | nBytes;
}
/////////////////// OnGetDescriptor()
static void OnGetDescriptor()
{
int bytesRequested;
switch (setupPacket.wValue.hi)
{
case DT_DEVICE:
pTransmitBufferEP0 = (uchar*) &deviceDesc;
bytesToTransmitEP0 = sizeof(deviceDesc);
break;
case DT_CONFIGURATION:
pTransmitBufferEP0 = (uchar*) &configDesc;
bytesToTransmitEP0 = configDesc.wTotalLength.lo;
break;
case DT_STRING:
pTransmitBufferEP0 = (uchar*) stringDescTable[setupPacket.wValue.lo];
bytesToTransmitEP0 = *pTransmitBufferEP0;
break;
#if HID_DEVICE
case DT_HID_CLASS:
pTransmitBufferEP0 = (uchar*) &hidClassDesc;
bytesToTransmitEP0 = hidClassDescSize;
break;
case DT_HID_REPORT:
pTransmitBufferEP0 = (uchar*) &reportDesc;
bytesToTransmitEP0 = reportDescSize;
break;
#endif
default:
// Unrecognized descriptor, so stall EP0
// UCON0 |= uSTALL0; - problems, so try 0 length packet instead
UCON0 = uTSEQ0 | uRX0E | uTX0E;
return;
}
bytesRequested = (setupPacket.wLength.hi << 8) | setupPacket.wLength.lo;
shortTransfer = (bytesToTransmitEP0 < bytesRequested);
if (bytesToTransmitEP0 > bytesRequested)
{
bytesToTransmitEP0 = bytesRequested;
}
// TransmitDataEP0 will toggle sequence bit to DATA1
UCON0 &= ~uTSEQ0;
TransmitBufferEP0();
}
/////////////////// ReadSetupPacket()
//
// Reads a setup packet from EP0.
//
// Returns TRUE if successful; stalls the endpoint and returns
// FALSE on an invalid packet size.
BOOL ReadSetupPacket()
{
int i;
uchar* p = (uchar*) &setupPacket;
// Make sure the SETUP packet is the correct size
if ((USTA & 0x0F) != 8)
{
UCON0 |= uSTALL0;
return FALSE;
}
// Read the setup packet
for (i = 0; i < sizeof(setup_buffer); i++)
{
*p++ = UDR0;
}
// Set data toggle bit (expecting DATA1)
USTA |= uRSEQ;
return TRUE;
}
/////////////////// OnSetupPacket()
//
// Basic handler for SETUP packets received on EP0.
void OnSetupPacket()
{
pTransmitBufferEP0 = NULL;
bytesToTransmitEP0 = 0;
// If it's a standard request...
if ((setupPacket.bmRequestType & 0x60) == 0)
{
// Handle the request
switch (setupPacket.bRequest)
{
case CLEAR_FEATURE:
OnClearFeature();
return;
case SET_ADDRESS:
OnSetAddress();
return;
case GET_DESCRIPTOR:
OnGetDescriptor();
return;
case SET_CONFIGURATION:
OnSetConfiguration();
return;
default:
break;
}
}
// It's not a request we handle so stall endpoint
// UCON0 |= uSTALL0; - problems, so try zero length packet instead
UCON0 = uTSEQ0 | uRX0E | uTX0E;
}
/////////////////// BaseEp0TxHandler()
//
// Handler for successful data transmission on control endpoint (EP0).
void BaseEp0TxHandler()
{
// Send next chunk of data in transaction
if (!TransmitBufferEP0())
{
// The current request has finished
if (setupPacket.bRequest == SET_ADDRESS)
{
UADR = setupPacket.wValue.lo | uUSBEN;
if (setupPacket.wValue.lo != 0)
usbState = US_ADDRESSED;
else
usbState = US_DEFAULT;
}
setupPacket.bRequest = REQUEST_COMPLETE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -