📄 btdriverstreamread.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include "BTDriverStream.h"
static DWORD BTWSSReadFromWindow (PWSSBTCLIENT_CONTEXT ptrcc, BYTE *buffer, int fFirstBuffer)
{
DWORD amountRead = READ_PORT_UCHAR(ptrcc->ioBase + (fFirstBuffer ? FIRST_RX_BUFFER_LENGTH_OFFSET : SECOND_RX_BUFFER_LENGTH_OFFSET));
if(amountRead > RXBUFFERSIZE)
{
amountRead = RXBUFFERSIZE;
}
DWORD firstWindowRead = 0;
if(amountRead >= RX_FIRST_WINDOW_SIZE)
{
firstWindowRead = RX_FIRST_WINDOW_SIZE;
}
else
{
firstWindowRead = amountRead;
}
DWORD secondWindowRead = 0;
if(amountRead > RX_FIRST_WINDOW_SIZE)
{
//There is data in second window
secondWindowRead = amountRead - firstWindowRead;
}
else
{
secondWindowRead = 0;
}
DWORD i = 0;
unsigned char *pioBase = ptrcc->ioBase + (fFirstBuffer ? FIRST_RX_BUFFER_FIRST_WINDOW_DATA_OFFSET : SECOND_RX_BUFFER_FIRST_WINDOW_DATA_OFFSET);
//Read from first window in first buffer
WRITE_PORT_UCHAR(ptrcc->ioBase + CMD_REGISTER_OFFSET, SET_FIRST_RX_WINDOW);
for(i = 0;i< firstWindowRead;i++)
{
*(buffer + i) = READ_PORT_UCHAR(pioBase + i);
}
pioBase = ptrcc->ioBase + (fFirstBuffer ? FIRST_RX_BUFFER_SECOND_WINDOW_DATA_OFFSET : SECOND_RX_BUFFER_SECOND_WINDOW_DATA_OFFSET);
//Read from second window in first buffer
WRITE_PORT_UCHAR(ptrcc->ioBase + CMD_REGISTER_OFFSET, SET_SECOND_RX_WINDOW);
for(i = 0;i< secondWindowRead;i++)
{
*(buffer + firstWindowRead + i) = READ_PORT_UCHAR(pioBase + i);
}
ptrcc->currentRxBuffer = fFirstBuffer ? SECOND_RX_BUFFER : FIRST_RX_BUFFER;
//Acknowledge interrupt
WRITE_PORT_UCHAR(ptrcc->ioBase + INTERRUPT_REGISTER_OFFSET, fFirstBuffer ? FIRST_RX_BUFFER_READY : SECOND_RX_BUFFER_READY);
WRITE_PORT_UCHAR(ptrcc->ioBase + CMD_REGISTER_OFFSET, fFirstBuffer ? START_FIRST_RX_BUFFER : START_SECOND_RX_BUFFER);
return amountRead;
}
///////////////////////////////////////////////////////////////
// BTWSSSetRTSState: Tell the PCCARD to set RTS. RTS here means
// Stop/Start data flow into FPGA from BT
///////////////////////////////////////////////////////////////
int BTWSSSetRTSState(PWSSBTCLIENT_CONTEXT ptrcc, int fOn)
{
DEBUGMSG(ZONE_TRACE, (L"WceStreamBT: BTWSSSetRTSState (%d)\r\n", fOn));
ptrcc->controlShadowRegister &= ~RTS_BIT_MASK;//Zero out RTS
//Set the bit
if (fOn) ptrcc->controlShadowRegister |= (RTS_BIT_MASK * RTS_ON_FLAG);
else ptrcc->controlShadowRegister |= (RTS_BIT_MASK * RTS_OFF_FLAG);
//Convert to proper bitfield here
__try
{
WRITE_PORT_UCHAR(ptrcc->ioBase + CONTROL_REGISTER_OFFSET, ptrcc->controlShadowRegister );
} __except (1)
{
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////
// RxInit: Initialize receive queues
///////////////////////////////////////////////////////////
void
RxInit(PWSSBTCLIENT_CONTEXT ptrcc)
{
__try
{
WRITE_PORT_UCHAR(ptrcc->ioBase + CMD_REGISTER_OFFSET, START_FIRST_RX_BUFFER | START_SECOND_RX_BUFFER);
} __except(1)
{
}
}
////////////////////////////////////////////////////////////
// BTWSSRead: A user application wants to read from us.
// Check if we can complete the request immediately
///////////////////////////////////////////////////////////
DWORD WBT_Read(DWORD dwOpenContext, LPVOID pBuffer, DWORD dwNumBytes)
{
DEBUGMSG(ZONE_TRACE, (L"WceStreamBT: WBT_Read %d bytes\r\n", dwNumBytes));
PWSSBTCLIENT_CONTEXT pcc = (PWSSBTCLIENT_CONTEXT)dwOpenContext;
EnterCriticalSection (&g_CS);
int iTotalTimeout = 0;
int iIntervalTimeout = 0;
if (pcc == g_pCC)
{
if (pcc->fReading)
{
LeaveCriticalSection (&g_CS);
return 0xffffffff;
}
pcc->fReading = TRUE;
iTotalTimeout = pcc->CommTimeOuts.ReadTotalTimeoutConstant;
if (pcc->CommTimeOuts.ReadTotalTimeoutMultiplier != MAXDWORD)
iTotalTimeout += pcc->CommTimeOuts.ReadTotalTimeoutMultiplier * dwNumBytes;
iIntervalTimeout = pcc->CommTimeOuts.ReadIntervalTimeout;
}
int iStartTime = GetTickCount ();
DWORD dwRes = WAIT_OBJECT_0;
DWORD read = 0;
for ( ; ; )
{
if ((pcc != g_pCC) || pcc->fOverflow || (! pcc->fDriverStarted) || (! pcc->fReading))
{
DEBUGMSG(ZONE_ERROR, (L"WceStreamBT: Overflow detected or card removed. Failing the read.\r\n"));
read = 0xffffffff;
break;
}
DWORD read_sav = read;
read += pcc->receiveBuffer->ReadData((BYTE *)pBuffer + read, dwNumBytes - read);
if (pcc->fDriverFlowOff && (pcc->receiveBuffer->GetEmptySpace() >= RESTART_FLOW))
{
//we may turn on flow again
pcc->fDriverFlowOff = FALSE;
BTWSSSetRTSState(pcc, TRUE);
}
if (read == dwNumBytes)
break;
if ((dwRes == WAIT_TIMEOUT) && (read_sav == read)) // Interval t/o and nothing read
break;
HANDLE h = pcc->hReadEvent;
int iGTC = (int)GetTickCount ();
int iTimeout = ((iIntervalTimeout != 0) && (iIntervalTimeout != MAXDWORD)) ? iIntervalTimeout : iTotalTimeout - (iGTC - iStartTime);
if (iTimeout > (iTotalTimeout - (iGTC - iStartTime)))
iTimeout = iTotalTimeout - (iGTC - iStartTime);
if (iTimeout < 0)
break;
pcc->iRefCnt++;
LeaveCriticalSection (&g_CS);
dwRes = WaitForSingleObject (h, iTimeout);
EnterCriticalSection (&g_CS);
if (pcc == g_pCC)
--pcc->iRefCnt;
}
if (pcc == g_pCC)
{
pcc->fReading = FALSE;
}
LeaveCriticalSection (&g_CS);
DEBUGMSG(ZONE_READ, (L"WceStreamBT: Completing a read with %d bytes\r\n",read));
return read;
}
void
BTWSSInterruptRead(PWSSBTCLIENT_CONTEXT ptrcc, BYTE reason) // Critical section taken
{
BYTE buffer [RXFIFOBUFFERSIZE];
DWORD amountRead = 0;
if((ptrcc->currentRxBuffer == FIRST_RX_BUFFER) && (reason & FIRST_RX_BUFFER_READY))
{
amountRead = BTWSSReadFromWindow (ptrcc, buffer, TRUE);
DEBUGMSG(ZONE_INTERRUPTS, (L"WCESTREAMBT:::::::::::::::::::RX1 %d bytes\n", amountRead));
}
else if((ptrcc->currentRxBuffer == SECOND_RX_BUFFER) && (reason & SECOND_RX_BUFFER_READY))
{
amountRead = BTWSSReadFromWindow (ptrcc, buffer, FALSE);
DEBUGMSG(ZONE_INTERRUPTS, (L"WCESTREAMBT:::::::::::::::::::RX2 %d bytes\n", amountRead));
}
else
{
// Die...
DEBUGMSG(ZONE_ERROR, (L"WCESTREAMBT: RX %s signalled, but current is %s\r\n", (reason & FIRST_RX_BUFFER_READY) ? L"FIRST" : L"SECOND", (ptrcc->currentRxBuffer == FIRST_RX_BUFFER) ? L"FIRST" : L"SECOND"));
//Acknowledge interrupt
if (reason & FIRST_RX_BUFFER_READY)
{
WRITE_PORT_UCHAR(ptrcc->ioBase + INTERRUPT_REGISTER_OFFSET, FIRST_RX_BUFFER_READY);
WRITE_PORT_UCHAR(ptrcc->ioBase + CMD_REGISTER_OFFSET, START_FIRST_RX_BUFFER);
}
if (reason & SECOND_RX_BUFFER_READY)
{
WRITE_PORT_UCHAR(ptrcc->ioBase + INTERRUPT_REGISTER_OFFSET, SECOND_RX_BUFFER_READY);
WRITE_PORT_UCHAR(ptrcc->ioBase + CMD_REGISTER_OFFSET, START_SECOND_RX_BUFFER);
}
//
// I would like to drop the card, but it turns out that PCMCIA card does
// raise this condition on initialization. So just clean up and ignore...
//
// ptrcc->fOverflow = TRUE;
// SetEvent (ptrcc->hWriteEvent);
// SetEvent (ptrcc->hReadEvent);
//
return;
}
if(amountRead == 0) return;
DWORD spaceLeft = ptrcc->receiveBuffer->GetEmptySpace();
if(spaceLeft >= amountRead)
{
//NEVER WRITE TOO MUCH DATA IN INTERRUPTHANDLER.
ptrcc->receiveBuffer->WriteData(buffer,amountRead);
}
else
{
// Die...
DEBUGMSG(ZONE_ERROR, (L"WCESTREAMBT: RX overflow!\r\n"));
ptrcc->fOverflow = TRUE;
SetEvent (ptrcc->hWriteEvent);
SetEvent (ptrcc->hReadEvent);
return;
}
if(spaceLeft <= STOP_FLOW)
{
//Stop flow to prevent buffer overflow
ptrcc->fDriverFlowOff=TRUE;
BTWSSSetRTSState(ptrcc, FALSE);
}
SetEvent (ptrcc->hReadEvent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -