serial_port_base.ipp 12 KB

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