📄 pipe.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 + -