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

📄 recv.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
                            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 + -