148 lines
3.7 KiB
C++
Executable File
148 lines
3.7 KiB
C++
Executable File
#include "OSerialBus.h"
|
|
#include <iostream>
|
|
|
|
#ifdef WINDOWS
|
|
OSerialBus::OSerialBus(const std::wstring& comPort, int baudRate) noexcept:
|
|
comPort(comPort),
|
|
baudRate(baudRate)
|
|
{
|
|
serialHandle = CreateFileW(normalizePort(comPort).c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if (serialHandle == INVALID_HANDLE_VALUE) {
|
|
DWORD err = GetLastError();
|
|
std::wcerr << L"Unable to open serial port file " << normalizePort(comPort) << L"! Error: " << (int)err << std::endl;
|
|
return;
|
|
}
|
|
|
|
DCB serialParams = { 0 };
|
|
serialParams.DCBlength = sizeof(serialParams);
|
|
|
|
if (!GetCommState(serialHandle, &serialParams)) {
|
|
DWORD err = GetLastError();
|
|
std::wcerr << L"Unable to get comm state of port " << normalizePort(comPort) << L"! Is the port busy? Error: " << (int)err << std::endl;
|
|
|
|
return;
|
|
}
|
|
|
|
serialParams.BaudRate = baudRate;
|
|
serialParams.ByteSize = 8;
|
|
serialParams.Parity = NOPARITY;
|
|
serialParams.StopBits = ONESTOPBIT;
|
|
serialParams.fParity = FALSE;
|
|
serialParams.fBinary = TRUE;
|
|
serialParams.fOutxCtsFlow = FALSE;
|
|
serialParams.fOutxDsrFlow = FALSE;
|
|
serialParams.fOutX = FALSE;
|
|
serialParams.fInX = FALSE;
|
|
serialParams.fRtsControl = RTS_CONTROL_DISABLE;
|
|
serialParams.fDtrControl = DTR_CONTROL_DISABLE;
|
|
|
|
if (!SetCommState(serialHandle, &serialParams)) {
|
|
DWORD err = GetLastError();
|
|
std::wcerr << L"Unable to set comm state of port " << normalizePort(comPort) << L"! Is the port busy? Error: " << (int)err << std::endl;
|
|
return;
|
|
}
|
|
|
|
COMMTIMEOUTS timeouts = { 0 };
|
|
timeouts.ReadIntervalTimeout = 50;
|
|
timeouts.ReadTotalTimeoutConstant = 50;
|
|
timeouts.ReadTotalTimeoutMultiplier = 50;
|
|
timeouts.WriteTotalTimeoutConstant = 50;
|
|
timeouts.WriteTotalTimeoutMultiplier = 10;
|
|
|
|
if (!SetCommTimeouts(serialHandle, &timeouts)) {
|
|
DWORD err = GetLastError();
|
|
std::wcerr << L"Unable to set comm timeouts of port " << normalizePort(comPort) << L"! Is the port busy? Error: " << (int)err << std::endl;
|
|
return;
|
|
}
|
|
|
|
open = true;
|
|
}
|
|
|
|
OSerialBus::OSerialBus(OSerialBus&& other) noexcept:
|
|
comPort(other.comPort),
|
|
baudRate(other.baudRate),
|
|
serialHandle(other.serialHandle),
|
|
open(other.open)
|
|
{
|
|
other.serialHandle = INVALID_HANDLE_VALUE;
|
|
other.open = false;
|
|
}
|
|
|
|
bool OSerialBus::isOpen() const noexcept
|
|
{
|
|
return open;
|
|
}
|
|
|
|
bool OSerialBus::close() noexcept
|
|
{
|
|
if (!isOpen()) {
|
|
return true;
|
|
}
|
|
return CloseHandle(serialHandle);
|
|
}
|
|
|
|
bool OSerialBus::send(const std::string& line) noexcept
|
|
{
|
|
// Important: this relies on chartype of line being 1 byte long!
|
|
const char* data = line.data();
|
|
std::size_t remaining = line.size();
|
|
|
|
while (remaining > 0) {
|
|
DWORD bytesWritten = 0;
|
|
|
|
if (!WriteFile(serialHandle, data, (DWORD)remaining, &bytesWritten, nullptr)) {
|
|
return false;
|
|
}
|
|
if (bytesWritten == 0) {
|
|
return false;
|
|
}
|
|
|
|
data += bytesWritten;
|
|
remaining -= bytesWritten;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OSerialBus::sendl(const std::string& line) noexcept
|
|
{
|
|
if (!send(line)) {
|
|
return false;
|
|
}
|
|
return send("\n");
|
|
}
|
|
|
|
int OSerialBus::getBaudRate() const noexcept
|
|
{
|
|
return baudRate;
|
|
}
|
|
|
|
const std::wstring& OSerialBus::getComPort() const noexcept
|
|
{
|
|
return comPort;
|
|
}
|
|
|
|
OSerialBus& OSerialBus::operator<<(const std::string& in)
|
|
{
|
|
if (!send(in)) {
|
|
throw std::runtime_error("Failed to write to COM port!");
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
std::wstring OSerialBus::normalizePort(const std::wstring& port) noexcept
|
|
{
|
|
// If port string already includes prefix, return as-is
|
|
if (port == L"\\\\.\\") {
|
|
return port;
|
|
}
|
|
|
|
// If the first 3 chars in the portstring are COM, prefix the prefix
|
|
if (_wcsnicmp(port.c_str(), L"COM", 3) == 0) {
|
|
return std::wstring(L"\\\\.\\") + port;
|
|
}
|
|
|
|
return port;
|
|
}
|
|
#endif
|