📄 win32_modem.cpp
字号:
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include <string>
#include <memory>
using namespace std;
#include "Win32_Modem.h"
#include "win32serialport.h"
//---------------------------------------------------------------------------
/*
OK, holding off on the connection stuff for know, until I can get
some USENET feedback or inspiration. The dialing works fine, but reception
never yields a notification, so we can't accept the call.
To do instead:
clean up the GUI
confirm correctness of PPP and LCP
implement CHAP
*/
static HWND g_hWndMainWindow; // Apps main window.
static HWND g_hDlgParentWindow; // This will be the parent of all dialogs.
static HLINEAPP g_hLineApp;
static DWORD g_dwNumDevs;
static HWND g_hDialog;
static bool g_bShuttingDown;
static bool g_bStoppingCall;
static bool g_bInitializing;
static bool g_bTapiInUse;
// static HCALL g_hCall;
LPHCALL g_hCall;
static HLINE g_hLine;
static DWORD g_dwDeviceID;
static DWORD g_dwAPIVersion;
static DWORD g_dwCallState;
static char g_szDisplayableAddress[1024];
static char g_szDialableAddress[1024];
static bool g_bConnected;
static LPVOID g_lpDeviceConfig;
static DWORD g_dwSizeDeviceConfig;
static bool g_bReplyRecieved;
static DWORD g_dwRequestedID;
static long g_lAsyncReply;
static bool g_bCallStateReceived;
DWORD gh_dwAPIVersion;
void Win32_Modem::SetTimeouts()
{
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 100;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 100;
timeouts.WriteTotalTimeoutConstant = 100;
if(!SetCommTimeouts(Comm, &timeouts))
{
// OutputDebugString("Failed to set comm timeouts");
}
}
bool Win32_Modem::WaitForConnection(char ** connectName)
{
long lReturn=-1;
static bool lineOpened=false;
static bool connected=false;
long ret=0;
long count=0;
LPLINECALLPARAMS lpCallParams = NULL;
*connectName = new char[30];
strcpy(*connectName, INVALID_COMM_NAME);
if(!isInited)
{
if (InitializeTAPI(NULL)==TRUE)
{
// OutputDebugString("TAPI Initialized");
isInited=true;
}
else
{
// OutputDebugString("Unable to Initialize TAPI!!!");
}
}
if ((lineOpened==false)&&(isInited==true))
{
lpCallParams = CreateCallParams (lpCallParams, g_szDisplayableAddress);
lReturn = lineOpen(g_hLineApp, g_dwDeviceID, &g_hLine,
g_dwAPIVersion, 0, NULL,
LINECALLPRIVILEGE_OWNER | LINECALLPRIVILEGE_MONITOR,
LINEMEDIAMODE_DATAMODEM , lpCallParams);
if (lReturn < 0)
{
// OutputDebugString("Failed to properly open line for listen");
}
else
{
// OutputDebugString("Opened line for listening");
lineOpened=true;
}
}
else if((connected==false) &&(isInited==true))
{
MSG msg;
if (!WaitForCallState(LINECALLSTATE_OFFERING))
{
ret = lineAnswer(*g_hCall, NULL,0);
if (ret < 0)
{
// OutputDebugString("Line answer failed");
}
else if (ret == 0)
{
// OutputDebugString("Xero!!??!?!? from line answer");
}
else
{
LPVARSTRING lpvarString;
lpvarString = (VARSTRING *)malloc(100);
lpvarString->dwTotalSize = 100;
while ((WaitForCallState(LINECALLSTATE_CONNECTED)) && (count < 10))
{
count++;
}
if (count < 10)
{
//OutputDebugString("Answered call, connected");
long lReturn = lineGetID(0,0, *g_hCall, LINECALLSELECT_CALL, lpvarString, "comm/datamodem");
if(lReturn < 0)
{
// OutputDebugString("Failed to set up comm ID");
}
else
{
memset(*connectName, 0, 30);
strncpy(*connectName, (char *)lpvarString+lpvarString->dwStringOffset, lpvarString->dwStringSize);
Comm = *((LPHANDLE)((LPBYTE)lpvarString + lpvarString -> dwStringOffset));
// Open(comm); // call Win32_sp_ovr open
connected=true;
//OutputDebugString("Got communications ID");
SetTimeouts();
}
}
else
{
//OutputDebugString("Failed in transition to CONNECTED state");
}
free(lpvarString);
}
}
}
return connected;
}
/*void Win32_Modem::ReadEvent(unsigned char * theBuffer, unsigned long * theBytesRead, OVERLAPPED *theOvrRead)
{
DWORD comm_event;
unsigned long bytes_read;
int linefeed = 0;
int err;
do
{
if (err=(ReadFile(Comm, &theBuffer[*theBytesRead], 1, &bytes_read, theOvrRead))!=0)
{
// succesful read... //CTL optimze for 0 bytes read and good return val
(*theBytesRead)++;
SleepEx(10,FALSE); // sleep for 10 ms should be enough even at 1200 baud
#ifdef DEBUG
cout << dec << " Read..." << (*theBytesRead) << " ";
cout << hex << (unsigned short)theBuffer[*theBytesRead-1];
if(linefeed == 3)
{
cout << "\n";
linefeed=0;
}
else
{
linefeed++;
}
}
else
{
long err;
err = GetLastError();
if (err == ERROR_HANDLE_EOF)
{
cout << "Reached end of buffer" << endl;
}
else
{
cout << dec << "Error number:- " << err << " where 997 is ERROR_IO_PENDING" << endl;
}
#endif
// All of the bytes have been read
}
}
while ((bytes_read!=0)&&(err!=0)); //(comm_event == EV_RXCHAR);
}
*/
void Win32_Modem::Open(char *theCommName, short theBaudRate, short theDataBits, char theParity, short theStopBits)
{
Open(theCommName);
}
void Win32_Modem::Open(char *theCommName)
{
if (Comm != NULL)
return;
/* if (Comm != INVALID_HANDLE_VALUE)
{
throw SP_Exception();
}
Comm = CreateFile(theCommName, GENERIC_READ | GENERIC_WRITE, 0,0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (Comm == INVALID_HANDLE_VALUE)
{
DWORD err=GetLastError();
printf("%d", err);
throw SP_Exception();
}*/
}
void Win32_Modem::WriteBuffer(unsigned char *theBuffer, long theBufferLength)
{
static BOOL write_flag = FALSE;
OVERLAPPED ovr_write = {0};
DWORD wfso_result;
DWORD bytes_written;
long pending_timeout;
/* while(write_flag==TRUE)
{
wfso_result = WaitForSingleObject(write_flag, COMM_WRITE_TIMEOUT);
}*/
ovr_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ovr_write.hEvent == NULL)
{
throw OverlappedEventException();
}
HANDLE thread_handle = GetCurrentThread();
int thread_pty = GetThreadPriority(thread_handle);
SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
// First attempt to write to the port
//OutputDebugString("Wrote:");
//OutputDebugString(theBuffer);
if (!WriteFile(Comm, theBuffer, theBufferLength, &bytes_written, &ovr_write))
{
if (GetLastError() != ERROR_IO_PENDING)
{
// Error in communications
throw WritingPortException();
}
else
{
// reading pending
write_flag = TRUE;
}
}
else
{
// succesful write...
}
// Detect the completion of the write if any was pending...
// Loop until the write pending is completed or timeout expires
pending_timeout = 0;
long comm_pending_timeout = theBufferLength * 10;
while (write_flag == TRUE && pending_timeout < comm_pending_timeout)
{
wfso_result = WaitForSingleObject(ovr_write.hEvent, COMM_WRITE_TIMEOUT);
switch(wfso_result)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(Comm, &ovr_write, &bytes_written, FALSE))
{
#ifdef WRITE_DEBUG
//OutputDebugString("Still not done writting...");
#endif
#if 0
// Error in communications
throw WritingPortException();
#endif
}
else
{
// successful write...
write_flag = FALSE;
// for (int i=0; i<bytes_written; i++)
// OutputDebugString(".");
#ifdef WRITE_DEBUG
//OutputDebugString("Successful Write...");
#endif
}
break;
case WAIT_TIMEOUT:
pending_timeout += COMM_WRITE_TIMEOUT;
#ifdef WRITE_DEBUG
//OutputDebugString("Write Event WAIT_TIMEOUT, pending_timeout is ");
// pending_timeout << endl;
#endif
if (pending_timeout >= comm_pending_timeout)
{
// Unable to finish the pending read!
throw PendingWriteException();
}
break;
default:
// Indicates an error on WaitForSingleObject
throw OverlappedEventException();
// Although break is unreachable, I'll leave it here.
break;
}
} // loop until successful write
SetThreadPriority(thread_handle, thread_pty);
#ifdef WRITE_DEBUG
//OutputDebugString("After pending write...");
#endif
// Close the reading event
CloseHandle(ovr_write.hEvent);
}
bool Win32_Modem::HandleReadEvent(OVERLAPPED *overlappedRead, unsigned char *theBuffer, long bufSize, unsigned long *theBytesRead, char *theOpenTime, char *theCloseTime)
{
DWORD lastError;
unsigned long numBytesRead;
if(Comm==INVALID_HANDLE_VALUE)
return false;
if (GetOverlappedResult(Comm, overlappedRead, &numBytesRead, TRUE)) //used to be FALSE
{
(*theBytesRead)+=numBytesRead;
return true;
}
else
{
lastError = GetLastError();
if (lastError == ERROR_INVALID_HANDLE)
{
//OutputDebugString("Error Invalid Handle");
return false;
}
else if(lastError == ERROR_IO_INCOMPLETE) //Win95 generates this on a read, its already done and fails Overlapped
{
/* if (theBuffer[0] != 0) // this should work, as there are no values < 0x20 in PPP
{
(*theBytesRead)+=1;
return true;
}
else*/
//OutputDebugString("ERROR_IO_INCOMPLETE");
return false;
}
else
{
//OutputDebugString("Unknown error returned by GetOverlappedResult");
return false;
}
}
}
//void Win32_Modem::ReadBuffer(unsigned char *theBuffer, long *theBytesRead, long theBytestoRead, char *theOpenTime, char *theCloseTime, bool newRead, OVERLAPPED *overlapped)
bool Win32_Modem::SetupReadEvent(OVERLAPPED *overlappedRead, unsigned char *theBuffer, long theBufferSize, unsigned long *theBytesRead, char *theOpenTime, char *theCloseTime)
{
static bool init = false;
bool done =false;
char tempStr[50];
char *tempStrPtr = &(tempStr[0]);
unsigned long bytesRead=0;
long err;
UtilTime presentTime;
if(Comm==INVALID_HANDLE_VALUE)
return false;
// if(!init)
// {
if(!SetCommMask(Comm, EV_RXCHAR))
{
long err=GetLastError();
printf("%d", err);
// throw ReadingPortException();
//OutputDebugString("Error setting the Comm Mask");
}
init=true;
// }
memset(tempStr,0,50);
presentTime.GetAsciiTime(&tempStrPtr);
memset(theOpenTime, 0, sizeof(theOpenTime));
strcpy(theOpenTime, tempStr);
while ( done!=true)
{
bytesRead=0;
err = ReadFile(Comm, &(theBuffer[*theBytesRead]), theBufferSize, &bytesRead, overlappedRead);
if((err!=0)&&(bytesRead!=0))
{
(*theBytesRead)+=bytesRead;
}
else
{
done=true;
}
}
memset(tempStr,0,50);
presentTime.GetAsciiTime(&tempStrPtr);
memset(theCloseTime, 0, sizeof(theCloseTime));
strcpy(theCloseTime, tempStr);
if (!err)
if (GetLastError() == ERROR_IO_PENDING)
return true;
return false;
}
/*bool Win32_Modem::HandleReadEvent(OVERLAPPED *overlappedRead, unsigned char *theBuffer, long theBufferSize, long *theBytesRead, char *theOpenTime, char *theCloseTime)
{
if (GetOverlappedResult(Comm, overlappedRead, *theBytesRead, FALSE))
return true;
DWORD lastError = GetLastError();
if (lastError == ERROR_INVALID_HANDLE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -