Created
March 7, 2015 03:41
-
-
Save jasin/adf969a34e654c5eac82 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include "stdafx.h" | |
#include "serial.h" | |
Serial::Serial(const TCHAR *pchPort, HWND &hwnd) // Constructor | |
{ | |
SetOnEventHandle(hwnd); | |
SetPort(pchPort); | |
m_bIsConnected = false; | |
} | |
Serial::~Serial() // Destructor | |
{ | |
delete m_pBuffer; | |
delete[] m_pchPort; | |
CloseHandle(m_hSerial); | |
} | |
int Serial::UnInit() | |
{ | |
/* Kill the worker thread, clean up */ | |
SignalObjectAndWait(m_hThreadTerminator, m_hThread, INFINITE, FALSE); | |
m_bIsConnected = false; | |
return 0; | |
} | |
int Serial::Init() | |
{ | |
m_hSerial = CreateFile(m_pchPort, | |
GENERIC_READ | GENERIC_WRITE, | |
0, | |
0, | |
OPEN_EXISTING, | |
FILE_FLAG_OVERLAPPED, | |
0); | |
if (m_hSerial == INVALID_HANDLE_VALUE) | |
{ | |
if (GetLastError() == ERROR_FILE_NOT_FOUND) | |
{ | |
// Serial port does not exist. | |
return -1; | |
} | |
// Error occurred | |
return -1; | |
} | |
else | |
{ | |
DCB dcbSerialParams = {0}; | |
dcbSerialParams.DCBlength = sizeof(dcbSerialParams); | |
if (!GetCommState(m_hSerial, &dcbSerialParams)) | |
{ | |
// error getting the connection, report to user | |
return -1; | |
} | |
dcbSerialParams.BaudRate = CBR_115200; | |
dcbSerialParams.ByteSize = 8; | |
dcbSerialParams.StopBits = ONESTOPBIT; | |
dcbSerialParams.Parity = NOPARITY; | |
if(!SetCommState(m_hSerial, &dcbSerialParams)) | |
{ | |
// error setting state of COM port, report to user | |
return -1; | |
} | |
// Not sure if the below code needs to be included or not with checking the status of the COM queue | |
COMMTIMEOUTS timeouts = {0}; | |
timeouts.ReadIntervalTimeout=MAXDWORD; | |
timeouts.ReadTotalTimeoutConstant=0; | |
timeouts.ReadTotalTimeoutMultiplier=0; | |
timeouts.WriteTotalTimeoutConstant=0; | |
timeouts.WriteTotalTimeoutMultiplier=0; | |
if(!SetCommTimeouts(m_hSerial, &timeouts)){ | |
//error inform the user | |
return -1; | |
} | |
if (!SetCommMask(m_hSerial, EV_RXCHAR | EV_TXEMPTY)) | |
{ | |
//error occurred inform the user | |
return -1; | |
} | |
// Create thread terminator | |
m_hThreadTerminator = CreateEvent(0, 0, 0, 0); | |
// Create an event that will be signaled w/(SetEvent()) in the worker thread. | |
m_hThreadRunning = CreateEvent(0, 0, 0, 0); | |
// Begin worker thread | |
m_hThread = (HANDLE)_beginthreadex(0, 0, &WorkThread, (void*) this, 0, 0); | |
// Wait for event, see that the thread is running. Clean up a possible handle leak. | |
DWORD dwWait = WaitForSingleObject(m_hThreadRunning, INFINITE); | |
assert(dwWait == WAIT_OBJECT_0); | |
m_bIsConnected = true; | |
m_pBuffer = new Buffer(); | |
CloseHandle(m_hThreadRunning); | |
return 0; | |
} | |
} | |
unsigned int __stdcall Serial::WorkThread(void* pvParam) | |
{ | |
// This is a pointer to the 'this' serial class. | |
// Needed to be able to set members of the class in a static class function | |
Serial * cThis = (Serial*) pvParam; | |
// Set up the overlapped event | |
OVERLAPPED ov; | |
memset(&ov, 0, sizeof(ov)); | |
ov.hEvent = CreateEvent(0, true, false, 0); | |
DWORD dwEventMask = 0; | |
DWORD dwWait; | |
HANDLE aHandles[2]; | |
aHandles[0] = cThis->m_hThreadTerminator; | |
aHandles[1] = ov.hEvent; | |
SetEvent(cThis->m_hThreadRunning); | |
while (true) | |
{ | |
if (!WaitCommEvent(cThis->m_hSerial, &dwEventMask, &ov)) | |
{ | |
assert(GetLastError() == ERROR_IO_PENDING); | |
} | |
dwWait = WaitForMultipleObjects(2, aHandles, FALSE, INFINITE); | |
switch(dwWait) | |
{ | |
case WAIT_OBJECT_0: | |
{ | |
_endthreadex(1); | |
} | |
case WAIT_OBJECT_0 + 1: | |
{ | |
if (dwEventMask & EV_TXEMPTY) | |
{ | |
ResetEvent(ov.hEvent); | |
} | |
else if (dwEventMask & EV_RXCHAR) | |
{ | |
// read data here | |
DWORD dwBytesRead = 0; | |
OVERLAPPED ovRead = { 0 }; | |
ovRead.hEvent = CreateEvent(0, true, false, 0); | |
// Get the Bytes in queue | |
//wstring str; | |
do | |
{ | |
byte szBuf; | |
//memset(szBuf, 0x00, sizeof(szBuf)); | |
if (ReadFile(cThis->m_hSerial, &szBuf, 1, NULL, &ovRead)) | |
{ | |
GetOverlappedResult(cThis->m_hSerial, &ovRead, &dwBytesRead, FALSE); | |
//if(szBuf[0] != '\r') | |
cThis->m_pBuffer->AddData(szBuf); | |
} | |
else | |
{ | |
DWORD err = GetLastError(); | |
(void)err; | |
} | |
} while (dwBytesRead > 0); | |
CloseHandle(ovRead.hEvent); // clean up!!! | |
} | |
// Reset the overlapped event | |
ResetEvent(ov.hEvent); | |
} | |
break; | |
}//switch | |
} | |
return 0; | |
} | |
bool Serial::WriteData(byte *byteBuffer, DWORD dwSize) | |
{ | |
//TODO: Write data to the serial port from the buffer. | |
OVERLAPPED ov = { 0 }; | |
ov.hEvent = CreateEvent(0, true, false, 0); | |
DWORD dwBytesWritten = 0; | |
if (!WriteFile(m_hSerial, byteBuffer, dwSize, &dwBytesWritten, &ov)) | |
if (GetLastError() == ERROR_IO_PENDING) | |
WaitForSingleObject(ov.hEvent, INFINITE); | |
CloseHandle(ov.hEvent); | |
return 0; | |
} | |
bool Serial::IsConnected() | |
{ | |
return m_bIsConnected; | |
} | |
TCHAR Serial::GetPort() | |
{ | |
return * m_pchPort; | |
} | |
void Serial::SetPort(const TCHAR *pchPort) | |
{ | |
m_nLength = _tcslen(pchPort)+1; // Get the length of the string | |
m_pchPort = new TCHAR[m_nLength]; // Allocate memory | |
_tcscpy_s(m_pchPort, m_nLength, pchPort); // Copy to internal buffer | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment