-
Notifications
You must be signed in to change notification settings - Fork 0
/
serial_win32.cc
84 lines (82 loc) · 2.15 KB
/
serial_win32.cc
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
#include <stdio.h>
#include <map>
#include <stdexcept>
#include <windows.h>
void msleep(unsigned msec) { Sleep(msec); }
std::map<serial *, int> serial_peek_buffer;
serial::serial(const std::string &name, int speed) {
data = CreateFile(name.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (!data || data==INVALID_HANDLE_VALUE) throw std::runtime_error("cannot open port '" + name + "'");
set_speed(speed);
serial_peek_buffer[this] = EOF;
}
serial::~serial() {
serial_peek_buffer.erase(this);
CloseHandle(data);
}
void serial::set_speed(int speed) {
if (speed<0) speed = 9600;
DCB dcb;
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = speed;
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
dcb.wReserved = 0;
dcb.XonLim = 0;
dcb.XoffLim = 0;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if (!SetCommState(data, &dcb)) throw std::runtime_error("cannot reset speed");
}
bool serial::readable() {
if (serial_peek_buffer[this]!=EOF) return true;
COMMTIMEOUTS ts;
GetCommTimeouts(data, &ts);
COMMTIMEOUTS to = { MAXDWORD, 0, 0, 0, 0 };
SetCommTimeouts(data, &to);
DWORD dw=0;
char c;
if (ReadFile(data, &c, 1, &dw, 0) && dw) serial_peek_buffer[this] = c;
SetCommTimeouts(data, &ts);
return serial_peek_buffer[this]!=EOF;
}
serial &serial::read(void *buf, std::streamsize n) {
DWORD dw;
unsigned char *p = static_cast<unsigned char *>(buf);
{
int &c = serial_peek_buffer[this];
if (c!=EOF) {
*p++ = c;
--n;
c = EOF;
}
}
while (n) {
ReadFile(data, p, n, &dw, 0);
p += dw;
n -= dw;
}
return *this;
}
serial &serial::write(const void *buf, std::streamsize n) {
DWORD dw;
const unsigned char *p = static_cast<const unsigned char *>(buf);
while (n) {
WriteFile(data, p, n, &dw, 0);
p += dw;
n -= dw;
}
return *this;
}