📄 cpftserial.cpp
字号:
// flush the pending wait and continue
SetCommMask(mPortHandle, EV_RXCHAR);
ResetEvent(handleArray[2]);
continue;
}
// figure out how long to wait. if we are waiting for a ring,
// then only fall asleep until the latest time the next ring
// could come in.
if(mState == _cs_calldetected)
{
if(mLastRingTime + 8*1000 < (now = pgp_getticks()))
{
SetState(_cs_listening);
continue;
}
timeout = mLastRingTime + 8*1000 - now;
}
else
timeout = INFINITE;
WAIT_AGAIN: // wait for the first event that gets triggered.
result = WaitForMultipleObjects(3, handleArray, FALSE, timeout);
if(result == WAIT_TIMEOUT)
{
// resume listening and flush the pending wait
SetState(_cs_listening);
SetCommMask(mPortHandle, EV_RXCHAR);
}
else if(result == WAIT_OBJECT_0)
break; // we have to abort
else if(result == (WAIT_OBJECT_0+1))
{
//ResetEvent(mAnswerEvent);
break; // the phone has been answered
}
else if(result != (WAIT_OBJECT_0+2))
{
int error = GetLastError();
if(error == ERROR_INVALID_HANDLE && handle_error_count++ < 50)
goto WAIT_AGAIN;
MODEM_ERROR("unknown error waiting on event", error);
response = _pge_InternalAbort;
break;
}
ResetEvent(handleArray[2]); // must have gotten data
}
}
// flush any pending calls to WaitCommEvent
SetCommMask(mPortHandle, EV_RXCHAR);
return response;
}
PGErr
CPFTSerial::Listen(Boolean answer)
{
short result = 0, reply = _cr_NoReply;
mTMutex->Wait();
if(answer)
mAnswer = TRUE;
else
SetState(_cs_listening);
while (!mAbort)
{
if((mAnswer || (WaitForRing() == _cr_Ring)) && !mAbort)
{
if(mAnswer)
{
SetState(_cs_connecting);
Write("ATA\r"); /* answer the call, universal AT command */
reply = GetModemResult(1000*60);
if(reply == _cr_Connect)
{
SetState(_cs_connected);
break;
}
else
Write("\r"); /* abort the modem connecting */
}
else
{
if(mState != _cs_calldetected)
SetState(_cs_calldetected);
mLastRingTime = pgp_getticks();
mPFWindow->GetStatusPane()->AddStatus(0, "...Ring...");
if(gPGFOpts.popt.playRing)
PlaySound("RING.WAV",NULL,SND_FILENAME+SND_SYNC);
}
}
Sleep(0);
}
if(!mAnswer && mAbort)
result = _pge_InternalAbort;
mAnswer = FALSE;
mTMutex->Signal();
return result;
}
short
CPFTSerial::Reset()
{
short result=0;
short reply, inx;
DCB dcb;
mTMutex->Wait();
mAbort = FALSE;
ResetEvent(mAbortEvent);
// get the current settings for the port
if(! GetCommState(mPortHandle, &dcb))
{
MODEM_ERROR("error getting modem settings", GetLastError());
mTMutex->Signal();
return -1;
}
// set the baud rate and other hardware parameters
dcb.BaudRate = mSerOpts.baud;
dcb.fBinary = 1;
dcb.fParity = 0;
dcb.fOutxCtsFlow = 1;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fDsrSensitivity = 0;
dcb.fOutX = 0;
dcb.fInX = 0;
dcb.fErrorChar = 0;
dcb.fNull = 0;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fAbortOnError = 0;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if(! SetCommState(mPortHandle, &dcb))
{
MODEM_ERROR("error setting modem settings", GetLastError());
mTMutex->Signal();
return -2;
}
SetState(_cs_initializing);
Sleep(1000); // sleep for a second to let the modem catch-up
// setup a mask so we know when a character comes in
if(! SetCommMask(mPortHandle, EV_RXCHAR))
{
MODEM_ERROR("error setting up comm mask", GetLastError());
return -3;
}
mTMutex->Signal();
reply = _cr_NoReply;
for(inx = 0; inx < 3 && reply != _cr_OK && !mAbort; inx++)
{
if(Write("AT%s\r", gPGFOpts.sopt.modemInit) < 0)
{
MODEM_ERROR("error writing to the modem", GetLastError());
return -4;
}
reply = GetModemResult(1000*5);
}
if(reply != _cr_OK)
result = _pge_ModemNotAvail;
if(mAbort)
result = _pge_InternalAbort;
return result;
}
long
CPFTSerial::Read(void *data, long len, short *channel)
{
static OVERLAPPED overlapped;
ulong read = 0;
long extra = 0;
uchar *buffer = (uchar*)data, l = 0, amount;
DWORD error;
// setup an overlapped structure for reading
overlapped.Offset = overlapped.OffsetHigh = 0;
overlapped.hEvent = mRXevent;
ResetEvent(mRXevent);
// check to see if the caller just wants to know whether we have
// any data waiting.
if(buffer && len)
{
// in an earlier check for waiting data, we may have read an
// extra character. if so, then include it in the data we
// send back.
if(mInFront != mInBack)
{
// check to see if we have enough data in our internal buffer
if(len > (uchar)(mInFront - mInBack))
{
if(mInFront > mInBack)
{
pgp_memcpy(buffer, mInBuffer + mInBack, l = mInFront - mInBack);
buffer += l;
len -= l;
}
else
{
pgp_memcpy(buffer, mInBuffer + mInBack, l = (uchar)(-mInBack));
buffer += l;
len -= l;
pgp_memcpy(buffer, mInBuffer, mInFront);
buffer += mInFront;
len -= mInFront;
l += mInFront;
}
mInBack = mInFront = 0;
}
else
{
if((uchar)(-mInBack) > len)
{
pgp_memcpy(buffer, mInBuffer + mInBack, len);
mInBack += (uchar)len;
return len;
}
else
{
pgp_memcpy(buffer, mInBuffer + mInBack, l = (uchar)(-mInBack));
mInBack += (uchar)len;
buffer += l;
len -= l;
pgp_memcpy(buffer, mInBuffer, len);
return len + l;
}
}
}
// try and read the data from the modem.
if(! ReadFile(mPortHandle, buffer, len, &read, &overlapped) &&
(error = GetLastError()) != ERROR_IO_PENDING)
{
MODEM_ERROR("error reading from modem", error);
return -2;
}
// wait for the read to complete
GetOverlappedResult(mPortHandle, &overlapped, &read, TRUE);
return l + read;
}
else if(buffer)
// if they don't want any data we succeed automatically.
return 0;
else
{
// if we have any data in our internal buffer from an earlier read
// then return the amount of data in our internal buffer
// immediately. otherwise, try to read some data into our
// internal buffer and return the number of bytes that we
// succeeded in reading.
if(mInFront != mInBack)
return (uchar)(mInFront - mInBack);
mInFront = mInBack = 0;
amount = 255;
if(! ReadFile(mPortHandle, mInBuffer, amount, &read, &overlapped) &&
(error = GetLastError()) != ERROR_IO_PENDING)
{
MODEM_ERROR("error reading from modem", error);
return -1;
}
// wait for the read to complete.
if(! GetOverlappedResult(mPortHandle, &overlapped, &read, TRUE))
{
MODEM_ERROR("error getting read result", GetLastError());
return -2;
}
mInFront = (uchar)read;
return read;
}
}
short
CPFTSerial::WriteBlock(void *buffer, long *count, short channel)
{
static OVERLAPPED overlapped;
ulong written;
DWORD error;
mTMutex->Wait();
// setup the OVERLAPPED structure for writing
overlapped.Offset = overlapped.OffsetHigh = 0;
overlapped.hEvent = mTXevent;
// we use an overlapped structure so that a read can occur at the same
// time as a write.
if(! WriteFile(mPortHandle, buffer, *count, &written, &overlapped) &&
(error = GetLastError()) != ERROR_IO_PENDING)
{
MODEM_ERROR("error writing to modem", error);
mTMutex->Signal();
return -1;
}
// wait for the write to complete
if(! GetOverlappedResult(mPortHandle, &overlapped, &written, TRUE))
{
MODEM_ERROR("error getting write result", GetLastError());
mTMutex->Signal();
return -2;
}
*count = written;
mTMutex->Signal();
return 0;
}
/*void
CPFTSerial::WaitAsync(AsyncTransport *asyncTrans)
{
return;
WaitForSingleObject(asyncTrans->u.overlapped.hEvent, INFINITE);
return;
}*/
PGErr
CPFTSerial::WriteAsync(long count, short channel, AsyncTransport *async)
{
return WriteBlock(async->buffer, &count, _pfc_Control);
BOOL result;
DWORD error;
async->u.overlapped.Internal = 0;
async->u.overlapped.InternalHigh = 0;
async->u.overlapped.Offset = 0;
async->u.overlapped.OffsetHigh = 0;
result = WriteFile(mPortHandle, async->buffer, count, &async->written,
&async->u.overlapped);
if(!result && (error = GetLastError()) != ERROR_IO_PENDING)
{
MODEM_ERROR("error writing to modem", error);
return _pge_ModemNotAvail;
}
return _pge_NoErr;
}
short
CPFTSerial::SleepForData(HANDLE *abortEvent)
{
OVERLAPPED overlapped;
DWORD eventMask, result, error = 0;
short retval = 0;
short handle_error_count = 0;
HANDLE handleArray[2] = {*abortEvent, mDataEvent};
memset (&overlapped,0, sizeof(OVERLAPPED));
overlapped.hEvent = handleArray[1];
if(mInFront == mInBack && Read(NIL, 0, NIL) == 0)
{
if(! WaitCommEvent(mPortHandle, &eventMask, &overlapped) &&
(error = GetLastError()) != ERROR_IO_PENDING)
{
MODEM_ERROR("error setting up comm event", error);
retval = -1;
//goto EXIT_FUNC;
}
// make sure that some data didn't come in before WaitCommEvent() was
// called
if(Read(NIL, 0, NIL) > 0)
{
// flush the pending wait and return
SetCommMask(mPortHandle, EV_RXCHAR);
retval = 0;
goto CLOSE_EVENT;
}
// wait for the first event that gets triggered.
WAIT_AGAIN: // Windows 95 returns ERROR_INVALID_HANDLE sometimes when there is nothing
// wrong with the handle. When that happens we ignor the error a few times and see
// if things don't just work fine anyway.
result = WaitForMultipleObjects(2, handleArray, FALSE, INFINITE);
if(result == WAIT_OBJECT_0)
{
// flush the pending wait and return
SetCommMask(mPortHandle, EV_RXCHAR);
error = 1;
}
else if(result != (WAIT_OBJECT_0+1))
{
// flush the pending wait, report an error, and return
DWORD error = GetLastError();
if(error == ERROR_INVALID_HANDLE && handle_error_count++ < 50)
goto WAIT_AGAIN;
SetCommMask(mPortHandle, EV_RXCHAR);
MODEM_ERROR("unknown result waiting on event", error);
retval = -2;
}
}
CLOSE_EVENT:;
return retval; // there's data so we're done
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -