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

📄 pipe.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// PIPE.C
//
// Object member functions for the Pipe device object.
//
// Author: Michael A. Denio
// Copyright 2000 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>

// Pipe Object Structure
typedef struct _pipe {
             uint         Type;         // Set to HTYPE_PIPE
             HANDLE       hFd;          // Handle to file descriptor
             struct _pipe *pConnect;    // Pointer to other end of pipe
             HANDLE       hSBRx;        // Rx Buffer
             INT32        TxSpace;      // Tx Space Required for "writeable"
        } PIPE;

//--------------------------------------------------------------------
// PipeNew()
//
// Creates a pipe, consisting of two handles
//--------------------------------------------------------------------
int PipeNew( HANDLE hFd1, HANDLE hFd2, HANDLE *phPipe1, HANDLE *phPipe2 )
{
    PIPE   *pp1 = 0, *pp2 = 0;
    int    error = 0;

    // Attempt to allocate space for both pipe ends
    pp1 = mmAlloc(sizeof(PIPE));
    pp2 = mmAlloc(sizeof(PIPE));

    if( !pp1 || !pp2 )
    {
        DbgPrintf(DBG_WARN,"PipeNew: OOM");
        ExecLowResource();
        error = ENOMEM;
        goto pipenew_freehandle;
    }

    // Initialize both pipe ends
    pp1->Type     = HTYPE_PIPE;
    pp2->Type     = HTYPE_PIPE;
    pp1->hFd      = hFd1;               // Set handle to owning file desc.
    pp2->hFd      = hFd2;               // Set handle to owning file desc.
    pp1->pConnect = pp2;                // 1 is connected to 2
    pp2->pConnect = pp1;                // 2 is connected to 1
    pp1->TxSpace  = PIPE_BUFMINTX;      // Space req to write to other end
    pp2->TxSpace  = PIPE_BUFMINTX;      // Space req to write to other end

    pp1->hSBRx = SBNew( PIPE_BUFSIZE, PIPE_BUFMINRX, SB_MODE_LINEAR );
    pp2->hSBRx = SBNew( PIPE_BUFSIZE, PIPE_BUFMINRX, SB_MODE_LINEAR );

    if( !pp1->hSBRx || !pp2->hSBRx )
    {
        error = ENOMEM;
        goto pipenew_free;
    }

    *phPipe1 = (HANDLE)pp1;
    *phPipe2 = (HANDLE)pp2;

    return( error );

pipenew_free:
    // Free whatever we allocated
    if( pp1->hSBRx )
        SBFree( pp1->hSBRx );
    if( pp2->hSBRx )
        SBFree( pp2->hSBRx );

pipenew_freehandle:
    if( pp1 )
    {
        pp1->Type = 0;
        mmFree( pp1 );
    }
    if( pp2 )
    {
        pp2->Type = 0;
        mmFree( pp2 );
    }

    return( error );
}

//--------------------------------------------------------------------
// PipeClose()
//
// Close a pipe end
//--------------------------------------------------------------------
int PipeClose( HANDLE h )
{
    PIPE *pp = (PIPE *)h;

#ifdef _STRONG_CHECKING
    if( pp->Type != HTYPE_PIPE )
    {
        DbgPrintf(DBG_ERROR,"PipeClose: HTYPE %04x",pp->Type);
        return( EINVAL );
    }
#endif

    // If still connected, disconnect
    if( pp->pConnect )
    {
        pp->pConnect->pConnect = 0;
        // We can event them now since their link to our side is broken
        FDSignalEvent( pp->pConnect->hFd, FD_EVENT_READ );
        pp->pConnect = 0;
    }

    // Free the Rx Buffer
    if( pp->hSBRx )
        SBFree( pp->hSBRx );

    // Free the pipe memory
    pp->Type = 0;
    mmFree( pp );

    return(0);
}

//--------------------------------------------------------------------
// PipeCheck()
//
// Check for pipe read/write/except status
//--------------------------------------------------------------------
int PipeCheck( HANDLE h, int IoType )
{
    PIPE *pp = (PIPE *)h;

#ifdef _STRONG_CHECKING
    if( pp->Type != HTYPE_PIPE )
    {
        DbgPrintf(DBG_ERROR,"PipeCheck: HTYPE %04x",pp->Type);
        return( 0 );
    }
#endif

    switch( IoType )
    {
    case PIPE_READ:
        //
        // Return TRUE if readable
        //
        if( SBGetTotal(pp->hSBRx) >= SBGetMin(pp->hSBRx) || !pp->pConnect )
            return(1);
        break;

    case PIPE_WRITE:
        //
        // Return TRUE if writeable
        //
        if( !pp->pConnect || SBGetSpace(pp->pConnect->hSBRx) >= pp->TxSpace )
            return(1);
        break;
    }
    return(0);
}

