]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // impl/serial_port_base.ipp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
b32b8144 | 5 | // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) |
7 | // | |
8 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
9 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
10 | // | |
11 | ||
12 | #ifndef BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP | |
13 | #define BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP | |
14 | ||
15 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
16 | # pragma once | |
17 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
18 | ||
19 | #include <boost/asio/detail/config.hpp> | |
20 | ||
21 | #if defined(BOOST_ASIO_HAS_SERIAL_PORT) | |
22 | ||
23 | #include <stdexcept> | |
24 | #include <boost/asio/error.hpp> | |
25 | #include <boost/asio/serial_port_base.hpp> | |
26 | #include <boost/asio/detail/throw_exception.hpp> | |
27 | ||
28 | #if defined(GENERATING_DOCUMENTATION) | |
29 | # define BOOST_ASIO_OPTION_STORAGE implementation_defined | |
30 | #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
31 | # define BOOST_ASIO_OPTION_STORAGE DCB | |
32 | #else | |
33 | # define BOOST_ASIO_OPTION_STORAGE termios | |
34 | #endif | |
35 | ||
36 | #include <boost/asio/detail/push_options.hpp> | |
37 | ||
38 | namespace boost { | |
39 | namespace asio { | |
40 | ||
b32b8144 | 41 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::baud_rate::store( |
7c673cae FG |
42 | BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const |
43 | { | |
44 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
45 | storage.BaudRate = value_; | |
46 | #else | |
47 | speed_t baud; | |
48 | switch (value_) | |
49 | { | |
50 | // Do POSIX-specified rates first. | |
51 | case 0: baud = B0; break; | |
52 | case 50: baud = B50; break; | |
53 | case 75: baud = B75; break; | |
54 | case 110: baud = B110; break; | |
55 | case 134: baud = B134; break; | |
56 | case 150: baud = B150; break; | |
57 | case 200: baud = B200; break; | |
58 | case 300: baud = B300; break; | |
59 | case 600: baud = B600; break; | |
60 | case 1200: baud = B1200; break; | |
61 | case 1800: baud = B1800; break; | |
62 | case 2400: baud = B2400; break; | |
63 | case 4800: baud = B4800; break; | |
64 | case 9600: baud = B9600; break; | |
65 | case 19200: baud = B19200; break; | |
66 | case 38400: baud = B38400; break; | |
67 | // And now the extended ones conditionally. | |
68 | # ifdef B7200 | |
69 | case 7200: baud = B7200; break; | |
70 | # endif | |
71 | # ifdef B14400 | |
72 | case 14400: baud = B14400; break; | |
73 | # endif | |
74 | # ifdef B57600 | |
75 | case 57600: baud = B57600; break; | |
76 | # endif | |
77 | # ifdef B115200 | |
78 | case 115200: baud = B115200; break; | |
79 | # endif | |
80 | # ifdef B230400 | |
81 | case 230400: baud = B230400; break; | |
82 | # endif | |
83 | # ifdef B460800 | |
84 | case 460800: baud = B460800; break; | |
85 | # endif | |
86 | # ifdef B500000 | |
87 | case 500000: baud = B500000; break; | |
88 | # endif | |
89 | # ifdef B576000 | |
90 | case 576000: baud = B576000; break; | |
91 | # endif | |
92 | # ifdef B921600 | |
93 | case 921600: baud = B921600; break; | |
94 | # endif | |
95 | # ifdef B1000000 | |
96 | case 1000000: baud = B1000000; break; | |
97 | # endif | |
98 | # ifdef B1152000 | |
99 | case 1152000: baud = B1152000; break; | |
100 | # endif | |
101 | # ifdef B2000000 | |
102 | case 2000000: baud = B2000000; break; | |
103 | # endif | |
104 | # ifdef B3000000 | |
105 | case 3000000: baud = B3000000; break; | |
106 | # endif | |
107 | # ifdef B3500000 | |
108 | case 3500000: baud = B3500000; break; | |
109 | # endif | |
110 | # ifdef B4000000 | |
111 | case 4000000: baud = B4000000; break; | |
112 | # endif | |
113 | default: | |
114 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 115 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae | 116 | } |
b32b8144 | 117 | # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) |
7c673cae FG |
118 | ::cfsetspeed(&storage, baud); |
119 | # else | |
120 | ::cfsetispeed(&storage, baud); | |
121 | ::cfsetospeed(&storage, baud); | |
122 | # endif | |
123 | #endif | |
124 | ec = boost::system::error_code(); | |
b32b8144 | 125 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
126 | } |
127 | ||
b32b8144 | 128 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::baud_rate::load( |
7c673cae FG |
129 | const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) |
130 | { | |
131 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
132 | value_ = storage.BaudRate; | |
133 | #else | |
134 | speed_t baud = ::cfgetospeed(&storage); | |
135 | switch (baud) | |
136 | { | |
137 | // First do those specified by POSIX. | |
138 | case B0: value_ = 0; break; | |
139 | case B50: value_ = 50; break; | |
140 | case B75: value_ = 75; break; | |
141 | case B110: value_ = 110; break; | |
142 | case B134: value_ = 134; break; | |
143 | case B150: value_ = 150; break; | |
144 | case B200: value_ = 200; break; | |
145 | case B300: value_ = 300; break; | |
146 | case B600: value_ = 600; break; | |
147 | case B1200: value_ = 1200; break; | |
148 | case B1800: value_ = 1800; break; | |
149 | case B2400: value_ = 2400; break; | |
150 | case B4800: value_ = 4800; break; | |
151 | case B9600: value_ = 9600; break; | |
152 | case B19200: value_ = 19200; break; | |
153 | case B38400: value_ = 38400; break; | |
154 | // Now conditionally handle a bunch of extended rates. | |
155 | # ifdef B7200 | |
156 | case B7200: value_ = 7200; break; | |
157 | # endif | |
158 | # ifdef B14400 | |
159 | case B14400: value_ = 14400; break; | |
160 | # endif | |
161 | # ifdef B57600 | |
162 | case B57600: value_ = 57600; break; | |
163 | # endif | |
164 | # ifdef B115200 | |
165 | case B115200: value_ = 115200; break; | |
166 | # endif | |
167 | # ifdef B230400 | |
168 | case B230400: value_ = 230400; break; | |
169 | # endif | |
170 | # ifdef B460800 | |
171 | case B460800: value_ = 460800; break; | |
172 | # endif | |
173 | # ifdef B500000 | |
174 | case B500000: value_ = 500000; break; | |
175 | # endif | |
176 | # ifdef B576000 | |
177 | case B576000: value_ = 576000; break; | |
178 | # endif | |
179 | # ifdef B921600 | |
180 | case B921600: value_ = 921600; break; | |
181 | # endif | |
182 | # ifdef B1000000 | |
183 | case B1000000: value_ = 1000000; break; | |
184 | # endif | |
185 | # ifdef B1152000 | |
186 | case B1152000: value_ = 1152000; break; | |
187 | # endif | |
188 | # ifdef B2000000 | |
189 | case B2000000: value_ = 2000000; break; | |
190 | # endif | |
191 | # ifdef B3000000 | |
192 | case B3000000: value_ = 3000000; break; | |
193 | # endif | |
194 | # ifdef B3500000 | |
195 | case B3500000: value_ = 3500000; break; | |
196 | # endif | |
197 | # ifdef B4000000 | |
198 | case B4000000: value_ = 4000000; break; | |
199 | # endif | |
200 | default: | |
201 | value_ = 0; | |
202 | ec = boost::asio::error::invalid_argument; | |
b32b8144 | 203 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
204 | } |
205 | #endif | |
206 | ec = boost::system::error_code(); | |
b32b8144 | 207 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
208 | } |
209 | ||
210 | serial_port_base::flow_control::flow_control( | |
211 | serial_port_base::flow_control::type t) | |
212 | : value_(t) | |
213 | { | |
214 | if (t != none && t != software && t != hardware) | |
215 | { | |
216 | std::out_of_range ex("invalid flow_control value"); | |
217 | boost::asio::detail::throw_exception(ex); | |
218 | } | |
219 | } | |
220 | ||
b32b8144 | 221 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::flow_control::store( |
7c673cae FG |
222 | BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const |
223 | { | |
224 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
225 | storage.fOutxCtsFlow = FALSE; | |
226 | storage.fOutxDsrFlow = FALSE; | |
227 | storage.fTXContinueOnXoff = TRUE; | |
228 | storage.fDtrControl = DTR_CONTROL_ENABLE; | |
229 | storage.fDsrSensitivity = FALSE; | |
230 | storage.fOutX = FALSE; | |
231 | storage.fInX = FALSE; | |
232 | storage.fRtsControl = RTS_CONTROL_ENABLE; | |
233 | switch (value_) | |
234 | { | |
235 | case none: | |
236 | break; | |
237 | case software: | |
238 | storage.fOutX = TRUE; | |
239 | storage.fInX = TRUE; | |
240 | break; | |
241 | case hardware: | |
242 | storage.fOutxCtsFlow = TRUE; | |
243 | storage.fRtsControl = RTS_CONTROL_HANDSHAKE; | |
244 | break; | |
245 | default: | |
246 | break; | |
247 | } | |
248 | #else | |
249 | switch (value_) | |
250 | { | |
251 | case none: | |
252 | storage.c_iflag &= ~(IXOFF | IXON); | |
b32b8144 | 253 | # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) |
7c673cae FG |
254 | storage.c_cflag &= ~CRTSCTS; |
255 | # elif defined(__QNXNTO__) | |
256 | storage.c_cflag &= ~(IHFLOW | OHFLOW); | |
257 | # endif | |
258 | break; | |
259 | case software: | |
260 | storage.c_iflag |= IXOFF | IXON; | |
b32b8144 | 261 | # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) |
7c673cae FG |
262 | storage.c_cflag &= ~CRTSCTS; |
263 | # elif defined(__QNXNTO__) | |
264 | storage.c_cflag &= ~(IHFLOW | OHFLOW); | |
265 | # endif | |
266 | break; | |
267 | case hardware: | |
b32b8144 | 268 | # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) |
7c673cae FG |
269 | storage.c_iflag &= ~(IXOFF | IXON); |
270 | storage.c_cflag |= CRTSCTS; | |
271 | break; | |
272 | # elif defined(__QNXNTO__) | |
273 | storage.c_iflag &= ~(IXOFF | IXON); | |
274 | storage.c_cflag |= (IHFLOW | OHFLOW); | |
275 | break; | |
276 | # else | |
277 | ec = boost::asio::error::operation_not_supported; | |
b32b8144 | 278 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
279 | # endif |
280 | default: | |
281 | break; | |
282 | } | |
283 | #endif | |
284 | ec = boost::system::error_code(); | |
b32b8144 | 285 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
286 | } |
287 | ||
b32b8144 | 288 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::flow_control::load( |
7c673cae FG |
289 | const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) |
290 | { | |
291 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
292 | if (storage.fOutX && storage.fInX) | |
293 | { | |
294 | value_ = software; | |
295 | } | |
296 | else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE) | |
297 | { | |
298 | value_ = hardware; | |
299 | } | |
300 | else | |
301 | { | |
302 | value_ = none; | |
303 | } | |
304 | #else | |
305 | if (storage.c_iflag & (IXOFF | IXON)) | |
306 | { | |
307 | value_ = software; | |
308 | } | |
b32b8144 | 309 | # if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) |
7c673cae FG |
310 | else if (storage.c_cflag & CRTSCTS) |
311 | { | |
312 | value_ = hardware; | |
313 | } | |
314 | # elif defined(__QNXNTO__) | |
315 | else if (storage.c_cflag & IHFLOW && storage.c_cflag & OHFLOW) | |
316 | { | |
317 | value_ = hardware; | |
318 | } | |
319 | # endif | |
320 | else | |
321 | { | |
322 | value_ = none; | |
323 | } | |
324 | #endif | |
325 | ec = boost::system::error_code(); | |
b32b8144 | 326 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
327 | } |
328 | ||
329 | serial_port_base::parity::parity(serial_port_base::parity::type t) | |
330 | : value_(t) | |
331 | { | |
332 | if (t != none && t != odd && t != even) | |
333 | { | |
334 | std::out_of_range ex("invalid parity value"); | |
335 | boost::asio::detail::throw_exception(ex); | |
336 | } | |
337 | } | |
338 | ||
b32b8144 | 339 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::parity::store( |
7c673cae FG |
340 | BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const |
341 | { | |
342 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
343 | switch (value_) | |
344 | { | |
345 | case none: | |
346 | storage.fParity = FALSE; | |
347 | storage.Parity = NOPARITY; | |
348 | break; | |
349 | case odd: | |
350 | storage.fParity = TRUE; | |
351 | storage.Parity = ODDPARITY; | |
352 | break; | |
353 | case even: | |
354 | storage.fParity = TRUE; | |
355 | storage.Parity = EVENPARITY; | |
356 | break; | |
357 | default: | |
358 | break; | |
359 | } | |
360 | #else | |
361 | switch (value_) | |
362 | { | |
363 | case none: | |
364 | storage.c_iflag |= IGNPAR; | |
365 | storage.c_cflag &= ~(PARENB | PARODD); | |
366 | break; | |
367 | case even: | |
368 | storage.c_iflag &= ~(IGNPAR | PARMRK); | |
369 | storage.c_iflag |= INPCK; | |
370 | storage.c_cflag |= PARENB; | |
371 | storage.c_cflag &= ~PARODD; | |
372 | break; | |
373 | case odd: | |
374 | storage.c_iflag &= ~(IGNPAR | PARMRK); | |
375 | storage.c_iflag |= INPCK; | |
376 | storage.c_cflag |= (PARENB | PARODD); | |
377 | break; | |
378 | default: | |
379 | break; | |
380 | } | |
381 | #endif | |
382 | ec = boost::system::error_code(); | |
b32b8144 | 383 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
384 | } |
385 | ||
b32b8144 | 386 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::parity::load( |
7c673cae FG |
387 | const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) |
388 | { | |
389 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
390 | if (storage.Parity == EVENPARITY) | |
391 | { | |
392 | value_ = even; | |
393 | } | |
394 | else if (storage.Parity == ODDPARITY) | |
395 | { | |
396 | value_ = odd; | |
397 | } | |
398 | else | |
399 | { | |
400 | value_ = none; | |
401 | } | |
402 | #else | |
403 | if (storage.c_cflag & PARENB) | |
404 | { | |
405 | if (storage.c_cflag & PARODD) | |
406 | { | |
407 | value_ = odd; | |
408 | } | |
409 | else | |
410 | { | |
411 | value_ = even; | |
412 | } | |
413 | } | |
414 | else | |
415 | { | |
416 | value_ = none; | |
417 | } | |
418 | #endif | |
419 | ec = boost::system::error_code(); | |
b32b8144 | 420 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
421 | } |
422 | ||
423 | serial_port_base::stop_bits::stop_bits( | |
424 | serial_port_base::stop_bits::type t) | |
425 | : value_(t) | |
426 | { | |
427 | if (t != one && t != onepointfive && t != two) | |
428 | { | |
429 | std::out_of_range ex("invalid stop_bits value"); | |
430 | boost::asio::detail::throw_exception(ex); | |
431 | } | |
432 | } | |
433 | ||
b32b8144 | 434 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::stop_bits::store( |
7c673cae FG |
435 | BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const |
436 | { | |
437 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
438 | switch (value_) | |
439 | { | |
440 | case one: | |
441 | storage.StopBits = ONESTOPBIT; | |
442 | break; | |
443 | case onepointfive: | |
444 | storage.StopBits = ONE5STOPBITS; | |
445 | break; | |
446 | case two: | |
447 | storage.StopBits = TWOSTOPBITS; | |
448 | break; | |
449 | default: | |
450 | break; | |
451 | } | |
452 | #else | |
453 | switch (value_) | |
454 | { | |
455 | case one: | |
456 | storage.c_cflag &= ~CSTOPB; | |
457 | break; | |
458 | case two: | |
459 | storage.c_cflag |= CSTOPB; | |
460 | break; | |
461 | default: | |
462 | ec = boost::asio::error::operation_not_supported; | |
b32b8144 | 463 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
464 | } |
465 | #endif | |
466 | ec = boost::system::error_code(); | |
b32b8144 | 467 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
468 | } |
469 | ||
b32b8144 | 470 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::stop_bits::load( |
7c673cae FG |
471 | const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) |
472 | { | |
473 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
474 | if (storage.StopBits == ONESTOPBIT) | |
475 | { | |
476 | value_ = one; | |
477 | } | |
478 | else if (storage.StopBits == ONE5STOPBITS) | |
479 | { | |
480 | value_ = onepointfive; | |
481 | } | |
482 | else if (storage.StopBits == TWOSTOPBITS) | |
483 | { | |
484 | value_ = two; | |
485 | } | |
486 | else | |
487 | { | |
488 | value_ = one; | |
489 | } | |
490 | #else | |
491 | value_ = (storage.c_cflag & CSTOPB) ? two : one; | |
492 | #endif | |
493 | ec = boost::system::error_code(); | |
b32b8144 | 494 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
495 | } |
496 | ||
497 | serial_port_base::character_size::character_size(unsigned int t) | |
498 | : value_(t) | |
499 | { | |
500 | if (t < 5 || t > 8) | |
501 | { | |
502 | std::out_of_range ex("invalid character_size value"); | |
503 | boost::asio::detail::throw_exception(ex); | |
504 | } | |
505 | } | |
506 | ||
b32b8144 | 507 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::character_size::store( |
7c673cae FG |
508 | BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const |
509 | { | |
510 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
511 | storage.ByteSize = value_; | |
512 | #else | |
513 | storage.c_cflag &= ~CSIZE; | |
514 | switch (value_) | |
515 | { | |
516 | case 5: storage.c_cflag |= CS5; break; | |
517 | case 6: storage.c_cflag |= CS6; break; | |
518 | case 7: storage.c_cflag |= CS7; break; | |
519 | case 8: storage.c_cflag |= CS8; break; | |
520 | default: break; | |
521 | } | |
522 | #endif | |
523 | ec = boost::system::error_code(); | |
b32b8144 | 524 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
525 | } |
526 | ||
b32b8144 | 527 | BOOST_ASIO_SYNC_OP_VOID serial_port_base::character_size::load( |
7c673cae FG |
528 | const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) |
529 | { | |
530 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
531 | value_ = storage.ByteSize; | |
532 | #else | |
533 | if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; } | |
534 | else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; } | |
535 | else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; } | |
536 | else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; } | |
537 | else | |
538 | { | |
539 | // Hmmm, use 8 for now. | |
540 | value_ = 8; | |
541 | } | |
542 | #endif | |
543 | ec = boost::system::error_code(); | |
b32b8144 | 544 | BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); |
7c673cae FG |
545 | } |
546 | ||
547 | } // namespace asio | |
548 | } // namespace boost | |
549 | ||
550 | #include <boost/asio/detail/pop_options.hpp> | |
551 | ||
552 | #undef BOOST_ASIO_OPTION_STORAGE | |
553 | ||
554 | #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) | |
555 | ||
556 | #endif // BOOST_ASIO_IMPL_SERIAL_PORT_BASE_IPP |