├── LICENSE ├── README.md ├── serialport.cpp └── serialport.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Youcef Kouchkar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wxSerialPort 2 | a wxWidgets cross platform Serial Port library 3 | -------------------------------------------------------------------------------- /serialport.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // Name: serialport.cpp 3 | // Purpose: Code for wxSerialPort Class 4 | // Author: Youcef Kouchkar 5 | // Created: 2018-01-08 6 | // Copyright: (c) 2019 Youcef Kouchkar 7 | // License: MIT License 8 | //////////////////////////////////////////////////////////////////////////////// 9 | 10 | #ifdef WX_PRECOMP 11 | #include "wx_pch.h" 12 | #endif 13 | 14 | #ifdef __BORLANDC__ 15 | #pragma hdrstop 16 | #endif //__BORLANDC__ 17 | 18 | #include "serialport.h" 19 | //#include 20 | #include 21 | //#include 22 | 23 | #ifdef __WXMSW__ 24 | #include 25 | #endif // __WXMSW__ 26 | 27 | wxSerialPortBase::wxSerialPortBase() : m_io_context() 28 | { 29 | // Ctor 30 | //Init(); 31 | } 32 | 33 | wxSerialPortBase::~wxSerialPortBase() 34 | { 35 | // Dtor 36 | //m_io_context.~io_context(); 37 | } 38 | 39 | std::vector wxSerialPortBase::GetPortNames() 40 | { 41 | std::vector vStrPortNames; 42 | #ifdef __WXMSW__ 43 | wxRegKey regKey(wxRegKey::HKLM, wxS("HARDWARE\\DEVICEMAP\\SERIALCOMM")); 44 | 45 | if (!regKey.Exists()) 46 | return vStrPortNames; 47 | 48 | wxASSERT(regKey.Exists()); 49 | 50 | wxString strValueName; 51 | long lIndex; 52 | 53 | // Enumerate all values 54 | bool bCont = regKey.GetFirstValue(strValueName, lIndex); 55 | 56 | while (bCont) 57 | { 58 | wxRegKey::ValueType valueType = regKey.GetValueType(strValueName); 59 | 60 | if ((valueType == wxRegKey::Type_String || valueType == wxRegKey::Type_Expand_String || 61 | valueType == wxRegKey::Type_Multi_String) && !strValueName.empty()) 62 | { 63 | wxString strValueData; 64 | regKey.QueryValue(strValueName, strValueData); 65 | vStrPortNames.push_back(strValueData); 66 | } 67 | 68 | bCont = regKey.GetNextValue(strValueName, lIndex); 69 | } 70 | #else // !__WXMSW__ 71 | wxArrayString arrStrFiles; 72 | wxDir::GetAllFiles(wxS("/dev/"), &arrStrFiles, wxS("ttyS*"), wxDIR_FILES); 73 | 74 | for (wxArrayString::const_iterator it = arrStrFiles.begin(); it != arrStrFiles.end(); ++it) 75 | vStrPortNames.push_back(*it); 76 | #endif // __WXMSW__ 77 | 78 | return vStrPortNames; 79 | } 80 | 81 | wxSerialPort::wxSerialPort() : m_serialPort(m_io_context), m_timer(m_io_context) 82 | { 83 | // Default ctor 84 | Init(); 85 | //m_strPortName = wxEmptyString; 86 | } 87 | 88 | wxSerialPort::wxSerialPort(const char *device) 89 | : m_serialPort(m_io_context, device), m_timer(m_io_context), m_strPortName(device) 90 | { 91 | // Ctor 92 | Init(); 93 | } 94 | 95 | wxSerialPort::wxSerialPort(const std::string& device) 96 | : m_serialPort(m_io_context, device), m_timer(m_io_context), m_strPortName(device) 97 | { 98 | // Ctor 99 | Init(); 100 | } 101 | 102 | wxSerialPort::wxSerialPort(const wxString& device) 103 | : m_serialPort(m_io_context, device), m_timer(m_io_context), m_strPortName(device) 104 | { 105 | // Ctor 106 | Init(); 107 | } 108 | 109 | wxSerialPort::wxSerialPort(const boost::asio::serial_port::native_handle_type& native_serial_port) 110 | : m_serialPort(m_io_context, native_serial_port), m_timer(m_io_context) 111 | { 112 | // Ctor 113 | Init(); 114 | //m_strPortName = wxEmptyString; 115 | } 116 | 117 | // Copy constructor 118 | wxSerialPort::wxSerialPort(const wxSerialPort& other) 119 | /*: m_serialPort(other.m_serialPort)*/ : m_serialPort(m_io_context) /*, m_timer(other.m_timer)*/, m_timer(m_io_context), 120 | m_strPortName(other.m_strPortName) 121 | { 122 | // Copy ctor 123 | Init(); 124 | } 125 | 126 | // Copy assignment operator 127 | wxSerialPort& wxSerialPort::operator=(const wxSerialPort& other) 128 | { 129 | //m_serialPort = other.m_serialPort; 130 | //m_timer = other.m_timer; 131 | m_strPortName = other.m_strPortName; 132 | //Init(); 133 | return *this; 134 | } 135 | 136 | #ifdef BOOST_ASIO_HAS_MOVE 137 | // Move constructor 138 | wxSerialPort::wxSerialPort(wxSerialPort&& other) 139 | : m_serialPort(std::move(other.m_serialPort)), m_timer(std::move(other.m_timer)), 140 | m_strPortName(/*std::move(*/other.m_strPortName/*)*/) //, m_bytes_read(/*std::move(*/other.m_bytes_read/*)*/), 141 | //m_bytes_written(/*std::move(*/other.m_bytes_written/*)*/) 142 | { 143 | // Move ctor 144 | } 145 | 146 | // Move assignment operator 147 | wxSerialPort& wxSerialPort::operator=(wxSerialPort&& other) 148 | { 149 | m_serialPort = std::move(other.m_serialPort); 150 | m_timer = std::move(other.m_timer); 151 | m_strPortName = /*std::move(*/other.m_strPortName/*)*/; 152 | //m_bytes_read = /*std::move(*/other.m_bytes_read/*)*/; 153 | //m_bytes_written = /*std::move(*/other.m_bytes_written/*)*/; 154 | return *this; 155 | } 156 | #endif // BOOST_ASIO_HAS_MOVE 157 | 158 | wxSerialPort::~wxSerialPort() 159 | { 160 | // Dtor 161 | m_serialPort.close(); 162 | //m_serialPort.~serial_port(); 163 | } 164 | 165 | boost::asio::serial_port& wxSerialPort::GetSerialPort() /*const*/ 166 | { 167 | return m_serialPort; 168 | } 169 | 170 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Assign(const boost::asio::serial_port::native_handle_type& native_serial_port) 171 | { 172 | boost::system::error_code error; 173 | m_serialPort.assign(native_serial_port, error); 174 | DoSetLastError(error); 175 | return error; 176 | } 177 | 178 | // =============================================================================================================================== 179 | 180 | // ------------------------------------------------------------------------------------------------------------------------------- 181 | // ReadSome 182 | // ------------------------------------------------------------------------------------------------------------------------------- 183 | 184 | // This helper function is intended for internal use by the class itself 185 | std::size_t wxSerialPort::DoReadSome(const boost::asio::mutable_buffer& buffer) 186 | { 187 | boost::system::error_code error; 188 | std::size_t ret = m_serialPort.read_some(buffer, error); 189 | DoSetLastError(error); 190 | return ret; 191 | } 192 | 193 | std::size_t wxSerialPort::ReadSome(std::string& strBuffer) 194 | { 195 | return DoReadSome(boost::asio::buffer(strBuffer)); 196 | } 197 | 198 | std::size_t wxSerialPort::ReadSome(wxCharBuffer& chBuffer) 199 | { 200 | return DoReadSome(boost::asio::buffer(chBuffer.data(), chBuffer.length())); 201 | } 202 | 203 | std::size_t wxSerialPort::ReadSome(void *pszBuffer, const std::size_t uiSize) 204 | { 205 | return DoReadSome(boost::asio::buffer(pszBuffer, uiSize)); 206 | } 207 | 208 | template 209 | std::size_t wxSerialPort::ReadSome(std::vector& vBuffer) 210 | { 211 | return DoReadSome(boost::asio::buffer(vBuffer)); 212 | } 213 | 214 | template 215 | std::size_t wxSerialPort::ReadSome(std::array& arrBuffer) 216 | { 217 | return DoReadSome(boost::asio::buffer(arrBuffer)); 218 | } 219 | 220 | // ------------------------------------------------------------------------------------------------------------------------------- 221 | // ReadSome with timeout 222 | // ------------------------------------------------------------------------------------------------------------------------------- 223 | 224 | // This helper function is intended for internal use by the class itself 225 | std::size_t wxSerialPort::DoReadSome(const boost::asio::mutable_buffer& buffer, const int timeout) 226 | { 227 | std::size_t bytes_read = 0; 228 | m_io_context.restart(); 229 | DoAsyncWaitThenCancelAsyncIO(timeout); 230 | 231 | m_serialPort.async_read_some(buffer, 232 | /*std::bind(&wxSerialPort::AsyncReadHandler, this, std::placeholders::_1, std::placeholders::_2)*/ 233 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) 234 | { 235 | // Read operation was not aborted 236 | if (!error) // != boost::asio::error::operation_aborted 237 | m_timer.cancel(); 238 | 239 | bytes_read = bytes_transferred; 240 | DoSetLastError(error); 241 | }); 242 | 243 | std::thread thread1([this] { m_io_context.run(); }); 244 | thread1.join(); 245 | return bytes_read; 246 | } 247 | 248 | std::size_t wxSerialPort::ReadSome(std::string& strBuffer, const int timeout) 249 | { 250 | return DoReadSome(boost::asio::buffer(strBuffer), timeout); 251 | } 252 | 253 | std::size_t wxSerialPort::ReadSome(wxCharBuffer& chBuffer, const int timeout) 254 | { 255 | return DoReadSome(boost::asio::buffer(chBuffer.data(), chBuffer.length()), timeout); 256 | } 257 | 258 | std::size_t wxSerialPort::ReadSome(void *pszBuffer, const std::size_t uiSize, const int timeout) 259 | { 260 | return DoReadSome(boost::asio::buffer(pszBuffer, uiSize), timeout); 261 | } 262 | 263 | template 264 | std::size_t wxSerialPort::ReadSome(std::vector& vBuffer, const int timeout) 265 | { 266 | return DoReadSome(boost::asio::buffer(vBuffer), timeout); 267 | } 268 | 269 | template 270 | std::size_t wxSerialPort::ReadSome(std::array& arrBuffer, const int timeout) 271 | { 272 | return DoReadSome(boost::asio::buffer(arrBuffer), timeout); 273 | } 274 | 275 | // ------------------------------------------------------------------------------------------------------------------------------- 276 | // WriteSome 277 | // ------------------------------------------------------------------------------------------------------------------------------- 278 | 279 | // This helper function is intended for internal use by the class itself 280 | std::size_t wxSerialPort::DoWriteSome(const boost::asio::const_buffer& buffer) 281 | { 282 | boost::system::error_code error; 283 | std::size_t ret = m_serialPort.write_some(buffer, error); 284 | DoSetLastError(error); 285 | return ret; 286 | } 287 | 288 | std::size_t wxSerialPort::WriteSome(const std::string& strBuffer) 289 | { 290 | return DoWriteSome(boost::asio::buffer(strBuffer)); 291 | } 292 | 293 | std::size_t wxSerialPort::WriteSome(const wxString& strBuffer) 294 | { 295 | return DoWriteSome(boost::asio::buffer(strBuffer.data(), strBuffer.size())); 296 | } 297 | 298 | std::size_t wxSerialPort::WriteSome(const wxCharBuffer& chBuffer) 299 | { 300 | return DoWriteSome(boost::asio::buffer(chBuffer.data(), chBuffer.length())); 301 | } 302 | 303 | std::size_t wxSerialPort::WriteSome(const void *pszBuffer, const std::size_t uiSize) 304 | { 305 | return DoWriteSome(boost::asio::buffer(pszBuffer, uiSize)); 306 | } 307 | 308 | template 309 | std::size_t wxSerialPort::WriteSome(const std::vector& vBuffer) 310 | { 311 | return DoWriteSome(boost::asio::buffer(vBuffer)); 312 | } 313 | 314 | template 315 | std::size_t wxSerialPort::WriteSome(const std::array& arrBuffer) 316 | { 317 | return DoWriteSome(boost::asio::buffer(arrBuffer)); 318 | } 319 | 320 | // ------------------------------------------------------------------------------------------------------------------------------- 321 | // WriteSome with timeout 322 | // ------------------------------------------------------------------------------------------------------------------------------- 323 | 324 | // This helper function is intended for internal use by the class itself 325 | std::size_t wxSerialPort::DoWriteSome(const boost::asio::const_buffer& buffer, const int timeout) 326 | { 327 | std::size_t bytes_written = 0; 328 | m_io_context.restart(); 329 | DoAsyncWaitThenCancelAsyncIO(timeout); 330 | 331 | m_serialPort.async_write_some(buffer, 332 | /*std::bind(&wxSerialPort::AsyncWriteHandler, this, std::placeholders::_1, std::placeholders::_2)*/ 333 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) 334 | { 335 | // Write operation was not aborted 336 | if (!error) // != boost::asio::error::operation_aborted 337 | m_timer.cancel(); 338 | 339 | bytes_written = bytes_transferred; 340 | DoSetLastError(error); 341 | }); 342 | 343 | std::thread thread1([this] { m_io_context.run(); }); 344 | thread1.join(); 345 | return bytes_written; 346 | } 347 | 348 | std::size_t wxSerialPort::WriteSome(const std::string& strBuffer, const int timeout) 349 | { 350 | return DoWriteSome(boost::asio::buffer(strBuffer), timeout); 351 | } 352 | 353 | std::size_t wxSerialPort::WriteSome(const wxString& strBuffer, const int timeout) 354 | { 355 | return DoWriteSome(boost::asio::buffer(strBuffer.data(), strBuffer.size()), timeout); 356 | } 357 | 358 | std::size_t wxSerialPort::WriteSome(const wxCharBuffer& chBuffer, const int timeout) 359 | { 360 | return DoWriteSome(boost::asio::buffer(chBuffer.data(), chBuffer.length()), timeout); 361 | } 362 | 363 | std::size_t wxSerialPort::WriteSome(const void *pszBuffer, const std::size_t uiSize, const int timeout) 364 | { 365 | return DoWriteSome(boost::asio::buffer(pszBuffer, uiSize), timeout); 366 | } 367 | 368 | template 369 | std::size_t wxSerialPort::WriteSome(const std::vector& vBuffer, const int timeout) 370 | { 371 | return DoWriteSome(boost::asio::buffer(vBuffer), timeout); 372 | } 373 | 374 | template 375 | std::size_t wxSerialPort::WriteSome(const std::array& arrBuffer, const int timeout) 376 | { 377 | return DoWriteSome(boost::asio::buffer(arrBuffer), timeout); 378 | } 379 | 380 | // =============================================================================================================================== 381 | 382 | // ------------------------------------------------------------------------------------------------------------------------------- 383 | // AsyncReadSome 384 | // ------------------------------------------------------------------------------------------------------------------------------- 385 | 386 | // This helper function is intended for internal use by the class itself 387 | template 388 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 389 | wxSerialPort::DoAsyncReadSome(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 390 | { 391 | return m_serialPort.async_read_some(buffer, handler); 392 | } 393 | 394 | template 395 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 396 | wxSerialPort::AsyncReadSome(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 397 | { 398 | return DoAsyncReadSome(boost::asio::buffer(strBuffer), handler); 399 | } 400 | 401 | template 402 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 403 | wxSerialPort::AsyncReadSome(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 404 | { 405 | return DoAsyncReadSome(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler); 406 | } 407 | 408 | template 409 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 410 | wxSerialPort::AsyncReadSome(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 411 | { 412 | return DoAsyncReadSome(boost::asio::buffer(pszBuffer, uiSize), handler); 413 | } 414 | 415 | template 416 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 417 | wxSerialPort::AsyncReadSome(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 418 | { 419 | return DoAsyncReadSome(boost::asio::buffer(vBuffer), handler); 420 | } 421 | 422 | template 423 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 424 | wxSerialPort::AsyncReadSome(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 425 | { 426 | return DoAsyncReadSome(boost::asio::buffer(arrBuffer), handler); 427 | } 428 | 429 | // ------------------------------------------------------------------------------------------------------------------------------- 430 | // AsyncReadSome with timeout 431 | // ------------------------------------------------------------------------------------------------------------------------------- 432 | 433 | // This helper function is intended for internal use by the class itself 434 | template 435 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 436 | wxSerialPort::DoAsyncReadSome(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 437 | { 438 | DoAsyncWaitThenCancelAsyncIO(timeout); 439 | return m_serialPort.async_read_some(buffer, handler); 440 | } 441 | 442 | template 443 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 444 | wxSerialPort::AsyncReadSome(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 445 | { 446 | return DoAsyncReadSome(boost::asio::buffer(strBuffer), handler, timeout); 447 | } 448 | 449 | template 450 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 451 | wxSerialPort::AsyncReadSome(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 452 | { 453 | return DoAsyncReadSome(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler, timeout); 454 | } 455 | 456 | template 457 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 458 | wxSerialPort::AsyncReadSome(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 459 | { 460 | return DoAsyncReadSome(boost::asio::buffer(pszBuffer, uiSize), handler, timeout); 461 | } 462 | 463 | template 464 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 465 | wxSerialPort::AsyncReadSome(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 466 | { 467 | return DoAsyncReadSome(boost::asio::buffer(vBuffer), handler, timeout); 468 | } 469 | 470 | template 471 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 472 | wxSerialPort::AsyncReadSome(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 473 | { 474 | return DoAsyncReadSome(boost::asio::buffer(arrBuffer), handler, timeout); 475 | } 476 | 477 | // ------------------------------------------------------------------------------------------------------------------------------- 478 | // AsyncWriteSome 479 | // ------------------------------------------------------------------------------------------------------------------------------- 480 | 481 | // This helper function is intended for internal use by the class itself 482 | template 483 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 484 | wxSerialPort::DoAsyncWriteSome(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 485 | { 486 | return m_serialPort.async_write_some(buffer, handler); 487 | } 488 | 489 | template 490 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 491 | wxSerialPort::AsyncWriteSome(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 492 | { 493 | return DoWriteSome(boost::asio::buffer(strBuffer), handler); 494 | } 495 | 496 | template 497 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 498 | wxSerialPort::AsyncWriteSome(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 499 | { 500 | return DoWriteSome(boost::asio::buffer(strBuffer.data(), strBuffer.size()), handler); 501 | } 502 | 503 | template 504 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 505 | wxSerialPort::AsyncWriteSome(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 506 | { 507 | return DoWriteSome(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler); 508 | } 509 | 510 | template 511 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 512 | wxSerialPort::AsyncWriteSome(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 513 | { 514 | return DoWriteSome(boost::asio::buffer(pszBuffer, uiSize), handler); 515 | } 516 | 517 | template 518 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 519 | wxSerialPort::AsyncWriteSome(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 520 | { 521 | return DoWriteSome(boost::asio::buffer(vBuffer), handler); 522 | } 523 | 524 | template 525 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 526 | wxSerialPort::AsyncWriteSome(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 527 | { 528 | return DoWriteSome(boost::asio::buffer(arrBuffer), handler); 529 | } 530 | 531 | // ------------------------------------------------------------------------------------------------------------------------------- 532 | // AsyncWriteSome with timeout 533 | // ------------------------------------------------------------------------------------------------------------------------------- 534 | 535 | // This helper function is intended for internal use by the class itself 536 | template 537 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 538 | wxSerialPort::DoAsyncWriteSome(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 539 | { 540 | DoAsyncWaitThenCancelAsyncIO(timeout); 541 | return m_serialPort.async_write_some(buffer, handler); 542 | } 543 | 544 | template 545 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 546 | wxSerialPort::AsyncWriteSome(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 547 | { 548 | return DoWriteSome(boost::asio::buffer(strBuffer), handler, timeout); 549 | } 550 | 551 | template 552 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 553 | wxSerialPort::AsyncWriteSome(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 554 | { 555 | return DoWriteSome(boost::asio::buffer(strBuffer.data(), strBuffer.size()), handler, timeout); 556 | } 557 | 558 | template 559 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 560 | wxSerialPort::AsyncWriteSome(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 561 | { 562 | return DoWriteSome(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler, timeout); 563 | } 564 | 565 | template 566 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 567 | wxSerialPort::AsyncWriteSome(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 568 | { 569 | return DoWriteSome(boost::asio::buffer(pszBuffer, uiSize), handler, timeout); 570 | } 571 | 572 | template 573 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 574 | wxSerialPort::AsyncWriteSome(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 575 | { 576 | return DoWriteSome(boost::asio::buffer(vBuffer), handler, timeout); 577 | } 578 | 579 | template 580 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 581 | wxSerialPort::AsyncWriteSome(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 582 | { 583 | return DoWriteSome(boost::asio::buffer(arrBuffer), handler, timeout); 584 | } 585 | 586 | // =============================================================================================================================== 587 | 588 | // ------------------------------------------------------------------------------------------------------------------------------- 589 | // Read 590 | // ------------------------------------------------------------------------------------------------------------------------------- 591 | 592 | // This helper function is intended for internal use by the class itself 593 | std::size_t wxSerialPort::DoRead(const boost::asio::mutable_buffer& buffer) 594 | { 595 | boost::system::error_code error; 596 | std::size_t ret = boost::asio::read(m_serialPort, buffer, error); 597 | DoSetLastError(error); 598 | return ret; 599 | } 600 | 601 | std::size_t wxSerialPort::Read(std::string& strBuffer) 602 | { 603 | return DoRead(boost::asio::buffer(strBuffer)); 604 | } 605 | 606 | std::size_t wxSerialPort::Read(wxCharBuffer& chBuffer) 607 | { 608 | return DoRead(boost::asio::buffer(chBuffer.data(), chBuffer.length())); 609 | } 610 | 611 | std::size_t wxSerialPort::Read(void *pszBuffer, const std::size_t uiSize) 612 | { 613 | return DoRead(boost::asio::buffer(pszBuffer, uiSize)); 614 | } 615 | 616 | template 617 | std::size_t wxSerialPort::Read(std::vector& vBuffer) 618 | { 619 | return DoRead(boost::asio::buffer(vBuffer)); 620 | } 621 | 622 | template 623 | std::size_t wxSerialPort::Read(std::array& arrBuffer) 624 | { 625 | return DoRead(boost::asio::buffer(arrBuffer)); 626 | } 627 | 628 | // ------------------------------------------------------------------------------------------------------------------------------- 629 | // Read with timeout 630 | // ------------------------------------------------------------------------------------------------------------------------------- 631 | 632 | // This helper function is intended for internal use by the class itself 633 | std::size_t wxSerialPort::DoRead(const boost::asio::mutable_buffer& buffer, const int timeout) 634 | { 635 | std::size_t bytes_read = 0; 636 | m_io_context.restart(); 637 | DoAsyncWaitThenCancelAsyncIO(timeout); 638 | 639 | boost::asio::async_read(m_serialPort, buffer, 640 | /*std::bind(&wxSerialPort::AsyncReadHandler, this, std::placeholders::_1, std::placeholders::_2)*/ 641 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) 642 | { 643 | // Read operation was not aborted 644 | if (!error) // != boost::asio::error::operation_aborted 645 | m_timer.cancel(); 646 | 647 | bytes_read = bytes_transferred; 648 | DoSetLastError(error); 649 | }); 650 | 651 | std::thread thread1([this] { m_io_context.run(); }); 652 | thread1.join(); 653 | return bytes_read; 654 | } 655 | 656 | std::size_t wxSerialPort::Read(std::string& strBuffer, const int timeout) 657 | { 658 | return DoRead(boost::asio::buffer(strBuffer), timeout); 659 | } 660 | 661 | std::size_t wxSerialPort::Read(wxCharBuffer& chBuffer, const int timeout) 662 | { 663 | return DoRead(boost::asio::buffer(chBuffer.data(), chBuffer.length()), timeout); 664 | } 665 | 666 | std::size_t wxSerialPort::Read(void *pszBuffer, const std::size_t uiSize, const int timeout) 667 | { 668 | return DoRead(boost::asio::buffer(pszBuffer, uiSize), timeout); 669 | } 670 | 671 | template 672 | std::size_t wxSerialPort::Read(std::vector& vBuffer, const int timeout) 673 | { 674 | return DoRead(boost::asio::buffer(vBuffer), timeout); 675 | } 676 | 677 | template 678 | std::size_t wxSerialPort::Read(std::array& arrBuffer, const int timeout) 679 | { 680 | return DoRead(boost::asio::buffer(arrBuffer), timeout); 681 | } 682 | 683 | // ------------------------------------------------------------------------------------------------------------------------------- 684 | // Write 685 | // ------------------------------------------------------------------------------------------------------------------------------- 686 | 687 | // This helper function is intended for internal use by the class itself 688 | std::size_t wxSerialPort::DoWrite(const boost::asio::const_buffer& buffer) 689 | { 690 | boost::system::error_code error; 691 | std::size_t ret = boost::asio::write(m_serialPort, buffer, error); 692 | DoSetLastError(error); 693 | return ret; 694 | } 695 | 696 | std::size_t wxSerialPort::Write(const std::string& strBuffer) 697 | { 698 | return DoWrite(boost::asio::buffer(strBuffer)); 699 | } 700 | 701 | std::size_t wxSerialPort::Write(const wxString& strBuffer) 702 | { 703 | return DoWrite(boost::asio::buffer(strBuffer.data(), strBuffer.size())); 704 | } 705 | 706 | std::size_t wxSerialPort::Write(const wxCharBuffer& chBuffer) 707 | { 708 | return DoWrite(boost::asio::buffer(chBuffer.data(), chBuffer.length())); 709 | } 710 | 711 | std::size_t wxSerialPort::Write(const void *pszBuffer, const std::size_t uiSize) 712 | { 713 | return DoWrite(boost::asio::buffer(pszBuffer, uiSize)); 714 | } 715 | 716 | template 717 | std::size_t wxSerialPort::Write(const std::vector& vBuffer) 718 | { 719 | return DoWrite(boost::asio::buffer(vBuffer)); 720 | } 721 | 722 | template 723 | std::size_t wxSerialPort::Write(const std::array& arrBuffer) 724 | { 725 | return DoWrite(boost::asio::buffer(arrBuffer)); 726 | } 727 | 728 | // ------------------------------------------------------------------------------------------------------------------------------- 729 | // Write with timeout 730 | // ------------------------------------------------------------------------------------------------------------------------------- 731 | 732 | // This helper function is intended for internal use by the class itself 733 | std::size_t wxSerialPort::DoWrite(const boost::asio::const_buffer& buffer, const int timeout) 734 | { 735 | std::size_t bytes_written = 0; 736 | m_io_context.restart(); 737 | DoAsyncWaitThenCancelAsyncIO(timeout); 738 | 739 | boost::asio::async_write(m_serialPort, buffer, 740 | /*std::bind(&wxSerialPort::AsyncWriteHandler, this, std::placeholders::_1, std::placeholders::_2)*/ 741 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) 742 | { 743 | // Write operation was not aborted 744 | if (!error) // != boost::asio::error::operation_aborted 745 | m_timer.cancel(); 746 | 747 | bytes_written = bytes_transferred; 748 | DoSetLastError(error); 749 | }); 750 | 751 | std::thread thread1([this] { m_io_context.run(); }); 752 | thread1.join(); 753 | return bytes_written; 754 | } 755 | 756 | std::size_t wxSerialPort::Write(const std::string& strBuffer, const int timeout) 757 | { 758 | return DoWrite(boost::asio::buffer(strBuffer), timeout); 759 | } 760 | 761 | std::size_t wxSerialPort::Write(const wxString& strBuffer, const int timeout) 762 | { 763 | return DoWrite(boost::asio::buffer(strBuffer.data(), strBuffer.size()), timeout); 764 | } 765 | 766 | std::size_t wxSerialPort::Write(const wxCharBuffer& chBuffer, const int timeout) 767 | { 768 | return DoWrite(boost::asio::buffer(chBuffer.data(), chBuffer.length()), timeout); 769 | } 770 | 771 | std::size_t wxSerialPort::Write(const void *pszBuffer, const std::size_t uiSize, const int timeout) 772 | { 773 | return DoWrite(boost::asio::buffer(pszBuffer, uiSize), timeout); 774 | } 775 | 776 | template 777 | std::size_t wxSerialPort::Write(const std::vector& vBuffer, const int timeout) 778 | { 779 | return DoWrite(boost::asio::buffer(vBuffer), timeout); 780 | } 781 | 782 | template 783 | std::size_t wxSerialPort::Write(const std::array& arrBuffer, const int timeout) 784 | { 785 | return DoWrite(boost::asio::buffer(arrBuffer), timeout); 786 | } 787 | 788 | // =============================================================================================================================== 789 | 790 | // ------------------------------------------------------------------------------------------------------------------------------- 791 | // AsyncRead 792 | // ------------------------------------------------------------------------------------------------------------------------------- 793 | 794 | // This helper function is intended for internal use by the class itself 795 | template 796 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 797 | wxSerialPort::DoAsyncRead(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 798 | { 799 | return boost::asio::async_read(m_serialPort, buffer, handler); 800 | } 801 | 802 | template 803 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 804 | wxSerialPort::AsyncRead(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 805 | { 806 | return DoAsyncRead(boost::asio::buffer(strBuffer), handler); 807 | } 808 | 809 | template 810 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 811 | wxSerialPort::AsyncRead(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 812 | { 813 | return DoAsyncRead(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler); 814 | } 815 | 816 | template 817 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 818 | wxSerialPort::AsyncRead(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 819 | { 820 | return DoAsyncRead(boost::asio::buffer(pszBuffer, uiSize), handler); 821 | } 822 | 823 | template 824 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 825 | wxSerialPort::AsyncRead(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 826 | { 827 | return DoAsyncRead(boost::asio::buffer(vBuffer), handler); 828 | } 829 | 830 | template 831 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 832 | wxSerialPort::AsyncRead(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 833 | { 834 | return DoAsyncRead(boost::asio::buffer(arrBuffer), handler); 835 | } 836 | 837 | // ------------------------------------------------------------------------------------------------------------------------------- 838 | // AsyncRead with timeout 839 | // ------------------------------------------------------------------------------------------------------------------------------- 840 | 841 | // This helper function is intended for internal use by the class itself 842 | template 843 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 844 | wxSerialPort::DoAsyncRead(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 845 | { 846 | DoAsyncWaitThenCancelAsyncIO(timeout); 847 | return boost::asio::async_read(m_serialPort, buffer, handler); 848 | } 849 | 850 | template 851 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 852 | wxSerialPort::AsyncRead(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 853 | { 854 | return DoAsyncRead(boost::asio::buffer(strBuffer), handler, timeout); 855 | } 856 | 857 | template 858 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 859 | wxSerialPort::AsyncRead(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 860 | { 861 | return DoAsyncRead(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler, timeout); 862 | } 863 | 864 | template 865 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 866 | wxSerialPort::AsyncRead(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 867 | { 868 | return DoAsyncRead(boost::asio::buffer(pszBuffer, uiSize), handler, timeout); 869 | } 870 | 871 | template 872 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 873 | wxSerialPort::AsyncRead(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 874 | { 875 | return DoAsyncRead(boost::asio::buffer(vBuffer), handler, timeout); 876 | } 877 | 878 | template 879 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 880 | wxSerialPort::AsyncRead(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout) 881 | { 882 | return DoAsyncRead(boost::asio::buffer(arrBuffer), handler, timeout); 883 | } 884 | 885 | // ------------------------------------------------------------------------------------------------------------------------------- 886 | // AsyncWrite 887 | // ------------------------------------------------------------------------------------------------------------------------------- 888 | 889 | // This helper function is intended for internal use by the class itself 890 | template 891 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 892 | wxSerialPort::DoAsyncWrite(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 893 | { 894 | return boost::asio::async_write(m_serialPort, buffer, handler); 895 | } 896 | 897 | template 898 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 899 | wxSerialPort::AsyncWrite(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 900 | { 901 | return DoWrite(boost::asio::buffer(strBuffer), handler); 902 | } 903 | 904 | template 905 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 906 | wxSerialPort::AsyncWrite(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 907 | { 908 | return DoWrite(boost::asio::buffer(strBuffer.data(), strBuffer.size()), handler); 909 | } 910 | 911 | template 912 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 913 | wxSerialPort::AsyncWrite(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 914 | { 915 | return DoWrite(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler); 916 | } 917 | 918 | template 919 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 920 | wxSerialPort::AsyncWrite(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 921 | { 922 | return DoWrite(boost::asio::buffer(pszBuffer, uiSize), handler); 923 | } 924 | 925 | template 926 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 927 | wxSerialPort::AsyncWrite(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 928 | { 929 | return DoWrite(boost::asio::buffer(vBuffer), handler); 930 | } 931 | 932 | template 933 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 934 | wxSerialPort::AsyncWrite(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 935 | { 936 | return DoWrite(boost::asio::buffer(arrBuffer), handler); 937 | } 938 | 939 | // ------------------------------------------------------------------------------------------------------------------------------- 940 | // AsyncWrite with timeout 941 | // ------------------------------------------------------------------------------------------------------------------------------- 942 | 943 | // This helper function is intended for internal use by the class itself 944 | template 945 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 946 | wxSerialPort::DoAsyncWrite(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 947 | { 948 | DoAsyncWaitThenCancelAsyncIO(timeout); 949 | return boost::asio::async_write(m_serialPort, buffer, handler); 950 | } 951 | 952 | template 953 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 954 | wxSerialPort::AsyncWrite(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 955 | { 956 | return DoWrite(boost::asio::buffer(strBuffer), handler, timeout); 957 | } 958 | 959 | template 960 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 961 | wxSerialPort::AsyncWrite(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 962 | { 963 | return DoWrite(boost::asio::buffer(strBuffer.data(), strBuffer.size()), handler, timeout); 964 | } 965 | 966 | template 967 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 968 | wxSerialPort::AsyncWrite(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 969 | { 970 | return DoWrite(boost::asio::buffer(chBuffer.data(), chBuffer.length()), handler, timeout); 971 | } 972 | 973 | template 974 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 975 | wxSerialPort::AsyncWrite(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 976 | { 977 | return DoWrite(boost::asio::buffer(pszBuffer, uiSize), handler, timeout); 978 | } 979 | 980 | template 981 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 982 | wxSerialPort::AsyncWrite(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 983 | { 984 | return DoWrite(boost::asio::buffer(vBuffer), handler, timeout); 985 | } 986 | 987 | template 988 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 989 | wxSerialPort::AsyncWrite(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout) 990 | { 991 | return DoWrite(boost::asio::buffer(arrBuffer), handler, timeout); 992 | } 993 | 994 | // =============================================================================================================================== 995 | 996 | // ------------------------------------------------------------------------------------------------------------------------------- 997 | // ReadUntil 998 | // ------------------------------------------------------------------------------------------------------------------------------- 999 | 1000 | // This helper function is intended for internal use by the class itself 1001 | std::size_t wxSerialPort::DoReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim) 1002 | { 1003 | boost::system::error_code error; 1004 | std::size_t ret = boost::asio::read(m_serialPort, buffer, 1005 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) -> std::size_t 1006 | { 1007 | return DoCompletionCondition(buffer, delim, error, bytes_transferred); 1008 | }, error); 1009 | DoSetLastError(error); 1010 | return ret; 1011 | } 1012 | 1013 | std::size_t wxSerialPort::ReadUntil(std::string& strBuffer, const std::string& strDelim) 1014 | { 1015 | return DoReadUntil(boost::asio::buffer(strBuffer), boost::asio::buffer(strDelim)); 1016 | } 1017 | 1018 | std::size_t wxSerialPort::ReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim) 1019 | { 1020 | return DoReadUntil(boost::asio::buffer(chBuffer.data(), chBuffer.length()), boost::asio::buffer(chDelim.data(), chDelim.length())); 1021 | } 1022 | 1023 | std::size_t wxSerialPort::ReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2) 1024 | { 1025 | return DoReadUntil(boost::asio::buffer(pszBuffer, uiSize1), boost::asio::buffer(pszDelim, uiSize2)); 1026 | } 1027 | 1028 | template 1029 | std::size_t wxSerialPort::ReadUntil(std::vector& vBuffer, const std::vector& vDelim) 1030 | { 1031 | return DoReadUntil(boost::asio::buffer(vBuffer), boost::asio::buffer(vDelim)); 1032 | } 1033 | 1034 | template 1035 | std::size_t wxSerialPort::ReadUntil(std::array& arrBuffer, const std::array& arrDelim) 1036 | { 1037 | return DoReadUntil(boost::asio::buffer(arrBuffer), boost::asio::buffer(arrDelim)); 1038 | } 1039 | 1040 | // ------------------------------------------------------------------------------------------------------------------------------- 1041 | // ReadUntil with timeout 1042 | // ------------------------------------------------------------------------------------------------------------------------------- 1043 | 1044 | // This helper function is intended for internal use by the class itself 1045 | std::size_t wxSerialPort::DoReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, const int timeout) 1046 | { 1047 | std::size_t bytes_read = 0; 1048 | m_io_context.restart(); 1049 | DoAsyncWaitThenCancelAsyncIO(timeout); 1050 | 1051 | boost::asio::async_read(m_serialPort, buffer, 1052 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) -> std::size_t 1053 | { 1054 | return DoCompletionCondition(buffer, delim, error, bytes_transferred); 1055 | }, 1056 | /*std::bind(&wxSerialPort::AsyncReadUntilHandler, this, std::placeholders::_1, std::placeholders::_2)*/ 1057 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) 1058 | { 1059 | // ReadUntil operation was not aborted 1060 | if (!error) // != boost::asio::error::operation_aborted 1061 | m_timer.cancel(); 1062 | 1063 | bytes_read = bytes_transferred; 1064 | DoSetLastError(error); 1065 | }); 1066 | 1067 | std::thread thread1([this] { m_io_context.run(); }); 1068 | thread1.join(); 1069 | return bytes_read; 1070 | } 1071 | 1072 | std::size_t wxSerialPort::ReadUntil(std::string& strBuffer, const std::string& strDelim, const int timeout) 1073 | { 1074 | return DoReadUntil(boost::asio::buffer(strBuffer), boost::asio::buffer(strDelim), timeout); 1075 | } 1076 | 1077 | std::size_t wxSerialPort::ReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim, const int timeout) 1078 | { 1079 | return DoReadUntil(boost::asio::buffer(chBuffer.data(), chBuffer.length()), boost::asio::buffer(chDelim.data(), chDelim.length()), timeout); 1080 | } 1081 | 1082 | std::size_t wxSerialPort::ReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2, const int timeout) 1083 | { 1084 | return DoReadUntil(boost::asio::buffer(pszBuffer, uiSize1), boost::asio::buffer(pszDelim, uiSize2), timeout); 1085 | } 1086 | 1087 | template 1088 | std::size_t wxSerialPort::ReadUntil(std::vector& vBuffer, const std::vector& vDelim, const int timeout) 1089 | { 1090 | return DoReadUntil(boost::asio::buffer(vBuffer), boost::asio::buffer(vDelim), timeout); 1091 | } 1092 | 1093 | template 1094 | std::size_t wxSerialPort::ReadUntil(std::array& arrBuffer, const std::array& arrDelim, const int timeout) 1095 | { 1096 | return DoReadUntil(boost::asio::buffer(arrBuffer), boost::asio::buffer(arrDelim), timeout); 1097 | } 1098 | 1099 | // =============================================================================================================================== 1100 | 1101 | // ------------------------------------------------------------------------------------------------------------------------------- 1102 | // AsyncReadUntil 1103 | // ------------------------------------------------------------------------------------------------------------------------------- 1104 | 1105 | // This helper function is intended for internal use by the class itself 1106 | template 1107 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1108 | wxSerialPort::DoAsyncReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler) 1109 | { 1110 | return boost::asio::async_read(m_serialPort, buffer, 1111 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) -> std::size_t 1112 | { 1113 | return DoCompletionCondition(buffer, delim, error, bytes_transferred); 1114 | }, handler); 1115 | } 1116 | 1117 | template 1118 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1119 | wxSerialPort::AsyncReadUntil(std::string& strBuffer, const std::string& strDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler) 1120 | { 1121 | return DoAsyncReadUntil(boost::asio::buffer(strBuffer), boost::asio::buffer(strDelim), handler); 1122 | } 1123 | 1124 | template 1125 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1126 | wxSerialPort::AsyncReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler) 1127 | { 1128 | return DoAsyncReadUntil(boost::asio::buffer(chBuffer.data(), chBuffer.length()), boost::asio::buffer(chDelim.data(), chDelim.length()), handler); 1129 | } 1130 | 1131 | template 1132 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1133 | wxSerialPort::AsyncReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler) 1134 | { 1135 | return DoAsyncReadUntil(boost::asio::buffer(pszBuffer, uiSize1), boost::asio::buffer(pszDelim, uiSize2), handler); 1136 | } 1137 | 1138 | template 1139 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1140 | wxSerialPort::AsyncReadUntil(std::vector& vBuffer, const std::vector& vDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler) 1141 | { 1142 | return DoAsyncReadUntil(boost::asio::buffer(vBuffer), boost::asio::buffer(vDelim), handler); 1143 | } 1144 | 1145 | template 1146 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1147 | wxSerialPort::AsyncReadUntil(std::array& arrBuffer, const std::array& arrDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler) 1148 | { 1149 | return DoAsyncReadUntil(boost::asio::buffer(arrBuffer), boost::asio::buffer(arrDelim), handler); 1150 | } 1151 | 1152 | // ------------------------------------------------------------------------------------------------------------------------------- 1153 | // AsyncReadUntil with timeout 1154 | // ------------------------------------------------------------------------------------------------------------------------------- 1155 | 1156 | // This helper function is intended for internal use by the class itself 1157 | template 1158 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1159 | wxSerialPort::DoAsyncReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout) 1160 | { 1161 | DoAsyncWaitThenCancelAsyncIO(timeout); 1162 | return boost::asio::async_read(m_serialPort, buffer, 1163 | [&](const boost::system::error_code& error, std::size_t bytes_transferred) -> std::size_t 1164 | { 1165 | return DoCompletionCondition(buffer, delim, error, bytes_transferred); 1166 | }, handler); 1167 | } 1168 | 1169 | template 1170 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1171 | wxSerialPort::AsyncReadUntil(std::string& strBuffer, const std::string& strDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout) 1172 | { 1173 | return DoAsyncReadUntil(boost::asio::buffer(strBuffer), boost::asio::buffer(strDelim), handler, timeout); 1174 | } 1175 | 1176 | template 1177 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1178 | wxSerialPort::AsyncReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout) 1179 | { 1180 | return DoAsyncReadUntil(boost::asio::buffer(chBuffer.data(), chBuffer.length()), boost::asio::buffer(chDelim.data(), chDelim.length()), handler, timeout); 1181 | } 1182 | 1183 | template 1184 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1185 | wxSerialPort::AsyncReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout) 1186 | { 1187 | return DoAsyncReadUntil(boost::asio::buffer(pszBuffer, uiSize1), boost::asio::buffer(pszDelim, uiSize2), handler, timeout); 1188 | } 1189 | 1190 | template 1191 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1192 | wxSerialPort::AsyncReadUntil(std::vector& vBuffer, const std::vector& vDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout) 1193 | { 1194 | return DoAsyncReadUntil(boost::asio::buffer(vBuffer), boost::asio::buffer(vDelim), handler, timeout); 1195 | } 1196 | 1197 | template 1198 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 1199 | wxSerialPort::AsyncReadUntil(std::array& arrBuffer, const std::array& arrDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout) 1200 | { 1201 | return DoAsyncReadUntil(boost::asio::buffer(arrBuffer), boost::asio::buffer(arrDelim), handler, timeout); 1202 | } 1203 | 1204 | // =============================================================================================================================== 1205 | 1206 | // This helper function is intended for internal use by the class itself 1207 | std::size_t wxSerialPort::DoCompletionCondition(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, 1208 | const boost::system::error_code& error, const std::size_t bytes_transferred) const 1209 | { 1210 | // Look for a match 1211 | auto it = std::search(boost::asio::buffers_begin(buffer), boost::asio::buffers_begin(buffer) + bytes_transferred, 1212 | boost::asio::buffers_begin(delim), boost::asio::buffers_end(delim)); 1213 | 1214 | return (!!error || it != (boost::asio::buffers_begin(buffer) + bytes_transferred)) ? 0 1215 | : boost::asio::detail::default_max_transfer_size_t::default_max_transfer_size; 1216 | } 1217 | 1218 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Cancel() 1219 | { 1220 | boost::system::error_code error; 1221 | m_serialPort.cancel(error); 1222 | DoSetLastError(error); 1223 | return error; 1224 | } 1225 | 1226 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Close() 1227 | { 1228 | boost::system::error_code error; 1229 | m_serialPort.close(error); 1230 | DoSetLastError(error); 1231 | return error; 1232 | } 1233 | 1234 | boost::asio::serial_port::executor_type wxSerialPort::GetExecutor() BOOST_ASIO_NOEXCEPT 1235 | { 1236 | return m_serialPort.get_executor(); 1237 | } 1238 | 1239 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetOption(BaudRate& option) 1240 | { 1241 | boost::asio::serial_port_base::baud_rate baudrate; 1242 | boost::system::error_code error; 1243 | m_serialPort.get_option(baudrate, error); 1244 | option = static_cast(baudrate.value()); 1245 | DoSetLastError(error); 1246 | return error; 1247 | } 1248 | 1249 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetOption(DataBits& option) 1250 | { 1251 | boost::asio::serial_port_base::character_size databits; 1252 | boost::system::error_code error; 1253 | m_serialPort.get_option(databits, error); 1254 | option = static_cast(databits.value()); 1255 | DoSetLastError(error); 1256 | return error; 1257 | } 1258 | 1259 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetOption(FlowControl& option) 1260 | { 1261 | boost::asio::serial_port_base::flow_control flowcontrol; 1262 | boost::system::error_code error; 1263 | m_serialPort.get_option(flowcontrol, error); 1264 | option = static_cast(flowcontrol.value()); 1265 | DoSetLastError(error); 1266 | return error; 1267 | } 1268 | 1269 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetOption(Parity& option) 1270 | { 1271 | boost::asio::serial_port_base::parity parity; 1272 | boost::system::error_code error; 1273 | m_serialPort.get_option(parity, error); 1274 | option = static_cast(parity.value()); 1275 | DoSetLastError(error); 1276 | return error; 1277 | } 1278 | 1279 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetOption(StopBits& option) 1280 | { 1281 | boost::asio::serial_port_base::stop_bits stopbits; 1282 | boost::system::error_code error; 1283 | m_serialPort.get_option(stopbits, error); 1284 | option = static_cast(stopbits.value()); 1285 | DoSetLastError(error); 1286 | return error; 1287 | } 1288 | 1289 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetOption(const BaudRate option) 1290 | { 1291 | boost::asio::serial_port_base::baud_rate baudrate(option); 1292 | 1293 | boost::system::error_code error; 1294 | m_serialPort.set_option(baudrate, error); 1295 | DoSetLastError(error); 1296 | return error; 1297 | } 1298 | 1299 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetOption(const DataBits option) 1300 | { 1301 | boost::asio::serial_port_base::character_size databits(option); 1302 | 1303 | boost::system::error_code error; 1304 | m_serialPort.set_option(databits, error); 1305 | DoSetLastError(error); 1306 | return error; 1307 | } 1308 | 1309 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetOption(const FlowControl option) 1310 | { 1311 | boost::asio::serial_port_base::flow_control flowcontrol(static_cast(option)); 1312 | 1313 | boost::system::error_code error; 1314 | m_serialPort.set_option(flowcontrol, error); 1315 | DoSetLastError(error); 1316 | return error; 1317 | } 1318 | 1319 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetOption(const Parity option) 1320 | { 1321 | boost::asio::serial_port_base::parity parity(static_cast(option)); 1322 | 1323 | boost::system::error_code error; 1324 | m_serialPort.set_option(parity, error); 1325 | DoSetLastError(error); 1326 | return error; 1327 | } 1328 | 1329 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetOption(const StopBits option) 1330 | { 1331 | boost::asio::serial_port_base::stop_bits stopbits(static_cast(option)); 1332 | 1333 | boost::system::error_code error; 1334 | m_serialPort.set_option(stopbits, error); 1335 | DoSetLastError(error); 1336 | return error; 1337 | } 1338 | 1339 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetBaudRate(BaudRate& baudrate) 1340 | { 1341 | return GetOption(baudrate); 1342 | } 1343 | 1344 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetDataBits(DataBits& databits) 1345 | { 1346 | return GetOption(databits); 1347 | } 1348 | 1349 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetFlowControl(FlowControl& flowcontrol) 1350 | { 1351 | return GetOption(flowcontrol); 1352 | } 1353 | 1354 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetParity(Parity& parity) 1355 | { 1356 | return GetOption(parity); 1357 | } 1358 | 1359 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::GetStopBits(StopBits& stopbits) 1360 | { 1361 | return GetOption(stopbits); 1362 | } 1363 | 1364 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetBaudRate(const BaudRate baudrate) 1365 | { 1366 | return SetOption(baudrate); 1367 | } 1368 | 1369 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetDataBits(const DataBits databits) 1370 | { 1371 | return SetOption(databits); 1372 | } 1373 | 1374 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetFlowControl(const FlowControl flowcontrol) 1375 | { 1376 | return SetOption(flowcontrol); 1377 | } 1378 | 1379 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetParity(const Parity parity) 1380 | { 1381 | return SetOption(parity); 1382 | } 1383 | 1384 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SetStopBits(const StopBits stopbits) 1385 | { 1386 | return SetOption(stopbits); 1387 | } 1388 | 1389 | bool wxSerialPort::IsOpen() const 1390 | { 1391 | return m_serialPort.is_open(); 1392 | } 1393 | 1394 | boost::asio::serial_port::native_handle_type wxSerialPort::GetNativeHandle() 1395 | { 1396 | return m_serialPort.native_handle(); 1397 | } 1398 | 1399 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Open(const std::string& strDevice) 1400 | { 1401 | m_strPortName = strDevice; 1402 | 1403 | boost::system::error_code error; 1404 | m_serialPort.open(strDevice, error); 1405 | DoSetLastError(error); 1406 | return error; 1407 | } 1408 | 1409 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Open(const wxString& strDevice) 1410 | { 1411 | return Open(strDevice.ToStdString()); 1412 | } 1413 | 1414 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Open(const char *pszDevice) 1415 | { 1416 | return Open(pszDevice); 1417 | } 1418 | 1419 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::ReOpen() 1420 | { 1421 | return Open(m_strPortName.ToStdString()); 1422 | } 1423 | 1424 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::SendBreak() 1425 | { 1426 | boost::system::error_code error; 1427 | #ifdef __WXMSW__ 1428 | std::thread thread1([&] 1429 | { 1430 | if (!::SetCommBreak(m_serialPort.native_handle())) 1431 | { 1432 | //wxLogError(wxS("SetCommBreak() failed!")); 1433 | error = boost::system::error_code(::GetLastError(), boost::asio::error::get_system_category()); 1434 | return; 1435 | } 1436 | 1437 | //::Sleep(500); 1438 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 1439 | 1440 | if (!::ClearCommBreak(m_serialPort.native_handle())) 1441 | { 1442 | //wxLogError(wxS("ClearCommBreak() failed!")); 1443 | error = boost::system::error_code(::GetLastError(), boost::asio::error::get_system_category()); 1444 | //return; 1445 | } 1446 | }); 1447 | thread1.join(); 1448 | #else // !__WXMSW__ 1449 | m_serialPort.send_break(error); 1450 | #endif // __WXMSW__ 1451 | DoSetLastError(error); 1452 | return error; 1453 | } 1454 | 1455 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::Wait(const int timeout) 1456 | { 1457 | return DoWait(timeout); 1458 | } 1459 | 1460 | template 1461 | BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, void (boost::system::error_code)) // Return type 1462 | wxSerialPort::AsyncWait(WaitHandler handler, const int timeout) 1463 | { 1464 | DoSetTimeout(timeout); 1465 | m_io_context.restart(); 1466 | 1467 | auto ret = m_timer.async_wait(handler); 1468 | m_io_context.run(); 1469 | return ret; 1470 | } 1471 | 1472 | wxString wxSerialPort::GetPortName() const 1473 | { 1474 | return m_strPortName; 1475 | } 1476 | 1477 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::FlushBuffers(const Buffers buffers) 1478 | { 1479 | wxASSERT(buffers >= buf_In && buffers <= buf_In_Out); 1480 | 1481 | boost::system::error_code error; 1482 | //std::thread thread1([&] 1483 | //{ 1484 | #ifdef __WXMSW__ 1485 | DWORD dwFlags = 0; 1486 | 1487 | if (buffers & buf_In) 1488 | dwFlags |= PURGE_RXCLEAR; 1489 | 1490 | if (buffers & buf_Out) 1491 | dwFlags |= PURGE_TXCLEAR; 1492 | 1493 | if (!::PurgeComm(m_serialPort.native_handle(), dwFlags)) 1494 | { 1495 | //wxLogError(wxS("PurgeComm() failed!")); 1496 | error = boost::system::error_code(::GetLastError(), boost::asio::error::get_system_category()); 1497 | //return; 1498 | } 1499 | #else // !__WXMSW__ 1500 | int flags = 0; 1501 | 1502 | if (buffers == buf_In_Out) 1503 | flags = TCIOFLUSH; 1504 | else if (buffers == buf_In) 1505 | flags = TCIFLUSH; 1506 | else if (buffers == buf_Out) 1507 | flags = TCOFLUSH; 1508 | 1509 | if (tcflush(m_serialPort.native_handle(), flags) == -1) 1510 | { 1511 | //wxLogError(wxS("tcflush() failed!")); 1512 | error = boost::system::error_code(errno, boost::asio::error::get_system_category()); 1513 | //return; 1514 | } 1515 | #endif // __WXMSW__ 1516 | //}); 1517 | //thread1.join(); 1518 | DoSetLastError(error); 1519 | return error; 1520 | } 1521 | 1522 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::WaitForBuffers(const Buffers buffers, const int timeout) 1523 | { 1524 | wxASSERT(buffers == buf_In || buffers == buf_Out); 1525 | DoSetTimeout(timeout); 1526 | 1527 | boost::system::error_code error; 1528 | m_io_context.restart(); 1529 | 1530 | m_timer.async_wait([&](const boost::system::error_code& error) 1531 | { 1532 | // Timed out 1533 | if (!error) // != boost::asio::error::operation_aborted 1534 | { 1535 | m_io_context.stop(); 1536 | DoSetLastError(boost::asio::error::timed_out); 1537 | } 1538 | }); 1539 | 1540 | boost::asio::post(m_io_context, [&] 1541 | { 1542 | for (;;) 1543 | { 1544 | // Have we timed out already? 1545 | if (m_io_context.poll()) // m_io_context.stopped() 1546 | return; 1547 | 1548 | int nNumByInBuf = 0; 1549 | int nNumByOutBuf = 0; 1550 | #ifdef __WXMSW__ 1551 | COMSTAT comstat; 1552 | 1553 | if (!::ClearCommError(m_serialPort.native_handle(), nullptr, &comstat)) 1554 | { 1555 | //wxLogError(wxS("ClearCommError() failed!")); 1556 | error = boost::system::error_code(::GetLastError(), boost::asio::error::get_system_category()); 1557 | return; 1558 | } 1559 | 1560 | nNumByInBuf = comstat.cbInQue; 1561 | nNumByOutBuf = comstat.cbOutQue; 1562 | #else // !__WXMSW__ 1563 | 1564 | int ret = 0; 1565 | 1566 | if (buffers == buf_In) 1567 | ret = ioctl(m_serialPort.native_handle(), FIONREAD /*TIOCINQ*/, &nNumByInBuf); 1568 | else if (buffers == buf_Out) 1569 | ret = ioctl(m_serialPort.native_handle(), TIOCOUTQ, &nNumByOutBuf); 1570 | 1571 | if (ret == -1) 1572 | { 1573 | //wxLogError(wxS("ioctl() failed!")); 1574 | error = boost::system::error_code(errno, boost::asio::error::get_system_category()); 1575 | return; 1576 | } 1577 | #endif // __WXMSW__ 1578 | 1579 | if (((buffers & buf_In) && nNumByInBuf) || ((buffers & buf_Out) && nNumByOutBuf)) 1580 | { 1581 | m_io_context.stop(); 1582 | m_timer.cancel(); 1583 | return; 1584 | } 1585 | 1586 | std::this_thread::yield(); 1587 | } 1588 | }); 1589 | 1590 | std::thread thread1([this] { m_io_context.run(); }); 1591 | thread1.join(); 1592 | DoSetLastError(error); 1593 | return error; 1594 | } 1595 | 1596 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::WaitForInBuffer(const int timeout) 1597 | { 1598 | return WaitForBuffers(buf_In, timeout); 1599 | } 1600 | 1601 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::WaitForOutBuffer(const int timeout) 1602 | { 1603 | return WaitForBuffers(buf_Out, timeout); 1604 | } 1605 | 1606 | void wxSerialPort::CancelAsyncIO() 1607 | { 1608 | m_serialPort.cancel(); 1609 | m_timer.cancel(); 1610 | } 1611 | 1612 | boost::system::error_code wxSerialPort::GetLastError() const 1613 | { 1614 | return m_last_error; 1615 | } 1616 | 1617 | // This helper function is intended for internal use by the class itself 1618 | void wxSerialPort::DoSetTimeout(const int timeout) 1619 | { 1620 | if (timeout == wxTIMEOUT_INFINITE) 1621 | m_timer.expires_at(std::chrono::steady_clock::time_point::max()); 1622 | else 1623 | m_timer.expires_from_now(std::chrono::milliseconds(timeout)); 1624 | } 1625 | 1626 | // This helper function is intended for internal use by the class itself 1627 | BOOST_ASIO_SYNC_OP_VOID wxSerialPort::DoWait(const int timeout) 1628 | { 1629 | DoSetTimeout(timeout); 1630 | 1631 | boost::system::error_code error; 1632 | m_timer.wait(error); 1633 | DoSetLastError(error); 1634 | return error; 1635 | } 1636 | 1637 | // This helper function is intended for internal use by the class itself 1638 | void wxSerialPort::DoAsyncWaitThenCancelAsyncIO(const int timeout) 1639 | { 1640 | DoSetTimeout(timeout); 1641 | 1642 | m_timer.async_wait(/*std::bind(&wxSerialPort::AsyncWaitHandler, this, std::placeholders::_1)*/ 1643 | [this](const boost::system::error_code& error) 1644 | { 1645 | // Timed out 1646 | if (!error) // != boost::asio::error::operation_aborted 1647 | { 1648 | boost::system::error_code error; 1649 | m_serialPort.cancel(error); 1650 | DoSetLastError(boost::asio::error::timed_out); 1651 | } 1652 | }); 1653 | } 1654 | 1655 | // This helper function is intended for internal use by the class itself 1656 | void wxSerialPort::DoAsyncWaitThenStopAsyncIO(const int timeout) 1657 | { 1658 | DoSetTimeout(timeout); 1659 | 1660 | m_timer.async_wait([this](const boost::system::error_code& error) 1661 | { 1662 | // Timed out 1663 | if (!error) // != boost::asio::error::operation_aborted 1664 | { 1665 | m_io_context.stop(); 1666 | DoSetLastError(boost::asio::error::timed_out); 1667 | } 1668 | }); 1669 | } 1670 | 1671 | // This helper function is intended for internal use by the class itself 1672 | void wxSerialPort::DoSetLastError(const boost::system::error_code& error) 1673 | { 1674 | wxCriticalSectionLocker lock(m_csLastError); 1675 | m_last_error = error; 1676 | OnError(); 1677 | } 1678 | 1679 | // Async read handler 1680 | //void wxSerialPort::AsyncReadHandler(const boost::system::error_code& error, std::size_t bytes_transferred) 1681 | //{ 1682 | // // Read operation was not aborted 1683 | // if (!error) // != boost::asio::error::operation_aborted 1684 | // m_timer.cancel(); 1685 | // 1686 | // { 1687 | // wxCriticalSectionLocker lock(m_csBytesRead); 1688 | // m_bytes_read = bytes_transferred; 1689 | // } 1690 | // 1691 | // DoSetLastError(error); 1692 | //} 1693 | 1694 | // Async write handler 1695 | //void wxSerialPort::AsyncWriteHandler(const boost::system::error_code& error, std::size_t bytes_transferred) 1696 | //{ 1697 | // // Write operation was not aborted 1698 | // if (!error) // != boost::asio::error::operation_aborted 1699 | // m_timer.cancel(); 1700 | // 1701 | // { 1702 | // wxCriticalSectionLocker lock(m_csBytesWritten); 1703 | // m_bytes_written = bytes_transferred; 1704 | // } 1705 | // 1706 | // DoSetLastError(error); 1707 | //} 1708 | 1709 | // Async wait handler 1710 | //void wxSerialPort::AsyncWaitHandler(const boost::system::error_code& error) 1711 | //{ 1712 | // // Timed out 1713 | // if (!error) // != boost::asio::error::operation_aborted 1714 | // m_serialPort.cancel(); 1715 | // 1716 | // DoSetLastError(error); 1717 | //} 1718 | 1719 | void wxSerialPort::Init() 1720 | { 1721 | //m_bytes_read = 0; 1722 | //m_bytes_written = 0; 1723 | m_last_error = boost::system::error_code(); // 0 1724 | } 1725 | -------------------------------------------------------------------------------- /serialport.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // Name: serialport.h 3 | // Purpose: Defines wxSerialPort Class 4 | // Author: Youcef Kouchkar 5 | // Created: 2018-01-08 6 | // Copyright: (c) 2019 Youcef Kouchkar 7 | // License: MIT License 8 | //////////////////////////////////////////////////////////////////////////////// 9 | 10 | #ifndef _WX_SERIALPORT_H_ 11 | #define _WX_SERIALPORT_H_ 12 | 13 | //#define BOOST_ASIO_DISABLE_STD_CHRONO 14 | //#define BOOST_ASIO_HAS_MOVE 15 | //#define BOOST_ASIO_NO_DEPRECATED 16 | 17 | #include 18 | #include 19 | //#include 20 | #include 21 | //#include 22 | 23 | #define wxTIMEOUT_INFINITE -1 24 | 25 | // =============================================================================================================================== 26 | 27 | // ------------------------------------------------------------------------------------------------------------------------------- 28 | // wxSerialPortBase 29 | // ------------------------------------------------------------------------------------------------------------------------------- 30 | 31 | class wxSerialPortBase 32 | { 33 | public: 34 | // Gettable wxSerialPort options 35 | #ifdef __WXMSW__ 36 | typedef enum /*_BaudRate*/ { br_75 = 75, br_110 = 110, br_134_5 = 134/*.5*/, br_150 = 150, br_300 = 300, br_600 = 600, 37 | br_1200 = 1200, br_1800 = 1800, br_2400 = 2400, br_4800 = 4800, br_7200 = 7200, br_9600 = 9600, 38 | br_14400 = 14400, br_19200 = 19200, br_38400 = 38400, br_56000 = 56000, br_57600 = 57600, 39 | br_128000 = 128000, br_115200 = 115200 } BaudRate; 40 | #else // !__WXMSW__ 41 | typedef enum /*_BaudRate*/ { br_0 = 0, br_50 = 50, br_75 = 75, br_110 = 110, br_134 = 134, br_150 = 150, br_200 = 200, 42 | br_300 = 300, br_600 = 600, br_1200 = 1200, br_1800 = 1800, br_2400 = 2400, br_4800 = 4800, 43 | br_9600 = 9600, br_19200 = 19200, br_38400 = 38400, br_57600 = 57600, br_115200 = 115200, 44 | br_230400 = 230400, br_460800 = 460800, br_500000 = 500000, br_576000 = 576000, br_921600 = 921600, 45 | br_1000000 = 1000000, br_1152000 = 1152000, br_1500000 = 1500000, br_2000000 = 2000000, 46 | br_2500000 = 2500000, br_3000000 = 3000000, br_3500000 = 3500000, br_4000000 = 4000000 } BaudRate; 47 | #endif // __WXMSW__ 48 | typedef enum /*_DataBits*/ { db_Five = 5, db_Six = 6, db_Seven = 7, db_Eight = 8, 49 | db_5 = 5, db_6 = 6, db_7 = 7, db_8 = 8 } DataBits; 50 | typedef enum /*_FlowControl*/ { fc_None, fc_Software, fc_Hardware } FlowControl; 51 | typedef enum /*_Parity*/ { p_None, p_Odd, p_Even } Parity; 52 | typedef enum /*_StopBits*/ { sb_One, sb_One_Five, sb_Two, sb_1 = 0, sb_1_5 = 1, sb_2 = 2 } StopBits; 53 | typedef enum /*_Buffers*/ { buf_In = 1, buf_Out = 2, buf_In_Out = 3 } Buffers; 54 | 55 | public: 56 | wxSerialPortBase(); 57 | ~wxSerialPortBase(); 58 | 59 | static std::vector GetPortNames(); 60 | 61 | protected: 62 | boost::asio::io_context m_io_context; 63 | }; 64 | 65 | // ------------------------------------------------------------------------------------------------------------------------------- 66 | // wxSerialPort 67 | // ------------------------------------------------------------------------------------------------------------------------------- 68 | 69 | class wxSerialPort : public wxSerialPortBase 70 | { 71 | public: 72 | wxSerialPort(); 73 | wxSerialPort(const std::string& strDevice); 74 | wxSerialPort(const wxString& strDevice); 75 | wxSerialPort(const char *pszDevice); 76 | wxSerialPort(const boost::asio::serial_port::native_handle_type& native_serial_port); 77 | 78 | // Copy constructor and assignment operator 79 | wxSerialPort(const wxSerialPort& other); 80 | wxSerialPort& operator=(const wxSerialPort& other); 81 | 82 | // Move constructor and assignment operator 83 | #ifdef BOOST_ASIO_HAS_MOVE 84 | wxSerialPort(wxSerialPort&& other); 85 | wxSerialPort& operator=(wxSerialPort&& other); 86 | #endif // BOOST_ASIO_HAS_MOVE 87 | virtual ~wxSerialPort(); 88 | 89 | boost::asio::serial_port& GetSerialPort(); /*const*/ 90 | BOOST_ASIO_SYNC_OP_VOID Assign(const boost::asio::serial_port::native_handle_type& native_serial_port); 91 | 92 | // =============================================================================================================================== 93 | 94 | // ------------------------------------------------------------------------------------------------------------------------------- 95 | // ReadSome 96 | // ------------------------------------------------------------------------------------------------------------------------------- 97 | 98 | std::size_t ReadSome(std::string& strBuffer); 99 | std::size_t ReadSome(wxCharBuffer& chBuffer); 100 | std::size_t ReadSome(void *pszBuffer, const std::size_t uiSize); 101 | 102 | template 103 | std::size_t ReadSome(std::vector& vBuffer); 104 | 105 | template 106 | std::size_t ReadSome(std::array& arrBuffer); 107 | 108 | // ------------------------------------------------------------------------------------------------------------------------------- 109 | // ReadSome with timeout 110 | // ------------------------------------------------------------------------------------------------------------------------------- 111 | 112 | std::size_t ReadSome(std::string& strBuffer, const int timeout); 113 | std::size_t ReadSome(wxCharBuffer& chBuffer, const int timeout); 114 | std::size_t ReadSome(void *pszBuffer, const std::size_t uiSize, const int timeout); 115 | 116 | template 117 | std::size_t ReadSome(std::vector& vBuffer, const int timeout); 118 | 119 | template 120 | std::size_t ReadSome(std::array& arrBuffer, const int timeout); 121 | 122 | // ------------------------------------------------------------------------------------------------------------------------------- 123 | // WriteSome 124 | // ------------------------------------------------------------------------------------------------------------------------------- 125 | 126 | std::size_t WriteSome(const std::string& strBuffer); 127 | std::size_t WriteSome(const wxString& strBuffer); 128 | std::size_t WriteSome(const wxCharBuffer& chBuffer); 129 | std::size_t WriteSome(const void *pszBuffer, const std::size_t uiSize); 130 | 131 | template 132 | std::size_t WriteSome(const std::vector& vBuffer); 133 | 134 | template 135 | std::size_t WriteSome(const std::array& arrBuffer); 136 | 137 | // ------------------------------------------------------------------------------------------------------------------------------- 138 | // WriteSome with timeout 139 | // ------------------------------------------------------------------------------------------------------------------------------- 140 | 141 | std::size_t WriteSome(const std::string& strBuffer, const int timeout); 142 | std::size_t WriteSome(const wxString& strBuffer, const int timeout); 143 | std::size_t WriteSome(const wxCharBuffer& chBuffer, const int timeout); 144 | std::size_t WriteSome(const void *pszBuffer, const std::size_t uiSize, const int timeout); 145 | 146 | template 147 | std::size_t WriteSome(const std::vector& vBuffer, const int timeout); 148 | 149 | template 150 | std::size_t WriteSome(const std::array& arrBuffer, const int timeout); 151 | 152 | // =============================================================================================================================== 153 | 154 | // ------------------------------------------------------------------------------------------------------------------------------- 155 | // AsyncReadSome 156 | // ------------------------------------------------------------------------------------------------------------------------------- 157 | 158 | template 159 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 160 | AsyncReadSome(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 161 | 162 | template 163 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 164 | AsyncReadSome(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 165 | 166 | template 167 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 168 | AsyncReadSome(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 169 | 170 | template 171 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 172 | AsyncReadSome(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 173 | 174 | template 175 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 176 | AsyncReadSome(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 177 | 178 | // ------------------------------------------------------------------------------------------------------------------------------- 179 | // AsyncReadSome with timeout 180 | // ------------------------------------------------------------------------------------------------------------------------------- 181 | 182 | template 183 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 184 | AsyncReadSome(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 185 | 186 | template 187 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 188 | AsyncReadSome(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 189 | 190 | template 191 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 192 | AsyncReadSome(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 193 | 194 | template 195 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 196 | AsyncReadSome(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 197 | 198 | template 199 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 200 | AsyncReadSome(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 201 | 202 | // ------------------------------------------------------------------------------------------------------------------------------- 203 | // AsyncWriteSome 204 | // ------------------------------------------------------------------------------------------------------------------------------- 205 | 206 | template 207 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 208 | AsyncWriteSome(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 209 | 210 | template 211 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 212 | AsyncWriteSome(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 213 | 214 | template 215 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 216 | AsyncWriteSome(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 217 | 218 | template 219 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 220 | AsyncWriteSome(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 221 | 222 | template 223 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 224 | AsyncWriteSome(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 225 | 226 | template 227 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 228 | AsyncWriteSome(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 229 | 230 | // ------------------------------------------------------------------------------------------------------------------------------- 231 | // AsyncWriteSome with timeout 232 | // ------------------------------------------------------------------------------------------------------------------------------- 233 | 234 | template 235 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 236 | AsyncWriteSome(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 237 | 238 | template 239 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 240 | AsyncWriteSome(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 241 | 242 | template 243 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 244 | AsyncWriteSome(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 245 | 246 | template 247 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 248 | AsyncWriteSome(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 249 | 250 | template 251 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 252 | AsyncWriteSome(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 253 | 254 | template 255 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 256 | AsyncWriteSome(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 257 | 258 | // =============================================================================================================================== 259 | 260 | // ------------------------------------------------------------------------------------------------------------------------------- 261 | // Read 262 | // ------------------------------------------------------------------------------------------------------------------------------- 263 | 264 | std::size_t Read(std::string& strBuffer); 265 | std::size_t Read(wxCharBuffer& chBuffer); 266 | std::size_t Read(void *pszBuffer, const std::size_t uiSize); 267 | 268 | template 269 | std::size_t Read(std::vector& vBuffer); 270 | 271 | template 272 | std::size_t Read(std::array& arrBuffer); 273 | 274 | // ------------------------------------------------------------------------------------------------------------------------------- 275 | // Read with timeout 276 | // ------------------------------------------------------------------------------------------------------------------------------- 277 | 278 | std::size_t Read(std::string& strBuffer, const int timeout); 279 | std::size_t Read(wxCharBuffer& chBuffer, const int timeout); 280 | std::size_t Read(void *pszBuffer, const std::size_t uiSize, const int timeout); 281 | 282 | template 283 | std::size_t Read(std::vector& vBuffer, const int timeout); 284 | 285 | template 286 | std::size_t Read(std::array& arrBuffer, const int timeout); 287 | 288 | // ------------------------------------------------------------------------------------------------------------------------------- 289 | // Write 290 | // ------------------------------------------------------------------------------------------------------------------------------- 291 | 292 | std::size_t Write(const std::string& strBuffer); 293 | std::size_t Write(const wxString& strBuffer); 294 | std::size_t Write(const wxCharBuffer& chBuffer); 295 | std::size_t Write(const void *pszBuffer, const std::size_t uiSize); 296 | 297 | template 298 | std::size_t Write(const std::vector& vBuffer); 299 | 300 | template 301 | std::size_t Write(const std::array& arrBuffer); 302 | 303 | // ------------------------------------------------------------------------------------------------------------------------------- 304 | // Write with timeout 305 | // ------------------------------------------------------------------------------------------------------------------------------- 306 | 307 | std::size_t Write(const std::string& strBuffer, const int timeout); 308 | std::size_t Write(const wxString& strBuffer, const int timeout); 309 | std::size_t Write(const wxCharBuffer& chBuffer, const int timeout); 310 | std::size_t Write(const void *pszBuffer, const std::size_t uiSize, const int timeout); 311 | 312 | template 313 | std::size_t Write(const std::vector& vBuffer, const int timeout); 314 | 315 | template 316 | std::size_t Write(const std::array& arrBuffer, const int timeout); 317 | 318 | // =============================================================================================================================== 319 | 320 | // ------------------------------------------------------------------------------------------------------------------------------- 321 | // AsyncRead 322 | // ------------------------------------------------------------------------------------------------------------------------------- 323 | 324 | template 325 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 326 | AsyncRead(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 327 | 328 | template 329 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 330 | AsyncRead(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 331 | 332 | template 333 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 334 | AsyncRead(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 335 | 336 | template 337 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 338 | AsyncRead(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 339 | 340 | template 341 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 342 | AsyncRead(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 343 | 344 | // ------------------------------------------------------------------------------------------------------------------------------- 345 | // AsyncRead with timeout 346 | // ------------------------------------------------------------------------------------------------------------------------------- 347 | 348 | template 349 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 350 | AsyncRead(std::string& strBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 351 | 352 | template 353 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 354 | AsyncRead(wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 355 | 356 | template 357 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 358 | AsyncRead(void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 359 | 360 | template 361 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 362 | AsyncRead(std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 363 | 364 | template 365 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 366 | AsyncRead(std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 367 | 368 | // ------------------------------------------------------------------------------------------------------------------------------- 369 | // AsyncWrite 370 | // ------------------------------------------------------------------------------------------------------------------------------- 371 | 372 | template 373 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 374 | AsyncWrite(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 375 | 376 | template 377 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 378 | AsyncWrite(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 379 | 380 | template 381 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 382 | AsyncWrite(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 383 | 384 | template 385 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 386 | AsyncWrite(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 387 | 388 | template 389 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 390 | AsyncWrite(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 391 | 392 | template 393 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 394 | AsyncWrite(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 395 | 396 | // ------------------------------------------------------------------------------------------------------------------------------- 397 | // AsyncWrite with timeout 398 | // ------------------------------------------------------------------------------------------------------------------------------- 399 | 400 | template 401 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 402 | AsyncWrite(const std::string& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 403 | 404 | template 405 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 406 | AsyncWrite(const wxString& strBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 407 | 408 | template 409 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 410 | AsyncWrite(const wxCharBuffer& chBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 411 | 412 | template 413 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 414 | AsyncWrite(const void *pszBuffer, const std::size_t uiSize, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 415 | 416 | template 417 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 418 | AsyncWrite(const std::vector& vBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 419 | 420 | template 421 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 422 | AsyncWrite(const std::array& arrBuffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 423 | 424 | // =============================================================================================================================== 425 | 426 | // ------------------------------------------------------------------------------------------------------------------------------- 427 | // ReadUntil 428 | // ------------------------------------------------------------------------------------------------------------------------------- 429 | 430 | std::size_t ReadUntil(std::string& strBuffer, const std::string& strDelim); 431 | std::size_t ReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim); 432 | std::size_t ReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2); 433 | 434 | template 435 | std::size_t ReadUntil(std::vector& vBuffer, const std::vector& vDelim); 436 | 437 | template 438 | std::size_t ReadUntil(std::array& arrBuffer, const std::array& arrDelim); 439 | 440 | // ------------------------------------------------------------------------------------------------------------------------------- 441 | // ReadUntil with timeout 442 | // ------------------------------------------------------------------------------------------------------------------------------- 443 | 444 | std::size_t ReadUntil(std::string& strBuffer, const std::string& strDelim, const int timeout); 445 | std::size_t ReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim, const int timeout); 446 | std::size_t ReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2, const int timeout); 447 | 448 | template 449 | std::size_t ReadUntil(std::vector& vBuffer, const std::vector& vDelim, const int timeout); 450 | 451 | template 452 | std::size_t ReadUntil(std::array& arrBuffer, const std::array& arrDelim, const int timeout); 453 | 454 | // =============================================================================================================================== 455 | 456 | // ------------------------------------------------------------------------------------------------------------------------------- 457 | // AsyncReadUntil 458 | // ------------------------------------------------------------------------------------------------------------------------------- 459 | 460 | template 461 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 462 | AsyncReadUntil(std::string& strBuffer, const std::string& strDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler); 463 | 464 | template 465 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 466 | AsyncReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler); 467 | 468 | template 469 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 470 | AsyncReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler); 471 | 472 | template 473 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 474 | AsyncReadUntil(std::vector& vBuffer, const std::vector& vDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler); 475 | 476 | template 477 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 478 | AsyncReadUntil(std::array& arrBuffer, const std::array& arrDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler); 479 | 480 | // ------------------------------------------------------------------------------------------------------------------------------- 481 | // AsyncReadUntil with timeout 482 | // ------------------------------------------------------------------------------------------------------------------------------- 483 | 484 | template 485 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 486 | AsyncReadUntil(std::string& strBuffer, const std::string& strDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout); 487 | 488 | template 489 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 490 | AsyncReadUntil(wxCharBuffer& chBuffer, const wxCharBuffer& chDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout); 491 | 492 | template 493 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 494 | AsyncReadUntil(void *pszBuffer, const std::size_t uiSize1, const void *pszDelim, const std::size_t uiSize2, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout); 495 | 496 | template 497 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 498 | AsyncReadUntil(std::vector& vBuffer, const std::vector& vDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout); 499 | 500 | template 501 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 502 | AsyncReadUntil(std::array& arrBuffer, const std::array& arrDelim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout); 503 | 504 | // =============================================================================================================================== 505 | 506 | BOOST_ASIO_SYNC_OP_VOID Cancel(); 507 | BOOST_ASIO_SYNC_OP_VOID Close(); 508 | boost::asio::serial_port::executor_type GetExecutor() BOOST_ASIO_NOEXCEPT; 509 | 510 | BOOST_ASIO_SYNC_OP_VOID GetOption(BaudRate& option); 511 | BOOST_ASIO_SYNC_OP_VOID GetOption(DataBits& option); 512 | BOOST_ASIO_SYNC_OP_VOID GetOption(FlowControl& option); 513 | BOOST_ASIO_SYNC_OP_VOID GetOption(Parity& option); 514 | BOOST_ASIO_SYNC_OP_VOID GetOption(StopBits& option); 515 | 516 | BOOST_ASIO_SYNC_OP_VOID SetOption(const BaudRate option); 517 | BOOST_ASIO_SYNC_OP_VOID SetOption(const DataBits option); 518 | BOOST_ASIO_SYNC_OP_VOID SetOption(const FlowControl option); 519 | BOOST_ASIO_SYNC_OP_VOID SetOption(const Parity option); 520 | BOOST_ASIO_SYNC_OP_VOID SetOption(const StopBits option); 521 | 522 | BOOST_ASIO_SYNC_OP_VOID GetBaudRate(BaudRate& baudrate); 523 | BOOST_ASIO_SYNC_OP_VOID GetDataBits(DataBits& databits); 524 | BOOST_ASIO_SYNC_OP_VOID GetFlowControl(FlowControl& flowcontrol); 525 | BOOST_ASIO_SYNC_OP_VOID GetParity(Parity& parity); 526 | BOOST_ASIO_SYNC_OP_VOID GetStopBits(StopBits& stopbits); 527 | 528 | BOOST_ASIO_SYNC_OP_VOID SetBaudRate(const BaudRate baudrate); 529 | BOOST_ASIO_SYNC_OP_VOID SetDataBits(const DataBits databits); 530 | BOOST_ASIO_SYNC_OP_VOID SetFlowControl(const FlowControl flowcontrol); 531 | BOOST_ASIO_SYNC_OP_VOID SetParity(const Parity parity); 532 | BOOST_ASIO_SYNC_OP_VOID SetStopBits(const StopBits stopbits); 533 | 534 | bool IsOpen() const; 535 | boost::asio::serial_port::native_handle_type GetNativeHandle(); 536 | BOOST_ASIO_SYNC_OP_VOID Open(const std::string& strDevice); 537 | BOOST_ASIO_SYNC_OP_VOID Open(const wxString& strDevice); 538 | BOOST_ASIO_SYNC_OP_VOID Open(const char *pszDevice); 539 | BOOST_ASIO_SYNC_OP_VOID ReOpen(); 540 | BOOST_ASIO_SYNC_OP_VOID SendBreak(); 541 | BOOST_ASIO_SYNC_OP_VOID Wait(const int timeout); 542 | 543 | template 544 | BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, void (boost::system::error_code)) // Return type 545 | AsyncWait(WaitHandler handler, const int timeout); 546 | wxString GetPortName() const; 547 | BOOST_ASIO_SYNC_OP_VOID FlushBuffers(const Buffers buffers); 548 | BOOST_ASIO_SYNC_OP_VOID WaitForBuffers(const Buffers buffers, const int timeout); 549 | BOOST_ASIO_SYNC_OP_VOID WaitForInBuffer(const int timeout); 550 | BOOST_ASIO_SYNC_OP_VOID WaitForOutBuffer(const int timeout); 551 | void CancelAsyncIO(); 552 | boost::system::error_code GetLastError() const; 553 | 554 | protected: 555 | // These helper functions are intended for internal use by the class itself 556 | std::size_t DoReadSome(const boost::asio::mutable_buffer& buffer); 557 | std::size_t DoReadSome(const boost::asio::mutable_buffer& buffer, const int timeout); 558 | std::size_t DoWriteSome(const boost::asio::const_buffer& buffer); 559 | std::size_t DoWriteSome(const boost::asio::const_buffer& buffer, const int timeout); 560 | 561 | template 562 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 563 | DoAsyncReadSome(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 564 | 565 | template 566 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 567 | DoAsyncReadSome(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 568 | 569 | template 570 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 571 | DoAsyncWriteSome(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 572 | 573 | template 574 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 575 | DoAsyncWriteSome(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 576 | 577 | std::size_t DoRead(const boost::asio::mutable_buffer& buffer); 578 | std::size_t DoRead(const boost::asio::mutable_buffer& buffer, const int timeout); 579 | std::size_t DoWrite(const boost::asio::const_buffer& buffer); 580 | std::size_t DoWrite(const boost::asio::const_buffer& buffer, const int timeout); 581 | 582 | template 583 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 584 | DoAsyncRead(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); 585 | 586 | template 587 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) // Return type 588 | DoAsyncRead(const boost::asio::mutable_buffer& buffer, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, const int timeout); 589 | 590 | template 591 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 592 | DoAsyncWrite(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler); 593 | 594 | template 595 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) // Return type 596 | DoAsyncWrite(const boost::asio::const_buffer& buffer, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, const int timeout); 597 | 598 | std::size_t DoReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim); 599 | std::size_t DoReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, const int timeout); 600 | 601 | template 602 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 603 | DoAsyncReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler); 604 | 605 | template 606 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadUntilHandler, void (boost::system::error_code, std::size_t)) // Return type 607 | DoAsyncReadUntil(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, BOOST_ASIO_MOVE_ARG(ReadUntilHandler) handler, const int timeout); 608 | 609 | void DoSetTimeout(const int timeout); 610 | BOOST_ASIO_SYNC_OP_VOID DoWait(const int timeout); 611 | void DoAsyncWaitThenCancelAsyncIO(const int timeout); 612 | void DoAsyncWaitThenStopAsyncIO(const int timeout); 613 | void DoSetLastError(const boost::system::error_code& error); 614 | 615 | // Async read, write and wait handlers 616 | //void AsyncReadHandler(const boost::system::error_code& error, std::size_t bytes_transferred); 617 | //void AsyncWriteHandler(const boost::system::error_code& error, std::size_t bytes_transferred); 618 | //void AsyncWaitHandler(const boost::system::error_code& error); 619 | 620 | std::size_t DoCompletionCondition(const boost::asio::mutable_buffer& buffer, const boost::asio::const_buffer& delim, 621 | const boost::system::error_code& error, const std::size_t bytes_transferred) const; 622 | 623 | // Error handler 624 | virtual void OnError(/*const boost::system::error_code& error*/) {} 625 | 626 | private: 627 | void Init(); 628 | 629 | private: 630 | boost::asio::serial_port m_serialPort; 631 | boost::asio::steady_timer m_timer; 632 | wxString m_strPortName; 633 | //std::size_t m_bytes_read; 634 | //std::size_t m_bytes_written; 635 | boost::system::error_code m_last_error; 636 | wxCriticalSection m_csLastError; // Protects m_last_error 637 | //wxCriticalSection m_csBytesRead; // Protects m_bytes_read 638 | //wxCriticalSection m_csBytesWritten; // Protects m_bytes_written 639 | }; 640 | 641 | #endif // _WX_SERIALPORT_H_ 642 | --------------------------------------------------------------------------------