DCL 3.7.4
Loading...
Searching...
No Matches
SerialPort.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#ifdef __WINNT__
4 #include <windows.h>
5#else
6 #include <dcl/_unistd.h>
7#endif
8
9#include <dcl/SerialPort.h>
10
11#if __DCL_HAVE_THIS_FILE__
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#ifdef __WINNT__
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#ifdef __WINNT__
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#ifdef __WINNT__
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#ifdef __WINNT__
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 case FC_NONE:
138 ;
139 }
140
141 if (!SetCommState(__handle, &dcb))
142 throw new IOException(toString(), GetLastError());
143 // success
144#else
145 /*
146 Ref erence
147 - Serial Programming Guide for POSIX Operation Systems.
148 http://www.easysw.com/~mike/serial/serial.html
149 - http://en.wikibooks.org/wiki/Serial_Programming/termios
150 - man termiso(3)
151 - 리눅스에서 시리얼통신(II).
152 http://www.lug.or.kr/docs/LINUX/others/00-05-5.htm
153 */
154
155 struct termios config;
156 if (tcgetattr(__handle, &config))
157 throw new IOException(toString(), errno);
158
159 // Raw mode , man 3 termios
160 config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
161 | INLCR | IGNCR | ICRNL | IXON);
162 config.c_oflag &= ~OPOST;
163 config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
164
165 config.c_cflag |= CLOCAL | CREAD;
166
167 // Flow Control
168#ifdef CRTSCTS // not in POSIX
169 config.c_cflag &= ~CRTSCTS;
170#endif
171 config.c_iflag &= ~(IXON | IXOFF | IXANY);
172 switch (_flowControl) {
173 case SerialPort::FC_NONE :
174 break;
175 case SerialPort::FC_RTSCTS :
176#ifdef CRTSCTS
177 config.c_cflag |= CRTSCTS;
178#endif
179 break;
180 case SerialPort::FC_XONXOFF :
181 config.c_iflag |= IXON | IXOFF;
182 break;
183 default :
184 __DCL_ASSERT(false);
185 }
186
187 // Stop Bits
188 if (_stopBits == SerialPort::SB_1)
189 config.c_cflag &= ~CSTOPB;
190 else
191 config.c_cflag |= CSTOPB;
192
193 // Byte Size
194 switch (_byteSize) {
195 case SerialPort::BS_8NO : // 8Bit, No parity
196 config.c_iflag &= ~INPCK; // enable input parity check
197 config.c_cflag &= ~(CSIZE | PARENB);
198 config.c_cflag |= CS8;
199 break;
200 case SerialPort::BS_7EVEN : // 7Bit, Even parity
201 config.c_iflag |= INPCK;
202 config.c_cflag &= ~(CSIZE | PARODD);
203 config.c_cflag |= CS7 | PARENB;
204 break;
205 case SerialPort::BS_7ODD : // 7Bit, Odd parity
206 config.c_iflag |= INPCK;
207 config.c_cflag &= ~CSIZE;
208 config.c_cflag |= CS7 | PARENB | PARODD;
209 break;
210 default :
211 __DCL_ASSERT(false);
212 }
213
214 cfsetispeed(&config, _baudRate);
215 cfsetospeed(&config, _baudRate);
216
217 config.c_cc[VMIN] = 1;
218 config.c_cc[VTIME] = 5; // 5/10 초
219
220 if (tcsetattr(__handle, TCSANOW, &config))
221 throw new IOException(toString(), errno);
222
223 // success
224#endif
225}
226
227void SerialPort::purge(int _flags)
229{
231 __DCL_ASSERT_PARAM(1 <= _flags && _flags <= 3);
232
233#ifdef __WINNT__
234 if (!PurgeComm(__handle,
235 (_flags & PURGE_RX ? PURGE_RXABORT | PURGE_RXCLEAR : 0)
236 | (_flags & PURGE_TX ? PURGE_TXABORT | PURGE_TXCLEAR : 0)))
237 throw new IOException(toString(), GetLastError());
238
239#else
240 if (tcflush(__handle, --_flags))
241 throw new IOException(toString(), errno);
242
243#endif
244}
245
246bool SerialPort::access(const String& _path)
247{
248#ifdef __WINNT__
249 SECURITY_ATTRIBUTES securityAttributes = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
250 HANDLE handle = CreateFileW(
251 _path, // __in LPCTSTR lpFileName,
252 GENERIC_READ | GENERIC_WRITE, // __in DWORD dwDesiredAccess,
253 0, // __in DWORD dwShareMode,
254 &securityAttributes, // __in LPSECURITY_ATTRIBUTES lpSecurityAttributes,
255 OPEN_EXISTING, // __in DWORD dwCreationDisposition,
256 0, // __in DWORD dwFlagsAndAttributes,
257 NULL // __in HANDLE hTemplateFile
258 );
260 CloseHandle(handle);
261 return true;
262 }
263 return false;
264
265#else
266 return __access(_path, R_OK | W_OK);
267
268#endif
269}
270
271bool SerialPort::onEvent(short _events, PollThread* _pPollThread)
273{
274 return true;
275}
276
277#ifdef __WINNT__
278// used only SerialPollThread
279bool SerialPort::waitCommEvent()
280{
281 __DCL_ASSERT(__overlapped.hEvent != NULL);
282
283 __overlapped.Internal = 0;
284 __overlapped.InternalHigh = 0;
285 __overlapped.Offset = 0;
286 __overlapped.OffsetHigh = 0;
287
288 // VS 2008의 디버깅 추적에서 이 문장이 지나고 나면 메모리 문제를 보고한다.
289 // 여기서 리턴을 해도 여전히 문제가 있는 것으로 추정된다.
290 // 2011-04-26
291 if (::WaitCommEvent(handle(), &__revents, &__overlapped)) {
292 SetEvent(__overlapped.hEvent);
293 return true;
294 }
295
296 if (GetLastError() == ERROR_IO_PENDING)
297 return true;
298
299 __DCL_TRACE1(__T("WaitCommEvent: %d\n"), GetLastError());
300 return false;
301}
302#endif
303
304__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
DCLCAPI int __access(const String &_path, int _type)
Definition _unistd.cpp:25
#define NULL
Definition Config.h:312
wchar_t char_t
Definition Config.h:247
#define __DCL_THROWS1(e)
Definition Config.h:152
#define INVALID_HANDLE_VALUE
Definition Dir.cpp:34
#define TRUE
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:399
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:409
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:245
#define __T(str)
Definition Object.h:60
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:408
virtual void destroy()
Definition Exception.cpp:74
HandleType handle() const
Definition File.h:246
void open(const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
Definition File.cpp:80
friend class PollThread
Definition PollAble.h:38
virtual bool onEvent(short _revents, PollThread *_pPollThread) __DCL_THROWS1(IOException *)
static bool access(const String &_path)