Go to the documentation of this file.00001
00008
00009
00010
00011
00012 #ifndef ECL_DEVICES_SERIAL_POS_HPP_
00013 #define ECL_DEVICES_SERIAL_POS_HPP_
00014
00015
00016
00017
00018
00019 #include <ecl/config.hpp>
00020 #if defined(ECL_IS_POSIX)
00021
00022
00023
00024
00025
00026 #include <string>
00027 #include <termios.h>
00028 #include <ecl/exceptions/standard_exception.hpp>
00029 #include <ecl/errors/compile_time_assert.hpp>
00030 #include <ecl/time/snooze.hpp>
00031 #include <ecl/utilities/parameter.hpp>
00032 #include <ecl/type_traits/fundamental_types.hpp>
00033 #include "detail/error_handler_pos.hpp"
00034 #include "detail/exception_handler_pos.hpp"
00035 #include "serial_parameters.hpp"
00036 #include "traits.hpp"
00037
00038
00039
00040
00041
00042 namespace ecl {
00043
00044
00045
00046
00130 class Serial {
00131 public:
00132
00133
00134
00142 Serial() : is_open(false), error_handler(NoError) {};
00160 Serial(const std::string& port_name, const BaudRate &baud_rate = BaudRate_115200, const DataBits &data_bits = DataBits_8,
00161 const StopBits &stop_bits = StopBits_1, const Parity &parity = NoParity ) ecl_throw_decl(StandardException);
00162
00168 virtual ~Serial();
00169
00170
00171
00172
00204 bool open(const std::string& port_name, const BaudRate &baud_rate = BaudRate_115200, const DataBits &data_bits = DataBits_8,
00205 const StopBits &stop_bits = StopBits_1, const Parity &parity = NoParity ) ecl_throw_decl(StandardException);
00206
00214 void close();
00220 bool open() const { return is_open; }
00221
00222
00223
00224
00234 template <typename Byte>
00235 long write(const Byte &byte) ecl_debug_throw_decl(StandardException);
00236
00247 template <typename Byte>
00248 long write(const Byte *bytes, const unsigned long &n) ecl_debug_throw_decl(StandardException);
00249
00256 void flush() {}
00257
00258
00259
00260
00279 void block(const unsigned long &timeout = 500);
00286 void unblock();
00287
00288
00289
00290
00298 long remaining();
00312 template <typename Byte>
00313 long read(Byte &byte) ecl_debug_throw_decl(StandardException);
00328 template <typename Byte>
00329 long read(Byte *bytes, const unsigned long &n) ecl_debug_throw_decl(StandardException);
00330
00331
00332
00333
00340 void clear() { tcflush(file_descriptor,TCIOFLUSH); }
00346 void clearInputBuffer() { tcflush(file_descriptor,TCIFLUSH); }
00352 void clearOutputBuffer() { tcflush(file_descriptor,TCOFLUSH); }
00353
00360 const Error& error() const { return error_handler; }
00361 private:
00362
00363
00364
00365 int file_descriptor;
00366 termios options;
00367 std::string port;
00368 unsigned long read_timeout_ms;
00369 ecl::Snooze fake_snooze;
00370 unsigned int fake_loop_count;
00371 bool is_open;
00372 ecl::Error error_handler;
00373 };
00374
00375
00376
00377
00378
00379 template <typename Byte>
00380 long Serial::write(const Byte &byte) ecl_debug_throw_decl(StandardException) {
00381 ecl_compile_time_assert( is_byte<Byte>::value );
00382 if ( !open() ) {
00383 ecl_debug_throw( StandardException(LOC, OpenError, std::string("Port ") + port + std::string(" is not open.")));
00384 error_handler = OpenError;
00385 return -1;
00386 }
00387 ssize_t no_written = ::write(file_descriptor, &byte, 1);
00388 if ( no_written < 0 ) {
00389 ecl_debug_throw(devices::write_exception(LOC));
00390 error_handler = devices::write_error();
00391 return -1;
00392 }
00393 error_handler = NoError;
00394 return no_written;
00395 }
00396
00397 template <typename Byte>
00398 long Serial::write(const Byte *bytes, const unsigned long &n) ecl_debug_throw_decl(StandardException) {
00399 ecl_compile_time_assert( is_byte<Byte>::value );
00400 if ( !open() ) {
00401 ecl_debug_throw( StandardException(LOC, OpenError, std::string("Port ") + port + std::string(" is not open.")));
00402 error_handler = OpenError;
00403 return -1;
00404 }
00405 ssize_t no_written = ::write(file_descriptor, bytes, n);
00406 if ( no_written < 0 ) {
00407 ecl_debug_throw(devices::write_exception(LOC));
00408 error_handler = devices::write_error();
00409 return -1;
00410 }
00411 error_handler = NoError;
00412 return no_written;
00413 }
00414
00415 template <typename Byte>
00416 long Serial::read(Byte &byte) ecl_debug_throw_decl(StandardException) {
00417 ecl_compile_time_assert( is_byte<Byte>::value );
00418 if ( !open() ) {
00419 ecl_debug_throw( StandardException(LOC, OpenError, std::string("Port ") + port + std::string(" is not open.")));
00420 error_handler = OpenError;
00421 return -1;
00422 }
00423 ssize_t no_read;
00424 if ( read_timeout_ms < 100 ) {
00425 fake_snooze.initialise();
00426 for ( unsigned int i = 0; i < fake_loop_count; ++i ) {
00427 no_read = ::read(file_descriptor, &byte, 1);
00428 if ( no_read != 0 ) {
00429 break;
00430 }
00431 fake_snooze();
00432 }
00433 } else {
00434 no_read = ::read(file_descriptor, &byte, 1);
00435 }
00436 if ( no_read < 0 ) {
00437 ecl_debug_throw(devices::read_exception(LOC));
00438 error_handler = devices::read_error();
00439 return -1;
00440 }
00441 error_handler = NoError;
00442 return no_read;
00443
00444 }
00445
00446 template <typename Byte>
00447 long Serial::read(Byte *bytes, const unsigned long &n) ecl_debug_throw_decl(StandardException) {
00448 ecl_compile_time_assert( is_byte<Byte>::value );
00449 if ( !open() ) {
00450 ecl_debug_throw( StandardException(LOC, OpenError, std::string("Port ") + port + std::string(" is not open.")));
00451 error_handler = OpenError;
00452 return -1;
00453 }
00454 ssize_t no_read = 0;
00455 if ( read_timeout_ms < 100 ) {
00456 fake_snooze.initialise();
00457 for ( unsigned int i = 0; i < fake_loop_count; ++i ) {
00458 no_read = ::read(file_descriptor, bytes, n);
00459 if ( no_read != 0 ) {
00460 break;
00461 }
00462 fake_snooze();
00463 }
00464 } else {
00465 no_read = ::read(file_descriptor, bytes, n);
00466 }
00467 if ( no_read < 0 ) {
00468 ecl_debug_throw(devices::read_exception(LOC));
00469 error_handler = devices::read_error();
00470 return -1;
00471 }
00472 error_handler = NoError;
00473 return no_read;
00474 }
00475
00476
00477
00478
00484 template <>
00485 class is_sink<Serial> : public True {};
00486
00492 template <>
00493 class is_source<Serial> : public True {};
00494
00500 template <>
00501 class is_sourcesink<Serial> : public True {};
00502
00503
00504 }
00505
00506 #endif
00507 #endif