📄 send.c
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
send.c
Abstract:
This file implements the IrDA Serial IR NDIS MAC driver send
functions. This is provided as a sample to platform writers and is
expected to be able to be used without modification on most (if not
all) hardware platforms.
Functions:
IrsirSend
IrsirTxThread
Notes:
--*/
#include "irsirp.h"
/*++
Function: IrsirSend
Description: Send a packet to the serial port.
Arguments:
hContext - Pointer to the current IR_DEVICE object.
pNdisPacket - NDIS packet to send.
Flags - Any flags set by the protocol. (This is protocol specific).
Returns:
NDIS_STATUS_PENDING - This is generally what we should return. We will
call NdisMSendComplete when the data is actually
sent.
NDIS_STATUS_FAILURE - The packet was invalid.
Comments:
We will need to put this write packet on a queue if there is another
packet pending completion.
--*/
NDIS_STATUS
IrsirSend(
IN NDIS_HANDLE hContext,
IN PNDIS_PACKET pNdisPacket,
IN UINT Flags
)
{
NDIS_STATUS status = NDIS_STATUS_PENDING;
PIR_DEVICE pIrDevice = (PIR_DEVICE)hContext;
DEBUGMSG(ZONE_SEND,
(TEXT("+IrsirSend(0x%.8X, 0x%.8X, 0x%.8X)\r\n"),
hContext, pNdisPacket, Flags)
);
DEBUG_PACKET(ZONE_SNIFFIR, pNdisPacket);
NdisAcquireSpinLock(&pIrDevice->slDevice);
//
// Are we currently sending data? If so, we add our new packet to
// the send queue, else we start sending the new packet.
//
if (pIrDevice->pSendActive == NULL)
{
// We are not currently sending data.
ASSERT(pIrDevice->pSendHead == NULL);
ASSERT(pIrDevice->pSendTail == NULL);
// Current packet is set to active.
pIrDevice->pSendActive = pNdisPacket;
*(PNDIS_PACKET *)pNdisPacket->MiniportReserved = NULL;
SetEvent(pIrDevice->hSendEvent);
}
else // We are currently sending, just queue the data.
{
// Put packet on the end of the pending queue.
if (pIrDevice->pSendHead == NULL)
{
// Queue is empty.
pIrDevice->pSendHead = pNdisPacket;
}
else
{
// Queue has some packets on it.
*(PNDIS_PACKET *)pIrDevice->pSendTail->MiniportReserved
= pNdisPacket;
}
pIrDevice->pSendTail = pNdisPacket;
*(PNDIS_PACKET *)pNdisPacket->MiniportReserved = NULL;
// There should be a currently running event thread which will
// take care of our send before it exits.
}
NdisReleaseSpinLock(&pIrDevice->slDevice);
DEBUGMSG(ZONE_SEND, (TEXT("-IrsirSend [0x%.8X]\r\n"), status));
return (status);
}
/*++
Function: IrsirTxThread
Description: Thread for sending packets to serial driver.
Arguments:
pv_pIrDevice - Pointer to an IR device object to transmit data on.
Returns:
NDIS_STATUS_SUCCESS.
Comments:
--*/
DWORD
IrsirTxThread(
LPVOID pv_pIrDevice
)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PIR_DEVICE pIrDevice = (PIR_DEVICE)pv_pIrDevice;
DWORD cbWritten;
DWORD cbTotalWritten;
BOOL fSwitchSuccessful;
NDIS_HANDLE hSwitchToMiniport;
DWORD cbTatBofs;
PNDIS_IRDA_PACKET_INFO pIrdaInfo;
ASSERT(pIrDevice != NULL);
DEBUGMSG(ZONE_INIT | ZONE_SEND,
(TEXT("+IrsirTxThread(0x%.8X)\r\n"), pIrDevice));
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
while (1)
{
if (WaitForSingleObject(pIrDevice->hSendEvent, INFINITE) == WAIT_FAILED)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("IrsirTxThread: WaitForSingleObject failure = %x\r\n"),
GetLastError())
);
ASSERT(FALSE);
break;
}
else if (pIrDevice->pSendActive == NULL)
{
// We are being signalled to exit the thread.
break;
}
if (pIrDevice->pCurrBaud->dwBPS == 576000 ||
pIrDevice->pCurrBaud->dwBPS == 1152000 ||
pIrDevice->pCurrBaud->dwBPS == 4000000 )
{
SendFIR(pIrDevice);
}else{
//
// Get irda media specific info.
//
pIrdaInfo = GetIrdaPacketInfo(pIrDevice->pSendActive);
ASSERT(pIrdaInfo != NULL);
ASSERT(pIrdaInfo->MinTurnAroundTime <= MAX_TAT_usec);
NdisAcquireSpinLock(&pIrDevice->slDevice);
// TAT BOFS.
if ((pIrDevice->fMinTATRequired == TRUE) &&
(pIrdaInfo->MinTurnAroundTime > 0))
{
// BitsPerSecond uSecDelay
// TAT = ------------- * --------------
// BitsPerChar uSecPerSecond
cbTatBofs = (pIrDevice->pCurrBaud->dwBPS * pIrdaInfo->MinTurnAroundTime)/8000000;
pIrDevice->fMinTATRequired = FALSE;
}
else
{
cbTatBofs = 0;
}
NdisReleaseSpinLock(&pIrDevice->slDevice);
pIrDevice->cbSendBuf = MAX_IRDA_DATA_SIZE;
// Need to convert NdisPacket to an IR packet.
if (NdisToIrPacket(
pIrDevice->pSendActive,
cbTatBofs,
pIrDevice->pSendBuf,
&pIrDevice->cbSendBuf) == TRUE)
{
// The buffer is now converted...we can send the buffer.
for (cbWritten = 0, cbTotalWritten = 0;
cbTotalWritten < pIrDevice->cbSendBuf;
cbTotalWritten += cbWritten
)
{
if (WriteFile(pIrDevice->hSerial,
pIrDevice->pSendBuf + cbTotalWritten,
pIrDevice->cbSendBuf - cbTotalWritten,
&cbWritten,
NULL) == FALSE)
{
DEBUGMSG(ZONE_ERROR, (TEXT("WriteFile failed to write packet.\r\n")));
status = NDIS_STATUS_FAILURE;
break;
}
}
// Log packet after it has gone out...less time critical now.
IRSIR_LOG_NDIS_PACKET(LOG_TXFRAME, pIrDevice->pSendActive);
}
else
{
IRSIR_LOG_DATA(LOG_TXFRAME,
LOG_DTYPE_ASCII,
0,
"Failed to convert NDIS packet to IR packet");
DEBUGMSG(ZONE_ERROR, (TEXT("NdisToIrPacket failed to convert packet.\r\n")));
status = NDIS_STATUS_FAILURE;
}
}
if (status == NDIS_STATUS_SUCCESS)
{
pIrDevice->cPacketsTx++;
DEBUGMSG(ZONE_SEND,
(TEXT("Tx: sent %d byte IR packet.\r\n"),
cbTotalWritten)
);
}
else
{
pIrDevice->cPacketsTxDropped++;
DEBUGMSG(ZONE_WARN,
(TEXT("Tx:Packets dropped = %d\r\n"),
pIrDevice->cPacketsTxDropped)
);
}
//
// Need to give the NDIS packet back to the protocol.
// Since this is an intermediate miniport, we must call
// NdisIMSwitchToMiniport to grab the NDIS miniport lock.
//
fSwitchSuccessful = NdisIMSwitchToMiniport(
pIrDevice->hNdisAdapter,
&hSwitchToMiniport
);
if (fSwitchSuccessful == FALSE)
{
// WinCE's NdisIMSwitchToMiniport should not fail.
ASSERT(FALSE);
}
// Indicate ownership of packet along with status of send.
NdisMSendComplete(
pIrDevice->hNdisAdapter,
pIrDevice->pSendActive,
status
);
NdisIMRevertBack(
pIrDevice->hNdisAdapter,
hSwitchToMiniport
);
//
// See if there is more data waiting to be sent.
//
NdisAcquireSpinLock(&pIrDevice->slDevice);
// Is the queue empty?
if (pIrDevice->pSendHead == NULL)
{
ASSERT(pIrDevice->pSendTail == NULL);
// We are done.
pIrDevice->pSendActive = NULL;
}
else
{
// More data to send. Remove the first item in the queue.
// Note: The MiniportReserved field is being used as the 'next'
// pointer for a singly linked list.
pIrDevice->pSendActive = pIrDevice->pSendHead;
// Update head.
pIrDevice->pSendHead = *(PNDIS_PACKET *)pIrDevice->pSendActive->MiniportReserved;
// Null out pointer.
*(PNDIS_PACKET *)pIrDevice->pSendActive->MiniportReserved = NULL;
// Did we take the last item off the queue?
if (pIrDevice->pSendHead == NULL)
{
pIrDevice->pSendTail = NULL;
}
// Need to set our own event so we can continue.
SetEvent(pIrDevice->hSendEvent);
}
NdisReleaseSpinLock(&pIrDevice->slDevice);
}
DEBUGMSG(ZONE_INIT | ZONE_SEND, (TEXT("-IrsirTxThread\r\n")));
return (NDIS_STATUS_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -