📄 serial_dl.cpp
字号:
// Update EP0 Request to send data, as this is a GET request.
pRequest->eDir = EP0In;
pRequest->pucData = pucData;
pRequest->dwExpectedSize = pUdr->wLength;
pRequest->dwActualSize = min(wLength, pUdr->wLength);
}
//------------------------------------------------------------------------------
//
// Function: HandleTransferComplete
//
// Respond to UFN_MSG_TRANSFER_COMPLETE. Do some cleanup and change EP state.
//
void HandleTransferComplete(STransfer *pTransfer)
{
if( pTransfer == &g_EP0Transfer )
{
g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
g_EP0State = TS_IDLE;
}
else if( pTransfer == &g_EP1Transfer )
{
// Data received on BULK OUT endpoint
if( g_EP1Transfer.dwUsbError != UFN_NO_ERROR )
{
OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated there was a transfer error on EP1!\r\n"));
DEBUGCHK(0);
}
if(g_EP1State != TS_RECEIVING_PACKET)
{
OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated RECV complete before transfer issued! ep1st is 0x%X\r\n",g_EP1State));
DEBUGCHK(0);
}
g_EP1State = TS_IDLE;
}
else if( pTransfer == &g_EP2Transfer )
{
if( g_EP2State == TS_SENDING_PACKET )
{
// Data sent on BULK IN endpoint
if( g_EP2Transfer.cbTransferred != g_EP2Transfer.cbBuffer )
{
OALMSG(OAL_ERROR, (L"ERROR: Sent data does not match expected size!\r\n"));
DEBUGCHK(0);
}
if( g_EP2Transfer.dwUsbError != UFN_NO_ERROR )
{
OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated there was a transfer error on EP2!\r\n"));
DEBUGCHK(0);
}
if( (g_EP2Transfer.cbTransferred % EPMaxSize ) == 0 )
{
g_EP2Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
g_EP2Transfer.pvBuffer = NULL;
g_EP2Transfer.cbBuffer = 0;
g_EP2Transfer.cbTransferred = 0;
g_EP2Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR;
g_EP2Transfer.pvPddData = NULL;
g_EP2Transfer.pvPddTransferInfo = NULL;
g_EP2State = TS_SENDING_PACKET_TERMINATOR;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 2, &g_EP2Transfer );
}
else
{
g_EP2State = TS_IDLE;
}
}
else if ( g_EP2State == TS_SENDING_PACKET_TERMINATOR)
{
if( g_EP2Transfer.dwUsbError != UFN_NO_ERROR )
{
OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated there was a transfer error on EP2 terminator!\r\n"));
DEBUGCHK(0);
}
g_EP2State = TS_IDLE;
}
else
{
ASSERT(!"Endpoint 2 has entered an unsupported state!");
}
}
else
{
ASSERT(!"PDD Signaled bogus transfer complete!");
}
}
//------------------------------------------------------------------------------
//
// Function: HandleSetupPkt
//
// Respond to SETUP packets as they come in from the PDD on EP0
//
static void HandleSetupPkt(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
//At a minimum prepare to ACK the SETUP packet
pRequest->eDir = EP0Setup;
pRequest->pucData = NULL;
pRequest->dwExpectedSize = 0;
pRequest->dwActualSize = 0;
pRequest->pfnNotification = NULL;
pRequest->pvUser = NULL;
switch( pUdr->bmRequestType )
{
case USB_REQUEST_DEVICE_TO_HOST:
case USB_REQUEST_HOST_TO_DEVICE:
switch( pUdr->bRequest )
{
case USB_REQUEST_GET_DESCRIPTOR:
HandleGetDescriptor(pUdr, pRequest);
break;
case USB_REQUEST_SET_CONFIGURATION:
g_DeviceState = DS_CONFIGURED;
break;
default:
ASSERT(!"Only GET_DESC and SET_CONFIG supported!");
}
break;
default:
HandleClassRequest(pUdr, pRequest);
}
}
//------------------------------------------------------------------------------
//
// Function: HandlePDDNotification
//
// The USB FN PDD will call this function to notify it of various events (data sent/received,
// setup packet received, device addressed, reset, etc.
//
static BOOL WINAPI HandlePDDNotification (
PVOID pvMddContext,
DWORD dwMsg,
DWORD dwParam
)
{
EP0_REQUEST Request;
EP0_REQUEST *pRequest = &Request;
switch( dwMsg )
{
case UFN_MSG_SETUP_PACKET:
HandleSetupPkt( (USB_DEVICE_REQUEST*)(void*)dwParam, pRequest);
pRequest->dwProcessed = 0;
pRequest->fCompleted = FALSE;
if( pRequest->eDir != EP0Setup )
{
g_EP0Transfer.pvBuffer = pRequest->pucData;
g_EP0Transfer.cbBuffer = pRequest->dwActualSize;
g_EP0Transfer.cbTransferred = 0;
g_EP0Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR;
g_EP0Transfer.pvPddData = NULL;
g_EP0Transfer.pvPddTransferInfo = NULL;
if( pRequest->eDir == EP0In )
{
OALMSG(OAL_FUNC, (L"Got SETUP IN packet\r\n"));
g_EP0Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
g_EP0State = TS_SENDING_MESSAGE;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer);
}
else
{
OALMSG(OAL_FUNC, (L"Got SETUP OUT packet\r\n"));
g_EP0Transfer.dwFlags = USB_REQUEST_HOST_TO_DEVICE;
g_EP0State = TS_RECEIVING_MESSAGE;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer);
}
}
else
{
g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
g_EP0State = TS_IDLE;
}
break;
case UFN_MSG_TRANSFER_COMPLETE:
HandleTransferComplete( (STransfer*)(void*)dwParam);
break;
case UFN_MSG_BUS_EVENTS:
switch( dwParam )
{
case UFN_DETACH:
g_DeviceState = DS_DETACHED;
break;
case UFN_ATTACH:
g_DeviceState = DS_ATTACHED;
break;
case UFN_RESET:
g_DeviceState = DS_DEFAULT;
// TODO: return to clean state?
break;
case UFN_SUSPEND:
g_DeviceState = DS_SUSPENDED;
break;
case UFN_RESUME:
g_DeviceState = DS_DEFAULT;
break;
default:
ASSERT(!"Unexpected bus event!");
}
break;
case UFN_MSG_BUS_SPEED:
break;
case UFN_MSG_SET_ADDRESS:
if( dwParam ) g_DeviceState = DS_ADDRESSED;
else g_DeviceState = DS_DEFAULT;
break;
default:
ASSERT(!"Unexpected Msg in HandlePDDNotification!");
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: USBSerialInit
//
// Lets send some data to the USB Bus.
//
BOOL USBSerialInit()
{
if(g_USBSerialInitialized)
{
OALMSG(OAL_ERROR, (L"ERROR: USBSerialInit called again before USBSerialDeinit\r\n"));
return FALSE;
}
// Setup the MDD/PDD interface structures
g_mddInterface.dwVersion = 1;
g_mddInterface.pfnNotify = HandlePDDNotification;
memset( &g_pddInterface, 0, sizeof(g_pddInterface) );
g_pddInterface.dwVersion = 1;
// Initialize our internal receive buffer markers
g_RecvBufferHead = g_RecvBufferTail = 0;
// Give the OEM an opportunity to setup clocks, GPIOs, etc:
if( !InitializeHardware() )
{
OALMSG(OAL_ERROR, (L"InitializeHardware failed!"));
return FALSE;
}
// Initialize USB Function block
if( UfnPdd_Init( NULL, (PVOID)0xdeadbeef, &g_mddInterface, &g_pddInterface ) != ERROR_SUCCESS )
{
OALMSG(OAL_ERROR, (L"UfnPdd_Init failed!"));
return FALSE;
}
// Negotiate with hardware by calling IsEndpointSupportable, IsConfigurationSupportable, etc.
// Update descriptors to reflect negotiated endpoints.
HandleUSBDeviceRegistration();
// Setup complete, Attach device to USB bus
g_pddInterface.pfnStart( g_pddInterface.pvPddContext );
// Give time for host to recognize device
// Sometimes we can hang without this delay
msWait(1);
// Respond to GET_DESCRIPTOR, SET_ADDRESS... until SET_CONFIGURATON
while( g_DeviceState != DS_CONFIGURED )
{
InterruptThread( g_pddInterface.pvPddContext );
}
g_USBSerialInitialized = TRUE;
return g_USBSerialInitialized;
}
//------------------------------------------------------------------------------
//
// Function: OEMSerialSendRaw
//
// Lets send some data to the USB Bus.
//
BOOL OEMSerialSendRaw(LPBYTE pbFrame, USHORT cbFrame)
{
if( !g_USBSerialInitialized)
{
OALMSG(OAL_ERROR, (L"ERROR: OEMSerialSendRaw called before USBSerialInit\r\n"));
return g_USBSerialInitialized;
}
// Package the transfer information into a struct to pass to PDD
g_EP2Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
g_EP2Transfer.pvBuffer = pbFrame;
g_EP2Transfer.cbBuffer = cbFrame;
g_EP2Transfer.cbTransferred = 0;
g_EP2Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; //possible values in usbfntypes.h
g_EP2Transfer.pvPddData = NULL;
g_EP2Transfer.pvPddTransferInfo = NULL;
g_EP2State = TS_SENDING_PACKET;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext,
rgEndPoints[2].Descriptor.bEndpointAddress & 0x7F,
&g_EP2Transfer);
// Poll Interrupt thread until they call notification routine
while( g_EP2State != TS_IDLE )
{
InterruptThread( g_pddInterface.pvPddContext );
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: OEMSerialRecvRaw
//
// Lets get some data from our internal buffer to return to caller. If we don't have enough data,
// we'll wait until we get it from the USB bus.
//
BOOL OEMSerialRecvRaw(LPBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite)
{
USHORT space;
// Make sure OEMSerialRecvRaw is called before USBSerialInit
if( !g_USBSerialInitialized)
{
OALMSG(OAL_ERROR, (L"ERROR: OEMSerialRecvRaw called before USBSerialInit\r\n"));
return FALSE;
}
// Sanity check parameters
if( *pcbFrame > RECV_BUFFER_SIZE - rgEndPoints[1].Descriptor.wMaxPacketSize + 1 )
{
OALMSG(OAL_ERROR, (L"ERROR: OEMSerialRecvRaw caller asking for 0x%X bytes\r\n",*pcbFrame));
OALMSG(OAL_ERROR, (L"Must increase RECV_BUFFER_SIZE to accomodate request!\r\n"));
OALMSG(OAL_ERROR, (L"Exiting OEMSerialRecvRaw....\r\n"));
return FALSE;
}
// If our internal buffer cannot satisfy the receive request
while( *pcbFrame > SPACE_IN_BUFFER(g_RecvBufferHead, g_RecvBufferTail) )
{
space = SPACE_IN_BUFFER(g_RecvBufferHead, g_RecvBufferTail);
// Serial interface won't be able to wrap its pointer...account for this
if( SPACE_UNTIL_WRAP(g_RecvBufferTail) <
rgEndPoints[1].Descriptor.wMaxPacketSize)
{
memmove( &g_RecvBuffer[0], &g_RecvBuffer[g_RecvBufferHead], space);
g_RecvBufferHead = 0;
g_RecvBufferTail = space;
}
// Package the transfer information into a struct to pass to PDD
g_EP1Transfer.dwFlags = USB_REQUEST_HOST_TO_DEVICE;
g_EP1Transfer.pvBuffer = &g_RecvBuffer[g_RecvBufferTail];
g_EP1Transfer.cbBuffer = rgEndPoints[1].Descriptor.wMaxPacketSize;
g_EP1Transfer.cbTransferred = 0;
g_EP1Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; //possible values in usbfntypes.h
g_EP1Transfer.pvPddData = NULL;
g_EP1Transfer.pvPddTransferInfo = NULL;
// Update state machine and kick off transfer
g_EP1State = TS_RECEIVING_PACKET;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext,
rgEndPoints[1].Descriptor.bEndpointAddress & 0x7F,
&g_EP1Transfer);
while( g_EP1State != TS_IDLE )
{
InterruptThread( g_pddInterface.pvPddContext );
}
// Done, make sure amount transferred doesn't overflow caller's UCHAR
if( (DWORD)(USHORT)g_EP1Transfer.cbTransferred != g_EP1Transfer.cbTransferred )
{
ASSERT(!"Amount of transferred data in DWORD too large for EBOOTs UCHAR!");
}
// Advance buffer's tail
g_RecvBufferTail = g_RecvBufferTail + (USHORT)g_EP1Transfer.cbTransferred;
if( g_RecvBufferTail >= RECV_BUFFER_SIZE )
{
ASSERT(!"Serial Wrapper Circular Buffer Overflow error!!!");
}
}
// Now, we definately have enough space to work with
ASSERT(*pcbFrame <= SPACE_IN_BUFFER(g_RecvBufferHead, g_RecvBufferTail) );
// Lets give the caller what he wants, advance our buffer's head
memcpy(pbFrame, &g_RecvBuffer[g_RecvBufferHead], *pcbFrame );
g_RecvBufferHead += *pcbFrame;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -