#include "ehs/io/COM.h" #include "ehs/Str.h" #include "ehs/Log.h" namespace ehs { COM::COM() : port(0), baudRate(9600), byteSize(8), parity(Parity::NONE), stopBits(StopBits::ONE), hdl(nullptr), initialized(false) { } COM::COM(const UInt_8 port, const UInt_32 baudRate, const UInt_8 byteSize, const Parity parity, const StopBits stopBits) : port(port), baudRate(baudRate), byteSize(byteSize), parity(parity), stopBits(stopBits), hdl(nullptr), initialized(false) { } void COM::Initialize() { if (initialized) return; hdl = CreateFileW(L"\\\\.\\COM" + Str_16::FromNum(port), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); if (hdl == INVALID_HANDLE_VALUE) { EHS_LOG_INT(LogType::ERR, 0, "Failed to create handle at COM" + Str_8::FromNum(port) + " with error #" + Str_8::FromNum(GetLastError()) + "."); return; } DCB dcb = {}; dcb.DCBlength = sizeof(DCB); if (!GetCommState(hdl, &dcb)) { EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve COM" + Str_8::FromNum(port) + " state with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); return; } dcb.BaudRate = (DWORD)baudRate; dcb.ByteSize = (BYTE)byteSize; dcb.fParity = (DWORD)parity; dcb.StopBits = (BYTE)stopBits; dcb.fDtrControl = DTR_CONTROL_ENABLE; if (!SetCommState(hdl, &dcb)) { EHS_LOG_INT(LogType::ERR, 2, "Failed to set COM" + Str_8::FromNum(port) + " state with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); return; } SetCommMask(hdl, EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY); PurgeComm(hdl, PURGE_RXCLEAR | PURGE_TXCLEAR); initialized = true; } void COM::UnInitialize() { if (hdl) { if (!CloseHandle(hdl)) EHS_LOG_INT(LogType::ERR, 0, "Failed to close COM" + Str_8::FromNum(port) + " handle with error #" + Str_8::FromNum(GetLastError()) + "."); hdl = nullptr; } initialized = false; } UInt_32 COM::Wait() { UInt_32 event = 0; if (!WaitCommEvent(hdl, (DWORD*)&event, nullptr)) { EHS_LOG_INT(LogType::ERR, 0, "Failed to wait for COM" + Str_8::FromNum(port) + " event with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); } return event; } void COM::Transmit(const Char_8 data) { if (!initialized) return; if (!TransmitCommChar(hdl, data)) { EHS_LOG_INT(LogType::ERR, 0, "Failed to transmit character to COM" + Str_8::FromNum(port) + " with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); } } UInt_32 COM::Send(const Char_8* data, const UInt_32 size) { UInt_32 sent = 0; if (!WriteFile(hdl, (void*)data, (DWORD)size, (DWORD*)&sent, nullptr)) { EHS_LOG_INT(LogType::ERR, 0, "Failed to receive data from COM" + Str_8::FromNum(port) + " with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); } return sent; } UInt_32 COM::Receive(const Char_8* data, const UInt_32 size) { UInt_32 received = 0; if (!ReadFile(hdl, (void*)data, (DWORD)size, (DWORD*)&received, nullptr)) { EHS_LOG_INT(LogType::ERR, 0, "Failed to receive data from COM" + Str_8::FromNum(port) + " with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); } return received; } void COM::Flush() { if (!FlushFileBuffers(hdl)) { EHS_LOG_INT(LogType::ERR, 0, "Failed to flush data for COM" + Str_8::FromNum(port) + " with error #" + Str_8::FromNum(GetLastError()) + "."); UnInitialize(); } } }