⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 send.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 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 + -