// ==========================================================================
// Author: Yee Hsu
// Date: 6/11/2010
//
// Desc: Serial Port Connector. Connects to Serial Port COM#
// Allows communication between serial port and device.
// ==========================================================================
// SerialPort.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SerialPort.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSerialPort::CSerialPort()
{
m_portHandle=INVALID_HANDLE_VALUE;
}
CSerialPort::~CSerialPort()
{
if(IsOpen())
ClosePort();
}
void CSerialPort::monitor_data()
{
DWORD thread_id;
monitor_data_thread_handle = CreateThread(0, 0, CSerialPort::monitor_data_thread, this, 0, &thread_id);
}
DWORD WINAPI CSerialPort::monitor_data_thread(LPVOID arg)
{
CSerialPort *pSerialPort;
pSerialPort = (CSerialPort *) arg;
pSerialPort->monitor_data_thread_terminate = false;
bool done;
BOOL success;
DWORD bytes;
byte buf[TMP_BUFFER_1024];
while (!pSerialPort->monitor_data_thread_terminate)
{
memset(buf, 0, sizeof(buf));
success = ReadFile (pSerialPort->m_portHandle, buf, sizeof(buf), &bytes,NULL);
done = success != 0;
if (!done)
{
DWORD rxgle = GetLastError ();
ASSERT (rxgle == ERROR_IO_PENDING);
}
else
{
if (pSerialPort->CallBackFunc_Data_Func && !pSerialPort->monitor_data_thread_terminate)
{
pSerialPort->CallBackFunc_Data_Func(buf, bytes, pSerialPort->data_func_context);
}
}
Sleep(1000);
}
return 0;
}
long CSerialPort::WriteData(const pbyte data, const int dwLength)
{
bool done;
BOOL success;
DWORD bytes;
if (dwLength == 0) /* Be pessimistic and assume WriteFile would choke on zero length */
{
return 0;
}
else
{
success = WriteFile(m_portHandle, data, dwLength, &bytes,NULL);
done = success != 0;
if (!done)
{
DWORD txgle = GetLastError ();
ASSERT (txgle == ERROR_IO_PENDING);
return 0;
}
}
return bytes;
}
BOOL CSerialPort::OpenPort(const int nPort, const int nBaudRate)
{
DCB dcb;
BOOL success;
COMMTIMEOUTS timeouts;
// TODO: Add your dispatch handler code here
CString portName;
portName.Format(_T("COM%d:"), nPort);
m_portHandle = CreateFile (portName,
GENERIC_READ | GENERIC_WRITE,
WIN32_NO_SHARING, // mandatory
0,
OPEN_EXISTING, // mandatory
0,//FILE_FLAG_OVERLAPPED,
WIN32_NO_TEMPLATE_FILE // mandatory
);
if (m_portHandle == INVALID_HANDLE_VALUE)
{
//CString msg;
//msg.Format(_T("Error %d"),GetLastError());
//MessageBox(msg);
return FALSE;
}
memset (&dcb, 0, sizeof (DCB));
dcb.DCBlength = sizeof (DCB);
//success = BuildCommDCB (cfgStr, &dcb); /* Note BuildCommDCB() turns off both hardware and software flow control */
dcb.BaudRate=nBaudRate;
dcb.fParity = FALSE;
dcb.fNull = FALSE;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
dcb.ByteSize = 8;
success = SetCommState (m_portHandle, &dcb);
ASSERT ((_T("SetCommState"), success));
if (!success)
{
CloseHandle (m_portHandle);
m_portHandle=INVALID_HANDLE_VALUE;
//MessageBox(_T("SetCommState Error"));
return FALSE;
}
/*
timeouts.ReadIntervalTimeout = WIN32_NO_TIMEOUT;
timeouts.ReadTotalTimeoutMultiplier = WIN32_NO_TIMEOUT;
timeouts.ReadTotalTimeoutConstant = WIN32_NO_TIMEOUT;
timeouts.WriteTotalTimeoutMultiplier = WIN32_NO_TIMEOUT;
timeouts.WriteTotalTimeoutConstant = WIN32_NO_TIMEOUT;
*/
timeouts.ReadIntervalTimeout = 3;
timeouts.ReadTotalTimeoutMultiplier = 3;
timeouts.ReadTotalTimeoutConstant = 2;
timeouts.WriteTotalTimeoutMultiplier = 3;
timeouts.WriteTotalTimeoutConstant = 2;
success = SetCommTimeouts (m_portHandle, &timeouts);
ASSERT ((_T("SetCommTimeouts"), success));
if (!success)
{
CloseHandle (m_portHandle);
m_portHandle=INVALID_HANDLE_VALUE;
//MessageBox(_T("SetCommTimeouts Error"));
return FALSE;
}
monitor_data();
//SystemParametersInfo(SPI_GETBATTERYIDLETIMEOUT,0,&m_batteryPowerTimeout,SPIF_UPDATEINIFILE);
//SystemParametersInfo(SPI_GETEXTERNALIDLETIMEOUT,0,&m_acPowerTimeout,SPIF_UPDATEINIFILE);
//SystemParametersInfo(SPI_SETBATTERYIDLETIMEOUT,0,NULL,SPIF_UPDATEINIFILE);
//SystemParametersInfo(SPI_SETEXTERNALIDLETIMEOUT,0,NULL,SPIF_UPDATEINIFILE);
return TRUE;
}
void CSerialPort::Set_Data_Callback(void (*CallBackFunctionName)(void *,unsigned long,void *), void *context)
{
if (CallBackFunctionName)
{
CallBackFunc_Data_Func=CallBackFunctionName;
data_func_context=context;
}
}
BOOL CSerialPort::ClosePort()
{
if (monitor_data_thread_handle != INVALID_HANDLE_VALUE)
{
monitor_data_thread_terminate = true;
}
Sleep(0);
if (m_portHandle != INVALID_HANDLE_VALUE)
{
CloseHandle (m_portHandle);
}
m_portHandle = INVALID_HANDLE_VALUE;
//SystemParametersInfo(SPI_SETBATTERYIDLETIMEOUT,m_batteryPowerTimeout,NULL,SPIF_UPDATEINIFILE);
//SystemParametersInfo(SPI_SETEXTERNALIDLETIMEOUT,m_acPowerTimeout,NULL,SPIF_UPDATEINIFILE);
return TRUE;
}
BOOL CSerialPort::IsOpen()
{
return m_portHandle!=INVALID_HANDLE_VALUE;
}
BOOL CSerialPort::SetDTR(const BOOL bEnable)
{
DCB dcb;
if(m_portHandle==INVALID_HANDLE_VALUE)
{
return FALSE;
}
if(GetCommState(m_portHandle,&dcb)==FALSE)
return FALSE;
if(bEnable)
{
// dcb.fDtrControl=DTR_CONTROL_ENABLE;
dcb.fRtsControl=RTS_CONTROL_ENABLE;
}
else
{
// dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
}
if(SetCommState(m_portHandle,&dcb)==FALSE)
return FALSE;
return TRUE;
}