Скачиваний:
35
Добавлен:
15.09.2014
Размер:
5.22 Кб
Скачать
#include "StdAfx.h"
#include "COM.h"
#include "Exception.h"
using namespace Kingas;
using namespace Kingas::Communication;

COM::COM(void)
	: _hCommunication(INVALID_HANDLE_VALUE), _WriterThreadId(0), _ReaderThreadId(0),
	_AbortReading(false) {
}

COM::~COM(void) {
	Close();
}

unsigned long WINAPI COM::WriteThreadProc(void * lpParameter) {
	COM * parameter = (COM *)lpParameter;
	unsigned long writed, toWrite = wcslen(parameter->_WriteCache) * sizeof(TCHAR);
	parameter->_WriterCompleteStatus = COM::CompleteStatus::Success;

	if (!WriteFile(parameter->_hCommunication,
		parameter->_WriteCache,
		toWrite,
		&writed,
		NULL))
		parameter->_WriterCompleteStatus = COM::CompleteStatus::Error;
	if (!writed)
		parameter->_WriterCompleteStatus = COM::CompleteStatus::TimeOut;

	if (!CreateThread(NULL,
		sizeof(parameter),
		WriterAsyncCallback,
		parameter,
		0,
		NULL))
		parameter->_WriterThreadId = 0;
	return parameter->_WriterCompleteStatus;
}

unsigned long WINAPI COM::WriterAsyncCallback(void * lpParameter) {
	COM * parameter = (COM *)lpParameter;
	void (*callback)(COM::CompleteStatus);
	callback = parameter->_WriteCompleteCallback;
	COM::CompleteStatus returnStatus = parameter->_WriterCompleteStatus;
	parameter->_WriterThreadId = 0;
	callback(returnStatus);
	return returnStatus;
}

unsigned long WINAPI COM::ReadThreadProc(void * lpParameter) {
	COM * parameter = (COM *)lpParameter;
	unsigned long readed;
	parameter->_ReaderCompleteStatus = COM::CompleteStatus::Success;
	parameter->_ReadedCache = new TCHAR[parameter->_ReadLimit + 1];
	memset(parameter->_ReadedCache, 0, parameter->_ReadLimit + 1);

	if (!ReadFile(parameter->_hCommunication,
		parameter->_ReadedCache,
		parameter->_ReadLimit * sizeof(TCHAR),
		&readed,
		NULL))
	{
		parameter->_ReaderCompleteStatus = COM::CompleteStatus::Error;
	}
	if (!readed)
		parameter->_ReaderCompleteStatus = COM::CompleteStatus::TimeOut;

	if (!CreateThread(NULL,
		sizeof(parameter),
		ReaderAsyncCallback,
		parameter,
		0,
		NULL))
		delete[] parameter->_ReadedCache;
	return parameter->_ReaderCompleteStatus;
}

unsigned long WINAPI COM::ReaderAsyncCallback(void * lpParameter) {
	COM * parameter = (COM *)lpParameter;
	void (*callback)(TCHAR *, COM::CompleteStatus);
	callback = parameter->_ReadCompleteCallback;
	COM::CompleteStatus returnStatus = parameter->_ReaderCompleteStatus;
	TCHAR * buffer = new TCHAR[wcslen(parameter->_ReadedCache) + 1];
	wcscpy(buffer, parameter->_ReadedCache);
	buffer[wcslen(parameter->_ReadedCache)] = 0;
	delete[] parameter->_ReadedCache;
	if (!parameter->_AbortReading)
	{
		CreateThread(NULL,
			sizeof(parameter),
			ReadThreadProc,
			parameter,
			0,
			&parameter->_ReaderThreadId);
	}
	else
	{
		parameter->_AbortReading = false;
		parameter->_ReaderThreadId = 0;
	}
	callback(buffer, returnStatus);
	return returnStatus;
}

void COM::Open(unsigned char port) {
	if (_hCommunication != INVALID_HANDLE_VALUE)
		throw Exception(_T("[Kingas::Communication::COM::Open] COM already is open."));
	Stream stream;
	stream << _T("COM") << port;
	_hCommunication = CreateFile(stream.str().c_str(),
		GENERIC_READ | GENERIC_WRITE,
		0,
		0,
		OPEN_EXISTING,
		0,
		NULL);
	if (_hCommunication == INVALID_HANDLE_VALUE) {
		Stream errorMessage;
		errorMessage << _T("[Kingas::Communication::COM::Open] Cann't open communication port ")
			<< stream.str() << _T(".");
		throw Exception(errorMessage.str());
	}

	COMMTIMEOUTS timeouts = {0};
	timeouts.ReadIntervalTimeout = 1;
	timeouts.ReadTotalTimeoutMultiplier = 1;
	timeouts.ReadTotalTimeoutConstant = 1;
	timeouts.WriteTotalTimeoutMultiplier = 1;
	timeouts.WriteTotalTimeoutConstant = 1;
	if (!SetCommTimeouts(_hCommunication, &timeouts))
		throw Exception(_T("[Kingas::Communication::COM::Open] Error setting time-outs."));

	DCB dcb = {0};
	if (!GetCommState(_hCommunication, &dcb))
		throw Exception(_T("[Kingas::Communication::COM::Open] Error in GetCommState."));
	dcb.BaudRate = CBR_57600;
	SetCommState(_hCommunication, &dcb);
}

bool COM::Close() {
	if (_hCommunication != INVALID_HANDLE_VALUE)
	{
		CloseHandle(_hCommunication);
		_hCommunication = INVALID_HANDLE_VALUE;
		return true;
	}
	return false;
}

void COM::AsyncWrite(const TCHAR * message, void (*callback)(COM::CompleteStatus)) {
	if (_WriterThreadId)
		throw Exception(_T("[Kingas::Communication::COM::AsyncWrite] Writer already exist."));
	_WriteCompleteCallback = callback;
	_WriteCache = new TCHAR[wcslen(message) + 1];
	_WriteCache[wcslen(message)] = 0;
	wcscpy(_WriteCache, message);
	CreateThread(NULL,
		sizeof(COM *),
		COM::WriteThreadProc,
		(void *)this,
		0,
		&_WriterThreadId);
}

void COM::AsyncRead(void (*callback)(TCHAR * message, COM::CompleteStatus), unsigned long limit) {
	if (_ReaderThreadId)
		throw Exception(_T("[Kingas::Communication::COM::AsyncRead] Reader already exist."));
	_ReadCompleteCallback = callback;
	_ReadLimit = limit;
	CreateThread(NULL,
		sizeof(COM *),
		COM::ReadThreadProc,
		(void *)this,
		0,
		&_ReaderThreadId);
}

void COM::AbortReading() {
	_AbortReading = true;
}
Соседние файлы в папке Source