//--------------------------------------------------------------------
// PipeRecv
//
// Receive data from a pipe.
//--------------------------------------------------------------------
int PipeRecv( HANDLE h, char *pBuf, INT32 size, int flags, INT32 *pRetSize )
{
    PIPE     *pp = (PIPE *)h;
    INT32    Total    = 0;
    INT32    SizeCopy = 0;
    int      retry    = 1;
    int      error    = 0;

#ifdef _STRONG_CHECKING
    if( pp->Type != HTYPE_PIPE )
    {
        DbgPrintf(DBG_ERROR,"PipeRecv: HTYPE %04x",pp->Type);
        return( EINVAL );
    }
#endif

    // Check for a null read
    if( !size )
        goto rx_complete;

rx_restart:
    // Get the total bytes available
    Total = SBGetTotal(pp->hSBRx);

    // Check for blocking condition
    if( !Total )
    {
        //
        // Check all non-blocking conditions first
        //

        // Assume we can't block
        retry = 0;

        // Don't block if the pipe is no longer connected
        if( !pp->pConnect )
        {
            error = ENOTCONN;
            goto rx_dontblock;
        }

        // Don't block if there was an overriding request not to block
        if( flags & MSG_DONTWAIT )
            goto rx_dontblock;

        // Don't block if we have Rx'd the minimum
        if( SizeCopy >= SBGetMin(pp->hSBRx) )
            goto rx_dontblock;

        // Finally, the blocking code

        // If we get a file event, then try the loop again
        if( FDWaitEvent( pp->hFd, FD_EVENT_READ, DEF_PIPE_TIMEIO*1000 ) )
        {
            retry = 1;
            goto rx_restart;
        }
    }

rx_dontblock:
    // Check for FATAL blocking condition
    if( !Total && !SizeCopy )
    {
        if( !error )
            error = EWOULDBLOCK;
        return( error );
    }

    // Get how much data to copy

    // Adjust to buffer size
    if( size < (Total+SizeCopy) )
        Total = size-SizeCopy;

    if( Total )
    {
        if( flags & MSG_PEEK )
            Total = SBRead( pp->hSBRx, Total, 0,
                            (UINT8 *)(pBuf+SizeCopy), 0, 0, 1 );
        else
            Total = SBRead( pp->hSBRx, Total, 0,
                            (UINT8 *)(pBuf+SizeCopy), 0, 0, 0 );

        // Record that we received this data
        SizeCopy += Total;

        // Notify the other side that we've read from our buffer
        if( pp->pConnect )
            FDSignalEvent( pp->pConnect->hFd, FD_EVENT_WRITE );
    }

    // Try and get all the data if possible
    if( retry && size > SizeCopy )
        goto rx_restart;

rx_complete:
    *pRetSize = SizeCopy;
    if( SizeCopy )
        return(0);
    return(error);
}

//--------------------------------------------------------------------
// PipeSend()
//
// Send data to a pipe.
//--------------------------------------------------------------------
int PipeSend( HANDLE h, char *pBuf, INT32 size, int flags, INT32 *pRetSize )
{
    PIPE     *pp = (PIPE *)h;
    int      error = 0;
    INT32    SizeCopy = 0;
    INT32    Space;
    INT32    ToCopy;

#ifdef _STRONG_CHECKING
    if( pp->Type != HTYPE_PIPE )
    {
        DbgPrintf(DBG_ERROR,"PipeRecv: HTYPE %04x",pp->Type);
        return( EINVAL );
    }
#endif

    while( SizeCopy < size )
    {
        // Must be connected
        if( !pp->pConnect )
        {
            error = ENOTCONN;
            break;
        }

        // Append as much data as possible to connected end's buffer
        ToCopy = size - SizeCopy;
        Space  = SBGetSpace( pp->pConnect->hSBRx );
        if( Space < ToCopy )
            ToCopy = Space;

        if( ToCopy )
        {
            // Copy out the data and mark what we did copy
            SizeCopy += SBWrite(pp->pConnect->hSBRx, ToCopy, pBuf+SizeCopy, 0);

            // Notify connected end we wrote to its buffer
            FDSignalEvent( pp->pConnect->hFd, FD_EVENT_READ );
        }

        // Break out now on an error condition
        if( error )
            break;

        // Check blocking condition
        if( SizeCopy < size && !ToCopy )
        {
            // Don't block if DONTWAIT specified.
            // If we timeout, we have an error and break the loop
            if( flags & MSG_DONTWAIT ||
                !FDWaitEvent( pp->hFd, FD_EVENT_WRITE, DEF_PIPE_TIMEIO*1000 ) )
            {
                error = EWOULDBLOCK;
                break;
            }
        }
    }

    *pRetSize = SizeCopy;
    return( error );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -