1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Initial Developer of this code is David Baum.
* Portions created by David Baum are Copyright (C) 1998 David Baum.
* All Rights Reserved.
*/
#include <windows.h>
#include "PSerial.h"
#define kDefaultSpeed 9600
#define kInputBufferSize 16384
#define kOutputBufferSize 16384
class PSerial_win : public PSerial
{
public:
virtual bool Open(const char *name);
virtual void Close();
virtual long Read(void *ptr, long count);
virtual long Write(const void *ptr, long count);
virtual void FlushWrite();
virtual bool SetTimeout(long timeout_ms);
virtual bool SetSpeed(int speed, int opts = 0);
virtual bool SetDTR(bool assert);
virtual bool SetRTS(bool assert);
private:
HANDLE fFile;
};
PSerial * PSerial::NewSerial()
{
return new PSerial_win;
}
const char *PSerial::GetDefaultName()
{
return "\\\\.\\COM1";
}
bool PSerial_win::Open(const char *name)
{
if (fOpen) return false;
fFile = CreateFile(name,GENERIC_READ | GENERIC_WRITE,
0, 0, OPEN_EXISTING, 0, 0);
if (fFile == INVALID_HANDLE_VALUE) return false;
// SetupComm(fFile, kInputBufferSize, kOutputBufferSize);
if (!SetSpeed(kDefaultSpeed)) return false;
SetBlocking(true);
fOpen = true;
return true;
}
bool PSerial_win::SetSpeed(int speed, int opts)
{
DCB dcb;
dcb.DCBlength = sizeof(DCB); // sizeof(DCB)
if (!GetCommState(fFile, &dcb)) return false;
dcb.BaudRate = speed;
dcb.fBinary = 1;
dcb.fOutxCtsFlow = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type
dcb.fDsrSensitivity = 0; // DSR sensitivity
dcb.fTXContinueOnXoff = 0; // XOFF continues Tx
dcb.fOutX = 0; // XON/XOFF out flow control
dcb.fInX = 0; // XON/XOFF in flow control
dcb.fErrorChar = 0; // enable error replacement
dcb.fNull = 0; // enable null stripping
dcb.fRtsControl = 0; // RTS flow control
dcb.fAbortOnError = 0; // abort reads/writes on error
dcb.XonLim = 100;
dcb.XoffLim = 100;
dcb.ByteSize = 8 - (opts & kPSerial_DataMask); // number of bits/byte, 4-8
dcb.Parity = (opts & kPSerial_ParityMask) >> kPSerial_ParityShift; // 0-4=no,odd,even,mark,space
dcb.StopBits = ((opts & kPSerial_StopMask) >> kPSerial_StopShift); // 0,1,2 = 1, 1.5, 2
dcb.XonChar = 1;
dcb.XoffChar = 2;
dcb.ErrorChar = 0;
dcb.EofChar = 0;
dcb.EvtChar = 0;
return SetCommState(fFile, &dcb);
}
bool PSerial_win::SetTimeout(long timeout_ms)
{
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
switch(timeout_ms)
{
case kPStream_NeverTimeout:
break;
case 0:
timeouts.ReadIntervalTimeout = MAXDWORD;
break;
default:
timeouts.ReadTotalTimeoutConstant = timeout_ms;
break;
}
SetCommTimeouts(fFile, &timeouts);
return true;
}
void PSerial_win::Close()
{
if (!fOpen) return;
CloseHandle(fFile);
fOpen = false;
}
long PSerial_win::Write(const void *ptr, long count)
{
DWORD actual;
if (!WriteFile(fFile, ptr, (unsigned long)count, &actual, (struct _OVERLAPPED *)NULL))
return -1;
return actual;
}
long PSerial_win::Read(void *ptr, long count)
{
DWORD actual;
if (!ReadFile(fFile, ptr, count, &actual, (struct _OVERLAPPED *)NULL))
{
DWORD lstError = GetLastError();
DWORD Errors;
COMSTAT cstat;
ClearCommError( fFile, &Errors, &cstat );
return 0;
}
return actual;
}
bool PSerial_win::SetDTR(bool assert)
{
return EscapeCommFunction(fFile, assert ? SETDTR : CLRDTR);
}
bool PSerial_win::SetRTS(bool assert)
{
return EscapeCommFunction(fFile, assert ? SETRTS : CLRRTS);
}
void PSerial_win::FlushWrite()
{
FlushFileBuffers(fFile);
}
|