#include #include #include "L4SERIAL.h" HANDLE InitSerialPort(WORD rate, WORD format, const char* port, bool overlapped) { HANDLE hComm = INVALID_HANDLE_VALUE; hComm = CreateFileA(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, overlapped ? FILE_FLAG_OVERLAPPED : NULL, NULL); if(hComm == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); DEBUG_STREAM << "ERROR: CreateFileA() failed [GetLastError() = " << GetLastError() << "]!\n" << std::flush; return INVALID_HANDLE_VALUE; } DCB control; memset(&control, 0, sizeof(control)); control.DCBlength = sizeof(control); control.EvtChar = (char)0xFF; if(rate == PCS_300) control.BaudRate = 300; else if(rate == PCS_1200) control.BaudRate = 1200; else if(rate == PCS_2400) control.BaudRate = 2400; else if(rate == PCS_9600) control.BaudRate = 9600; else if(rate == PCS_19P2) control.BaudRate = 19200; else if(rate == PCS_38P4) control.BaudRate = 38400; else if(rate == PCS_115K) control.BaudRate = 115200; else { DEBUG_STREAM << "ERROR: Invalid Baud Rate!\n" << std::flush; CloseHandle(hComm); return INVALID_HANDLE_VALUE; } if((format & PCSMAP) == PCSNP) control.Parity = NOPARITY; else if((format & PCSMAP) == PCSOP) control.Parity = ODDPARITY; else if((format & PCSMAP) == PCSEP) control.Parity = EVENPARITY; else if((format & PCSMAP) == PCSMP) control.Parity = MARKPARITY; else if((format & PCSMAP) == PCSSP) control.Parity = SPACEPARITY; else { DEBUG_STREAM << "ERROR: Invalid Parity!\n" << std::flush; CloseHandle(hComm); return INVALID_HANDLE_VALUE; } if((format & PCSMD) == PCS8D) control.ByteSize = 8; else if((format & PCSMD) == PCS6D) control.ByteSize = 6; else if((format & PCSMD) == PCS7D) control.ByteSize = 7; else if((format & PCSMD) == PCS8D) control.ByteSize = 8; else { DEBUG_STREAM << "ERROR: Invalid Byte Size!\n" << std::flush; CloseHandle(hComm); return INVALID_HANDLE_VALUE; } if((format & PCSMS) == PCS1S) control.StopBits = ONESTOPBIT; else if((format & PCSMS) == PCS2S) control.StopBits = TWOSTOPBITS; else { DEBUG_STREAM << "ERROR: Invalid Stop Bits!\n" << std::flush; CloseHandle(hComm); return INVALID_HANDLE_VALUE; } if(!SetCommState(hComm, &control)) { DEBUG_STREAM << "ERROR: SetCommState() failed [rate = " << control.BaudRate; DEBUG_STREAM << ", dataBits = " << control.ByteSize; DEBUG_STREAM << ", stopBits = " << control.StopBits; DEBUG_STREAM << ", parity = " << control.Parity << "!\n"; CloseHandle(hComm); return INVALID_HANDLE_VALUE; } //Non-blocking COMMTIMEOUTS timeout; timeout.ReadIntervalTimeout = MAXDWORD; timeout.ReadTotalTimeoutConstant = 0; timeout.ReadTotalTimeoutMultiplier = 0; timeout.WriteTotalTimeoutConstant = 0; timeout.WriteTotalTimeoutMultiplier = 0; if(!SetCommTimeouts(hComm, &timeout)) { DEBUG_STREAM << "ERROR: SetCommTimeouts() failed!\n"; CloseHandle(hComm); return INVALID_HANDLE_VALUE; } PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); return hComm; } //Win32 Serial support: ADB 01/11/07 PCSerial::PCSerial(WORD rate, WORD format, const char* port) //PCSerial(DWORD rate, BYTE dataBits, BYTE stopBits, BYTE parity, const WCHAR* port) { enabled = 0; mOverlappedOb.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); mOverlappedOb.Internal = 0; mOverlappedOb.InternalHigh = 0; mOverlappedOb.Offset = 0; mOverlappedOb.OffsetHigh = 0; //PCSerialInit(this, rate, format, port, int_num); hComm = InitSerialPort(rate, format, port, true); if(hComm != INVALID_HANDLE_VALUE) enabled = 1; } PCSerial::~PCSerial() { if (this == NULL) { std::cout << "~PCSerial has been passed a NULL pointer\n" << std::flush; } else { WaitForSingleObject(mOverlappedOb.hEvent,INFINITE); CloseHandle(mOverlappedOb.hEvent); CloseHandle(hComm); hComm = INVALID_HANDLE_VALUE; enabled = 0; } } //Win32 Serial support: ADB 01/15/07 Logical PCSerial::TestInstance() { //return PCSerialTestInstance(this); return 1; } //Win32 Serial support: ADB 01/15/07 int PCSerial::ReceiveString(char *destPtr, int maxLen) // returns length { //TODO: Do overlapped reads if we ever need this function again assert(FALSE); //return PCSerialReceive(this, destPtr, maxLen) DWORD bytesRead; ReadFile(hComm, (void *)destPtr, maxLen, &bytesRead, NULL); return (int)bytesRead; } //Win32 Serial support: ADB 01/15/07 void PCSerial::FlowControlEnable(Logical onOff) { //STUBBED: Serial ADB 01/15/07 //VERIFY: Probably not used //PCSerialFlowControl(this, (int) onOff);DCB control; } Logical PCSerial::CanDraw() { return (WaitForSingleObject(mOverlappedOb.hEvent, 0) == WAIT_OBJECT_0); } //Win32 Serial support: ADB 01/15/07 void PCSerial::SendString(char *srcPtr, int length) { //PCSerialSend(this, srcPtr, length); WaitForSingleObject(mOverlappedOb.hEvent, INFINITE); DWORD bytesWritten; WriteFile(hComm, (void*)srcPtr, length, &bytesWritten, &mOverlappedOb); } //Win32 Serial support: ADB 01/15/07 int PCSerial::ReceiveCharCount() { //return PCSerialReceiveCount(this); COMMPROP props; if(!GetCommProperties(hComm, &props)) { DEBUG_STREAM << "ERROR: GetCommProperties() failed in TransmitCharCount()! GetLastError() = " << GetLastError() << std::endl; return 0; } return props.dwCurrentRxQueue; } //Win32 Serial support: ADB 01/15/07 int PCSerial::TransmitCharCount() { //return PCSerialTransmitCount(this); COMMPROP props; if(!GetCommProperties(hComm, &props)) { DEBUG_STREAM << "ERROR: GetCommProperties() failed in TransmitCharCount()! GetLastError() = " << GetLastError() << std::endl; return 0; } return props.dwCurrentTxQueue; } //Win32 Serial support: ADB 01/15/07 int PCSerial::Errors() // returns error value, clears it { //return PCSerialErrors(this); DWORD errors; if(!ClearCommError(hComm, &errors, NULL)) { DEBUG_STREAM << "ERROR: GetCommError() failed!\n"; return PCS_ERR_OTHER; } int outError = 0; if(errors & CE_OVERRUN) { outError |= PCS_ERR_OVERRUN; errors ^= CE_OVERRUN; } if(errors & CE_RXPARITY) { outError |= PCS_ERR_PARITY; errors ^= CE_RXPARITY; } if(errors & CE_FRAME) { outError |= PCS_ERR_FRAMING; errors ^= CE_FRAME; } if(errors & CE_BREAK) { outError |= PCS_ERR_BREAK; errors ^= CE_BREAK; } if(errors & CE_RXOVER) { outError |= PCS_ERR_RXOVER; errors ^= CE_RXOVER; } if(errors & CE_TXFULL) { outError |= PCS_ERR_TXOVER; errors ^= CE_TXFULL; } //other error if(errors) outError |= PCS_ERR_OTHER; return outError; } //Win32 Serial support: ADB 01/15/07 int PCSerial::IsActive() { //return PCSerialActive(this); return enabled; } //Win32 Serial support: ADB 01/15/07 int PCSerial::ModemStatus() { //return PCSerialModemStatus(this); DWORD modem; if(!GetCommModemStatus(hComm, &modem)) { DEBUG_STREAM << "ERROR: GetCommModemStatus() failed!\n"; return 0; } return modem; }