DCL 4.0
Loading...
Searching...
No Matches
SerialPort.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#if __DCL_WINDOWS
4 #include <windows.h>
5#else
6 #include <dcl/_unistd.h>
7#endif
8
9#include <dcl/SerialPort.h>
10
11#if __DCL_DEBUG
12#undef __THIS_FILE__
13static const char_t __THIS_FILE__[] = __T("dcl/SerialPort.cpp");
14#endif
15
16__DCL_BEGIN_NAMESPACE
17
19
20#ifndef INVALID_HANDLE_VALUE
21#define INVALID_HANDLE_VALUE -1
22#endif
23
24SerialPort::~SerialPort()
25{
26#if __DCL_WINDOWS
27 if (__overlapped.hEvent != NULL)
28 CloseHandle(__overlapped.hEvent);
29#endif
30}
31
32SerialPort::SerialPort(const String& _path, int _oflags,
33 size_t _inQueue, size_t _outQueue
35{
36#if __DCL_WINDOWS
37 __revents = 0;
38 ZeroMemory(&__overlapped, sizeof(__overlapped));
39#endif
40 open(_path, _oflags, _inQueue, _outQueue);
41}
42
43void SerialPort::open(const String& _path, int _oflags,
44 size_t _inQueue, size_t _outQueue
46{
47 File::open(_path, _oflags | File::NOCTTY);
48
49#if __DCL_WINDOWS
50 __DCL_ASSERT_PARAM(_inQueue > 0 && _outQueue > 0);
51 do {
52 if (!SetupComm(__handle, (DWORD)_inQueue, (DWORD)_outQueue))
53 break;
54
55 if (_oflags & File::NONBLOCK) {
56 /*
57 if (!SetCommMask(__handle, EV_RXCHAR))
58 break;
59 */
60
61 // set read non-blocking
62 COMMTIMEOUTS cto;
63 if (!GetCommTimeouts(__handle, &cto))
64 break;
65
66 cto.ReadIntervalTimeout = MAXDWORD;
67 cto.ReadTotalTimeoutConstant = 0;
68 cto.ReadTotalTimeoutMultiplier = 0;
69 if (!SetCommTimeouts(__handle, &cto))
70 break;
71 }
72
73 // success
74 return;
75 } while (false);
76
77 // failed
78 DWORD dwSaveError = GetLastError();
79 try {
80 close();
81 }
82 catch (Exception* cause) {
83 cause->destroy();
84 }
85 throw new IOException(_path, dwSaveError);
86#endif
87}
88
89void SerialPort::setAttributes(
90 SerialPort::BaudRate _baudRate, // BR_9600
91 SerialPort::ByteSize _byteSize, // BS_8NO
92 SerialPort::StopBits _stopBits, // SB_1
93 SerialPort::FlowControl _flowControl // FC_NONE
95{
96#if __DCL_WINDOWS
97 DCB dcb;
98 ZeroMemory(&dcb, sizeof(dcb));
99 dcb.DCBlength = sizeof(dcb);
100 if (!GetCommState(__handle, &dcb))
101 throw new IOException(toString(), GetLastError());
102
103 dcb.BaudRate = _baudRate;
104 switch (_byteSize) {
105 case SerialPort::BS_8NO:
106 dcb.ByteSize = 8;
107 dcb.Parity = NOPARITY;
108 break;
109 case SerialPort::BS_7EVEN:
110 dcb.ByteSize = 7;
111 dcb.Parity = EVENPARITY;
112 break;
113 case SerialPort::BS_7ODD:
114 dcb.ByteSize = 7;
115 dcb.Parity = ODDPARITY;
116 break;
117 }
118 dcb.fParity = dcb.Parity != NOPARITY;
119
120 switch (_stopBits) {
121 case SB_1:
122 dcb.StopBits = ONESTOPBIT;
123 break;
124 case SB_2:
125 dcb.StopBits = TWOSTOPBITS;
126 break;
127 }
128
129 switch (_flowControl) {
130 case FC_RTSCTS :
131 dcb.fOutxCtsFlow = TRUE;
132 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
133 break;
134 case FC_XONXOFF :
135 dcb.fOutX = dcb.fInX = TRUE;
136 break;
137 }
138
139 if (!SetCommState(__handle, &dcb))
140 throw new IOException(toString(), GetLastError());
141
142 // success
143#else
144 /*
145 Ref erence
146 - Serial Programming Guide for POSIX Operation Systems.
147 http://www.easysw.com/~mike/serial/serial.html
148 - http://en.wikibooks.org/wiki/Serial_Programming/termios
149 - man termiso(3)
150 - 리눅스에서 시리얼통신(II).
151 http://www.lug.or.kr/docs/LINUX/others/00-05-5.htm
152 */
153
154 struct termios config;
155 if (tcgetattr(__handle, &config))
156 throw new IOException(toString(), errno);
157
158 // Raw mode , man 3 termios
159 config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
160 | INLCR | IGNCR | ICRNL | IXON);
161 config.c_oflag &= ~OPOST;
162 config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
163
164 config.c_cflag |= CLOCAL | CREAD;
165
166 // Flow Control
167#ifdef CRTSCTS // not in POSIX
168 config.c_cflag &= ~CRTSCTS;
169#endif
170 config.c_iflag &= ~(IXON | IXOFF | IXANY);
171 switch (_flowControl) {
172 case SerialPort::FC_NONE :
173 break;
174 case SerialPort::FC_RTSCTS :
175#ifdef CRTSCTS
176 config.c_cflag |= CRTSCTS;
177#endif
178 break;
179 case SerialPort::FC_XONXOFF :
180 config.c_iflag |= IXON | IXOFF;
181 break;
182 default :
183 __DCL_ASSERT(false);
184 }
185
186 // Stop Bits
187 if (_stopBits == SerialPort::SB_1)
188 config.c_cflag &= ~CSTOPB;
189 else
190 config.c_cflag |= CSTOPB;
191
192 // Byte Size
193 switch (_byteSize) {
194 case SerialPort::BS_8NO : // 8Bit, No parity
195 config.c_iflag &= ~INPCK; // enable input parity check
196 config.c_cflag &= ~(CSIZE | PARENB);
197 config.c_cflag |= CS8;
198 break;
199 case SerialPort::BS_7EVEN : // 7Bit, Even parity
200 config.c_iflag |= INPCK;
201 config.c_cflag &= ~(CSIZE | PARODD);
202 config.c_cflag |= CS7 | PARENB;
203 break;
204 case SerialPort::BS_7ODD : // 7Bit, Odd parity
205 config.c_iflag |= INPCK;
206 config.c_cflag &= ~CSIZE;
207 config.c_cflag |= CS7 | PARENB | PARODD;
208 break;
209 default :
210 __DCL_ASSERT(false);
211 }
212
213 cfsetispeed(&config, _baudRate);
214 cfsetospeed(&config, _baudRate);
215
216 config.c_cc[VMIN] = 1;
217 config.c_cc[VTIME] = 5; // 5/10 초
218
219 if (tcsetattr(__handle, TCSANOW, &config))
220 throw new IOException(toString(), errno);
221
222 // success
223#endif
224}
225
226void SerialPort::purge(int _flags)
228{
230 __DCL_ASSERT_PARAM(1 <= _flags && _flags <= 3);
231
232#if __DCL_WINDOWS
233 if (!PurgeComm(__handle,
234 (_flags & PURGE_RX ? PURGE_RXABORT | PURGE_RXCLEAR : 0)
235 | (_flags & PURGE_TX ? PURGE_TXABORT | PURGE_TXCLEAR : 0)))
236 throw new IOException(toString(), GetLastError());
237
238#else
239 if (tcflush(__handle, --_flags))
240 throw new IOException(toString(), errno);
241
242#endif
243}
244
245bool SerialPort::access(const String& _path)
246{
247#if __DCL_WINDOWS
248 SECURITY_ATTRIBUTES securityAttributes = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
249 HANDLE handle = CreateFileW(
250 _path, // __in LPCTSTR lpFileName,
251 GENERIC_READ | GENERIC_WRITE, // __in DWORD dwDesiredAccess,
252 0, // __in DWORD dwShareMode,
253 &securityAttributes, // __in LPSECURITY_ATTRIBUTES lpSecurityAttributes,
254 OPEN_EXISTING, // __in DWORD dwCreationDisposition,
255 0, // __in DWORD dwFlagsAndAttributes,
256 NULL // __in HANDLE hTemplateFile
257 );
259 CloseHandle(handle);
260 return true;
261 }
262 return false;
263
264#else
265 return __access(_path, R_OK | W_OK);
266
267#endif
268}
269
270bool SerialPort::onEvent(short _events, PollThread* _pPollThread)
272{
273 return true;
274}
275
276#if __DCL_WINDOWS
277// used only SerialPollThread
278bool SerialPort::waitCommEvent()
279{
280 __DCL_ASSERT(__overlapped.hEvent != NULL);
281
282 __overlapped.Internal = 0;
283 __overlapped.InternalHigh = 0;
284 __overlapped.Offset = 0;
285 __overlapped.OffsetHigh = 0;
286
287 // VS 2008의 디버깅 추적에서 이 문장이 지나고 나면 메모리 문제를 보고한다.
288 // 여기서 리턴을 해도 여전히 문제가 있는 것으로 추정된다.
289 // 2011-04-26
290 if (::WaitCommEvent(handle(), &__revents, &__overlapped)) {
291 SetEvent(__overlapped.hEvent);
292 return true;
293 }
294
295 if (GetLastError() == ERROR_IO_PENDING)
296 return true;
297
298 __DCL_TRACE1(__T("WaitCommEvent: %d\n"), GetLastError());
299 return false;
300}
301#endif
302
303__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
DCLCAPI int __access(const String &_path, int _type)
Definition _unistd.cpp:22
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS1(e)
Definition Config.h:167
#define INVALID_HANDLE_VALUE
Definition Dir.cpp:31
#define TRUE
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:384
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:383
virtual void destroy()
Definition Exception.cpp:74
HandleType handle() const
Definition File.h:242
void open(const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
Definition File.cpp:77
friend class PollThread
Definition PollAble.h:38
virtual bool onEvent(short _revents, PollThread *_pPollThread) __DCL_THROWS1(IOException *)
static bool access(const String &_path)