📄 sir.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.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, 2005, 2006 Freescale Semiconductor, Inc. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// File: sir.cpp
//
// This file implements the device specific functions for zeus fir device.
//
//------------------------------------------------------------------------------
#include "IrFir.h"
//------------------------------------------------------------------------------
// External Functions
//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Local Variables
//------------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
//
// Function: DumpUart2Reg
//
// Dump Uart2 registers
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID DumpUart2Reg(VOID)
{
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UCR1 is 0x%08x\r\n"), g_pVSIRReg->UCR1));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UCR2 is 0x%08x\r\n"), g_pVSIRReg->UCR2));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UCR3 is 0x%08x\r\n"), g_pVSIRReg->UCR3));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UCR4 is 0x%08x\r\n"), g_pVSIRReg->UCR4));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UFCR is 0x%08x\r\n"), g_pVSIRReg->UFCR));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: USR1 is 0x%08x\r\n"), g_pVSIRReg->USR1));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: USR2 is 0x%08x\r\n"), g_pVSIRReg->USR2));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UBIR is 0x%08x\r\n"), g_pVSIRReg->UBIR));
DEBUGMSG(ZONE_ERROR, (TEXT("DumpUart2Reg: UBMR is 0x%08x\r\n"), g_pVSIRReg->UBMR));
}
//-----------------------------------------------------------------------------
//
// Function: SirHwWrite
//
// Step the send fsm to send a few more bytes of an IR frame.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// This function returns packet send status.
//
//-----------------------------------------------------------------------------
static BOOLEAN SirHwWrite(pFirDevice_t thisDev)
{
UINT i, bytesAtATime, startPos = thisDev->portInfo.sendBufPos;
BOOLEAN result;
UINT maxLoops;
// Ordinarily, we want to fill the send FIFO once per interrupt.
// However, at high speeds the interrupt latency is too slow and
// we need to poll inside the ISR to send the whole packet during
// the first interrupt.
if(thisDev->newSpeed > 115200)
maxLoops = REG_TIMEOUT_LOOPS;
else
maxLoops = REG_POLL_LOOPS;
// Temporarily disable receiver first to avoid receiving data from ourselves
CSP_BITFINS(g_pVSIRReg->UCR2, UART_UCR2_RXEN, UART_UCR2_RXEN_DISABLE);
// Write databytes as long as we have them and the UART's FIFO hasn't filled up.
while (thisDev->portInfo.sendBufPos < thisDev->writeBufLen)
{
// send up to the FIFO size.
bytesAtATime = MIN(SER_FIFO_DEPTH, (thisDev->writeBufLen - thisDev->portInfo.sendBufPos));
// Wait for ready-to-send.
while (!(g_pVSIRReg->USR2 & CSP_BITFMASK(UART_USR2_TXFE)))
Sleep(0);
// Send the next byte or FIFO-volume of bytes.
while (bytesAtATime)
{
DEBUGMSG(ZONE_SEND, (TEXT("Sir: Send 0x%x\r\n"), thisDev->writeBuf[thisDev->portInfo.sendBufPos]));
g_pVSIRReg->UTXD = thisDev->writeBuf[thisDev->portInfo.sendBufPos++];
bytesAtATime--;
}
}
// Wail until transmission complete
i = 0;
while ((!(g_pVSIRReg->USR2 & CSP_BITFMASK(UART_USR2_TXDC))) && (++i < REG_TIMEOUT_LOOPS))
Sleep(0);
// Re-enable receiver once again.
CSP_BITFINS(g_pVSIRReg->UCR2, UART_UCR2_RXEN, UART_UCR2_RXEN_ENABLE);
if (i >= REG_TIMEOUT_LOOPS)
{
DEBUGMSG(ZONE_ERROR, (TEXT("Sir: Wait for tansmitting complete timeout!!"), i));
return FALSE;
}
if (thisDev->portInfo.sendBufPos >= thisDev->writeBufLen)
result = TRUE;
else
result = FALSE;
DEBUGMSG(ZONE_SEND, (TEXT("Sir: SirHwWrite wrote %d bytes (%s): LOOP TIMES %d"), (UINT)(thisDev->portInfo.sendBufPos-startPos), (PUCHAR)(result ? "Successful" : "Failed"), i));
return result;
}
//-----------------------------------------------------------------------------
//
// Function: SirHwRead
//
// Read up to maxBytes bytes from the UART's receive FIFO.
//
// Parameters:
// thisDev
// [in] .
// maxBytes
// [in] .
//
// Returns:
// This function returns number of bytes read.
//
//-----------------------------------------------------------------------------
static UINT SirHwRead(UCHAR *data, UINT maxBytes)
{
UINT bytesRead = 0;
UINT32 tempData;
while (bytesRead < maxBytes)
{
// Wait for data-ready
if(!(g_pVSIRReg->USR2 & CSP_BITFVAL(UART_USR2_RDR, UART_USR2_RDR_SET)))
break;
tempData = g_pVSIRReg->URXD;
// The UART reports framing and break errors as the effected
// characters appear on the stack. We drop these characters,
// which will probably result in a bad frame checksum.
if (tempData & SIR_RCV_ERROR)
{
return (UINT)-1;
}
else
{
data[bytesRead] = tempData & UART_URXD_RX_DATA_MSK;
}
DEBUGMSG(ZONE_RECV, (TEXT("Sir: Receive 0x%x\r\n"), data[bytesRead]));
bytesRead++;
}
return bytesRead;
}
//-----------------------------------------------------------------------------
//
// Function: NdisToSirPacket
//
// This function reads the NDIS packet into a contiguous buffer.
//
// Parameters:
// Packet
// [in] .
// irPacketBuf
// [in] .
// irPacketBufLen
// [in] .
// irPacketLen
// [in] .
//
// Returns:
// This function returns TRUE if the packet check is successful.
//
//-----------------------------------------------------------------------------
BOOLEAN NdisToSirPacket( PNDIS_PACKET Packet, UCHAR *irPacketBuf,
UINT irPacketBufLen, UINT *irPacketLen )
{
static UCHAR contigPacketBuf[MAX_IRDA_DATA_SIZE];
PNDIS_BUFFER ndisBuf;
UINT i, ndisPacketBytes = 0, I_fieldBytes, totalBytes = 0;
UINT ndisPacketLen, numExtraBOFs;
SLOW_IR_FCS_TYPE fcs, tmpfcs;
UCHAR fcsBuf[SLOW_IR_FCS_SIZE*2];
UINT fcsLen=0;
PNDIS_IRDA_PACKET_INFO packetInfo = GetPacketInfo(Packet);
UCHAR nextChar;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: +NdisToSirPacket\r\n")));
// Get the packet's entire length and its first NDIS buffer
NdisQueryPacket(Packet, NULL, NULL, &ndisBuf, &ndisPacketLen);
// Make sure that the packet is big enough to be legal.
// It consists of an A, C, and variable-length I field.
if (ndisPacketLen < IR_ADDR_SIZE + IR_CONTROL_SIZE)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: packet too short in NdisToSirPacket (%d bytes)\r\n"), ndisPacketLen));
return FALSE;
}
else
{
I_fieldBytes = ndisPacketLen - IR_ADDR_SIZE - IR_CONTROL_SIZE;
}
// Make sure that we won't overwrite our contiguous buffer.
// Make sure that the passed-in buffer can accomodate this packet's
// data no matter how much it grows through adding ESC-sequences, etc.
if ((ndisPacketLen > MAX_IRDA_DATA_SIZE) ||
(MAX_POSSIBLE_IR_PACKET_SIZE_FOR_DATA(I_fieldBytes) > irPacketBufLen))
{
// The packet is too large
// Tell the caller to retry with a packet size large
// enough to get past this stage next time.
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: Packet too large in NdisToSirPacket (%d=%xh bytes), MAX_IRDA_DATA_SIZE=%d, irPacketBufLen=%d.\r\n"),
ndisPacketLen, ndisPacketLen, MAX_IRDA_DATA_SIZE, irPacketBufLen));
*irPacketLen = ndisPacketLen;
return FALSE;
}
// First, read the NDIS packet into a contiguous buffer.
// We have to do this in two steps so that we can compute the
// FCS BEFORE applying escape-byte transparency.
while (ndisBuf)
{
UCHAR *bufData;
UINT bufLen;
NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
if (ndisPacketBytes + bufLen > ndisPacketLen)
{
// Packet was corrupt -- it misreported its size.
*irPacketLen = 0;
return FALSE;
}
NdisMoveMemory((PVOID)(contigPacketBuf+ndisPacketBytes), (PVOID)bufData, bufLen);
ndisPacketBytes += bufLen;
NdisGetNextBuffer(ndisBuf, &ndisBuf);
}
// Do a sanity check on the length of the packet.
if (ndisPacketBytes != ndisPacketLen)
{
// Packet was corrupt -- it misreported its size.
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: acket corrupt in NdisToSirPacket (buffer lengths don't add up to packet length).\r\n")));
*irPacketLen = 0;
return FALSE;
}
// Compute the FCS on the packet BEFORE applying transparency fixups.
// The FCS also must be sent using ESC-char transparency, so figure
// out how large the fcs will really be.
fcs = ComputeFCS(contigPacketBuf, ndisPacketBytes);
for (i = 0, tmpfcs = fcs, fcsLen = 0; i < SLOW_IR_FCS_SIZE; tmpfcs >>= 8, i++)
{
UCHAR fcsbyte = tmpfcs & 0x00ff;
switch (fcsbyte)
{
case SLOW_IR_BOF:
case SLOW_IR_EOF:
case SLOW_IR_ESC:
fcsBuf[fcsLen++] = SLOW_IR_ESC;
fcsBuf[fcsLen++] = fcsbyte ^ SLOW_IR_ESC_COMP;
break;
default:
fcsBuf[fcsLen++] = fcsbyte;
break;
}
}
// Now begin building the IR frame.
//
// This is the final format:
//
// BOF (1)
// extra BOFs ...
// NdisMediumIrda packet (what we get from NDIS):
// Address (1)
// Control (1)
// FCS (2)
// EOF (1)
// Prepend BOFs (extra BOFs + 1 actual BOF)
numExtraBOFs = packetInfo->ExtraBOFs;
if (numExtraBOFs > MAX_NUM_EXTRA_BOFS)
numExtraBOFs = MAX_NUM_EXTRA_BOFS;
for (i = totalBytes = 0; i < numExtraBOFs; i++)
{
*(SLOW_IR_BOF_TYPE *)(irPacketBuf+totalBytes) = SLOW_IR_EXTRA_BOF;
totalBytes += SLOW_IR_EXTRA_BOF_SIZE;
}
*(SLOW_IR_BOF_TYPE *)(irPacketBuf+totalBytes) = SLOW_IR_BOF;
totalBytes += SLOW_IR_BOF_SIZE;
// Copy the NDIS packet from our contiguous buffer,
// applying escape-char transparency.
for (i = 0; i < ndisPacketBytes; i++)
{
nextChar = contigPacketBuf[i];
switch (nextChar)
{
case SLOW_IR_BOF:
case SLOW_IR_EOF:
case SLOW_IR_ESC:
irPacketBuf[totalBytes++] = SLOW_IR_ESC;
irPacketBuf[totalBytes++] = nextChar ^ SLOW_IR_ESC_COMP;
break;
default:
irPacketBuf[totalBytes++] = nextChar;
break;
}
}
// Add FCS, EOF.
NdisMoveMemory((PVOID)(irPacketBuf+totalBytes), (PVOID)fcsBuf, fcsLen);
totalBytes += fcsLen;
*(SLOW_IR_EOF_TYPE *)(irPacketBuf+totalBytes) = (UCHAR)SLOW_IR_EOF;
totalBytes += SLOW_IR_EOF_SIZE;
*irPacketLen = totalBytes;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: ... NdisToSirPacket converted %d-byte ndis pkt to %d-byte irda pkt:\r\n"),
ndisPacketLen, *irPacketLen));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: SirDoSend
//
// This function setup send packet.
//
// Parameters:
// thisDev
// [in] .
// packetToSend
// [in] .
//
// Returns:
// This function returns packet send status.
//
//-----------------------------------------------------------------------------
BOOLEAN SirDoSend(pFirDevice_t thisDev, PNDIS_PACKET packetToSend)
{
BOOLEAN stat;
DEBUGMSG(ZONE_SEND, (TEXT("Sir: +SirDoSend\r\n")));
DEBUGMSG(ZONE_SEND, (TEXT("Sir: SirDoSend()")));
stat = NdisToSirPacket(packetToSend,
(UCHAR *)thisDev->writeBuf, MAX_IRDA_DATA_SIZE, &thisDev->writeBufLen);
if (stat)
{
// Disable interrupts while setting up the send FSM.
SirDisableInterrupt(thisDev);
// Finish initializing the send FSM.
thisDev->portInfo.sendBufPos = 0;
thisDev->writePending = TRUE;
thisDev->nowReceiving = FALSE;
// Enable Tx interupt
CSP_BITFINS(g_pVSIRReg->UCR1, UART_UCR1_TXMPTYEN, UART_UCR1_TXMPTYEN_ENABLE);
}
else
{
DEBUGMSG(ZONE_SEND, (TEXT("Sir: Couldn't convert packet in SirDoSend()\r\n")));
}
DEBUGMSG(ZONE_SEND, (TEXT("Sir: -SirDoSend\r\n")));
return stat;
}
//-----------------------------------------------------------------------------
//
// Function: SirSetSpeed
//
// This function sets the Sir baudrate.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -