📄 recv.c
字号:
pIrDevice->RxState = RX_STATE_IN_ESC;
break;
case SLOW_IR_EOF:
pIrDevice->RxState = RX_STATE_READY;
// Compute data size.
pRxBuf->cbData = (DWORD)(pData - pRxBuf->pbBuffer);
fcs = ComputeFCS(
pRxBuf->pbBuffer,
pRxBuf->cbData
);
if (fcs == GOOD_FCS)
{
pIrDevice->cPacketsRx++;
// Take off size of FCS.
pRxBuf->cbData -= SLOW_IR_FCS_SIZE;
goto done;
}
else
{
// Reset.
pIrDevice->cPacketsRxDropped++;
DEBUGMSG(ZONE_ERROR,
(TEXT("Rx:Bad FCS (%x) count = %d\r\n"),
fcs, pIrDevice->cPacketsRxDropped)
);
}
break;
default:
if (pData < pLimit)
{
*pData++ = bRead;
}
else
{
// Overflow. Reset.
pIrDevice->RxState = RX_STATE_READY;
pIrDevice->cPacketsRxOverflow++;
DEBUGMSG(ZONE_ERROR,
(TEXT("Rx:Overflow[2] count = %d.\r\n"),
pIrDevice->cPacketsRxOverflow)
);
}
break;
}
break; // RX_STATE_RX.
case RX_STATE_SHUTDOWN:
DEBUGMSG(ZONE_WARN, (TEXT("Rx:Shutting down receive thread.\r\n")));
fSuccess = FALSE;
goto done;
default:
// Illegal state.
ASSERT(FALSE);
pIrDevice->RxState = RX_STATE_READY;
break;
}
}
}
done:
#ifdef DEBUG
if (fSuccess == TRUE)
{
DEBUGMSG(ZONE_RECV,
(TEXT("-RxFrame [TRUE -> buffer = 0x%.8x, bytes = %d, ")
TEXT("Total read (incl. esc/fcs) = %d]\r\n"),
pRxBuf->pbBuffer, pRxBuf->cbData, cbTotalRead)
);
}
else
{
DEBUGMSG(ZONE_RECV, (TEXT("-RxFrame [FALSE]\r\n")));
}
#endif // DEBUG
return (fSuccess);
}
/*++
Function: RxReadByte
Description: This will either read a byte from an array of previously
buffered data, or call ReadFile to read in more data
and return a byte.
Arguments:
pIrDevice - Pointer to the IR device object.
lpRead - Pointer to a byte to return.
lpcbRead - Number of bytes returned - either 0 or 1.
Returns:
BOOL
Success - TRUE. Read bytes successfully or timed-out.
Failure - FALSE. Some ReadFile error.
Comments:
--*/
BOOL
RxReadByte(
PIR_DEVICE pIrDevice,
LPBYTE lpRead,
LPDWORD lpcbRead
)
{
DWORD dwCommMask;
BOOL fWaitCommMask;
// If we have data buffered, return byte immediately.
if (pIrDevice->iRxCurrByte < pIrDevice->cbRxNumBytes)
{
*lpRead = pIrDevice->lpRxBuf[pIrDevice->iRxCurrByte++];
*lpcbRead = 1;
return (TRUE);
}
pIrDevice->cbRxNumBytes = 0;
// Need to read bytes from serial driver.
if (ReadFile(
pIrDevice->hSerial,
pIrDevice->lpRxBuf,
pIrDevice->cbRxBuf,
&pIrDevice->cbRxNumBytes,
0) == FALSE)
{
return (FALSE);
}
// Did we get any data? If not, block using WaitCommEvent until we do.
if (pIrDevice->cbRxNumBytes == 0)
{
// dwBPS might be changed to FIR rate while ReadFile is running.
// We should check it
// if the baudrate becomes one of follows.
if (pIrDevice->pCurrBaud->dwBPS == 576000 ||
pIrDevice->pCurrBaud->dwBPS == 1152000 ||
pIrDevice->pCurrBaud->dwBPS == 4000000 )
{
*lpcbRead = 0;
return TRUE;
}
// We will use the CommMask to figure out media busy.
fWaitCommMask = TRUE;
while (fWaitCommMask == TRUE)
{
if (WaitCommEvent(pIrDevice->hSerial, &dwCommMask, NULL) == FALSE)
{
DEBUGMSG(ZONE_COMMMASK, (TEXT("WaitCommEvent failure = 0x%x.\r\n"),
GetLastError()));
break;
}
// If woken by SetCommMask, just continue.
if (dwCommMask == 0) { continue; }
DEBUGMSG(ZONE_COMMMASK,
(TEXT("Rx:WaitCommEvent: 0x%.8X\r\n"), dwCommMask));
NdisAcquireSpinLock(&pIrDevice->slDevice);
if (dwCommMask & EV_RXCHAR)
{
pIrDevice->fMediaBusy = TRUE;
fWaitCommMask = FALSE;
}
else if (dwCommMask & EV_ERR)
{
pIrDevice->fMediaBusy = TRUE;
pIrDevice->dwCommMask &= ~EV_ERR;
if (SetCommMask(pIrDevice->hSerial, pIrDevice->dwCommMask) == FALSE)
{
fWaitCommMask = FALSE;
}
DEBUGMSG(ZONE_COMMMASK,
(TEXT("Rx:SetCommMask 0x%.8X\r\n"),
pIrDevice->dwCommMask)
);
#ifdef DEBUG
// This will be used to get statistical info on MB. Will be
// reset in SetMB.
pIrDevice->cMediaBusyRxErrs++;
#endif // DEBUG
}
NdisReleaseSpinLock(&pIrDevice->slDevice);
}
if ((dwCommMask & EV_RXCHAR) == 0)
{
// Error or closed handle, let's bail.
return (FALSE);
}
// We can try to read as much as possible. We know that we have at
// least one byte and RX timeout it to return immediately.
if (ReadFile(
pIrDevice->hSerial,
pIrDevice->lpRxBuf,
pIrDevice->cbRxBuf,
&pIrDevice->cbRxNumBytes,
0) == FALSE)
{
return (FALSE);
}
}
#ifdef DEBUG
if (ZONE_RAWRXTX)
{
DWORD i;
TCHAR buffer[1024];
TCHAR *pBuf = buffer;
for (i = 0; i < pIrDevice->cbRxNumBytes; i++, pBuf = pBuf + 3)
{
wsprintf(pBuf, TEXT("%02X "), pIrDevice->lpRxBuf[i]);
}
pBuf[0] = TEXT('\0');
DEBUGMSG(ZONE_RAWRXTX, (TEXT("%s\r\n"), buffer));
}
// Keep track of how many bytes are received. This is reset on SetMB.
pIrDevice->cMediaBusyRxBytes += pIrDevice->cbRxNumBytes;
#endif // DEBUG
DEBUGMSG(ZONE_RECV,
(TEXT("RxReadByte read %d from serial.\r\n"), pIrDevice->cbRxNumBytes)
);
// Now return a byte.
pIrDevice->iRxCurrByte = 0;
if (pIrDevice->iRxCurrByte < pIrDevice->cbRxNumBytes)
{
*lpRead = pIrDevice->lpRxBuf[pIrDevice->iRxCurrByte++];
*lpcbRead = 1;
// Set media busy and TAT.
NdisAcquireSpinLock(&pIrDevice->slDevice);
pIrDevice->fMediaBusy = TRUE;
pIrDevice->fMinTATRequired = TRUE;
NdisReleaseSpinLock(&pIrDevice->slDevice);
}
else
{
// We timed-out.
*lpcbRead = 0;
}
return (TRUE);
}
/*++
Function: SetRxTimeouts
Description: Sets the receive timeout values on the serial port.
Arguments:
hSerial - Handle to serial port to set timeout values.
dwReadInterval - Max time in msec to elapse between two characters
arriving.
dwReadTotalMult - Multilplier in msec to calculate timeout. This value
is multiplied by the number of bytes requested.
dwReadTotalConst - Constant read timeout in msec.
Returns:
BOOL
TRUE - Comm timeouts were set successfully.
FALSE - Some error occurred.
Comments:
--*/
static __inline BOOL
SetRxTimeouts(
HANDLE hSerial,
DWORD dwReadInterval,
DWORD dwReadTotalMult,
DWORD dwReadTotalConst
)
{
COMMTIMEOUTS CommTimeouts;
if (GetCommTimeouts(hSerial, &CommTimeouts) == FALSE)
{
return (FALSE);
}
CommTimeouts.ReadIntervalTimeout = dwReadInterval;
CommTimeouts.ReadTotalTimeoutMultiplier = dwReadTotalMult;
CommTimeouts.ReadTotalTimeoutConstant = dwReadTotalConst;
return (SetCommTimeouts(hSerial, &CommTimeouts));
}
/*++
Function: GetRxBuffer
Description: Gets an unused receive buffer from the free list.
Arguments:
pIrDevice - Pointer to the IR device to get recv buffer from.
Returns:
PRX_BUFFER
Success - Valid pointer to an RX_BUFFER.
Failure - NULL.
Comments:
--*/
static PRX_BUFFER
GetRxBuffer(
PIR_DEVICE pIrDevice
)
{
PNDIS_PACKET_OOB_DATA pOobData;
PNDIS_BUFFER pNdisBuffer;
PRX_BUFFER pRxBuf;
pRxBuf = (PRX_BUFFER)NdisInterlockedRemoveHeadList(
&pIrDevice->RxBufFree,
&pIrDevice->slDevice
);
if (pRxBuf != NULL)
{
// Zero data buffer.
NdisZeroMemory(pRxBuf->pbBuffer, pRxBuf->cbBuffer);
// Zero OOB data in packet.
pOobData = NDIS_OOB_DATA_FROM_PACKET(pRxBuf->pPacket);
ASSERT(pOobData);
NdisZeroMemory(pOobData, sizeof(NDIS_PACKET_OOB_DATA));
// Reset packet/buffer size.
NdisQueryPacket(pRxBuf->pPacket, NULL, NULL, &pNdisBuffer, NULL);
NdisAdjustBufferLength(pNdisBuffer, pRxBuf->cbBuffer);
pRxBuf->cbData = 0;
// This forces NdisQueryPacket to recalculate #packets and #bytes.
pRxBuf->pPacket->Private.ValidCounts = FALSE;
}
return (pRxBuf);
}
/*++
Function: ReturnRxBuffer
Description: Return a receive buffer to the free list.
Arguments:
pIrDevice - Pointer to a device to return recv buffer to.
pRxBuf - Recv buffer to add back to free list.
Returns:
None.
Comments:
--*/
static __inline VOID
ReturnRxBuffer(
PIR_DEVICE pIrDevice,
PRX_BUFFER pRxBuf
)
{
NdisInterlockedInsertTailList(
&pIrDevice->RxBufFree,
&pRxBuf->Linkage,
&pIrDevice->slDevice
);
return;
}
/*++
Function: AddRxPendingBuffer
Description: Add a receive buffer to the pending queue.
Arguments:
pIrDevice - Pointer to the IR device object.
pRxBuf - Pointer to the recv buffer to add to the pending queue.
Returns:
None.
Comments:
--*/
static __inline VOID
AddRxPendingBuffer(
PIR_DEVICE pIrDevice,
PRX_BUFFER pRxBuf
)
{
NdisInterlockedInsertTailList(
&pIrDevice->RxBufPending,
&pRxBuf->Linkage,
&pIrDevice->slDevice
);
return;
}
/*++
Function: RemoveRxPendingBuffer
Description: Removes a receive buffer from the pending queue, based
on the associated NDIS_PACKET address.
Arguments:
pIrDevice - Pointer to the IR device object.
pNdisPacket - Pointer to the NDIS packet to remove from the pending queue.
Returns:
PRX_BUFFER
Success - Removed the RX_BUFFER with the NDIS packet.
Failure - NULL. Could not find an RX_BUFFER with the given NDIS packet.
Comments:
Need to go through the pending queue and search for the NDIS packet pointer
in the RX_BUFFER to match.
--*/
static PRX_BUFFER
RemoveRxPendingBuffer(
PIR_DEVICE pIrDevice,
PNDIS_PACKET pNdisPacket
)
{
PRX_BUFFER pRxBuf;
PLIST_ENTRY pEntry;
NdisAcquireSpinLock(&pIrDevice->slDevice);
for (pEntry = pIrDevice->RxBufPending.Flink;
pEntry != &pIrDevice->RxBufPending;
pEntry = pEntry->Flink
)
{
pRxBuf = (PRX_BUFFER)pEntry;
if (pRxBuf->pPacket == pNdisPacket)
{
RemoveEntryList(pEntry);
break;
}
}
if (pEntry == &pIrDevice->RxBufPending)
{
pRxBuf = NULL;
}
NdisReleaseSpinLock(&pIrDevice->slDevice);
return (pRxBuf);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -