Guest User

Untitled

a guest
Mar 10th, 2011
292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.64 KB | None | 0 0
  1. /* minicom.cpp
  2.         A simple demonstration minicom client with Boost asio
  3.        
  4.         Parameters:
  5.                 baud rate
  6.                 serial port (eg /dev/ttyS0 or COM1)
  7.                
  8.         To end the application, send Ctrl-C on standard input
  9. */
  10.  
  11. #include <deque>
  12. #include <iostream>
  13. #include <boost/bind.hpp>
  14. #include <boost/asio.hpp>
  15. #include <boost/asio/serial_port.hpp>
  16. #include <boost/thread.hpp>
  17. #include <boost/lexical_cast.hpp>
  18. #include <boost/date_time/posix_time/posix_time_types.hpp>
  19.  
  20. #ifdef POSIX
  21. #include <termios.h>
  22. #endif
  23.  
  24. using namespace std;
  25.  
  26. class minicom_client
  27. {
  28. public:
  29.         minicom_client(boost::asio::io_service& io_service, unsigned int baud, const string& device)
  30.                 : active_(true),
  31.                   io_service_(io_service),
  32.                   serialPort(io_service, device)
  33.         {
  34.                 if (not serialPort.is_open())
  35.                 {
  36.                         cerr << "Failed to open serial port\n";
  37.                         return;
  38.                 }
  39.                 boost::asio::serial_port_base::baud_rate baud_option(baud);
  40.                 serialPort.set_option(baud_option); // set the baud rate after the port has been opened
  41.                 read_start();
  42.         }
  43.        
  44.         void write(const char msg) // pass the write data to the do_write function via the io service in the other thread
  45.         {
  46.                 io_service_.post(boost::bind(&minicom_client::do_write, this, msg));
  47.         }
  48.        
  49.         void close() // call the do_close function via the io service in the other thread
  50.         {
  51.                 io_service_.post(boost::bind(&minicom_client::do_close, this, boost::system::error_code()));
  52.         }
  53.  
  54.         bool active() // return true if the socket is still active
  55.         {
  56.                 return active_;
  57.         }
  58.  
  59. private:
  60.  
  61.         static const int max_read_length = 512; // maximum amount of data to read in one operation
  62.        
  63.         void read_start(void)
  64.         { // Start an asynchronous read and call read_complete when it completes or fails
  65.                 serialPort.async_read_some(boost::asio::buffer(read_msg_, max_read_length),
  66.                         boost::bind(&minicom_client::read_complete,
  67.                                 this,
  68.                                 boost::asio::placeholders::error,
  69.                                 boost::asio::placeholders::bytes_transferred));
  70.         }
  71.        
  72.         void read_complete(const boost::system::error_code& error, size_t bytes_transferred)
  73.         { // the asynchronous read operation has now completed or failed and returned an error
  74.                 if (!error)
  75.                 { // read completed, so process the data
  76.                         cout.write(read_msg_, bytes_transferred); // echo to standard output
  77.                         read_start(); // start waiting for another asynchronous read again
  78.                 }
  79.                 else
  80.                         do_close(error);
  81.         }
  82.        
  83.         void do_write(const char msg)
  84.         { // callback to handle write call from outside this class
  85.                 bool write_in_progress = !write_msgs_.empty(); // is there anything currently being written?
  86.                 write_msgs_.push_back(msg); // store in write buffer
  87.                 if (!write_in_progress) // if nothing is currently being written, then start
  88.                         write_start();
  89.         }
  90.        
  91.         void write_start(void)
  92.         { // Start an asynchronous write and call write_complete when it completes or fails
  93.                 boost::asio::async_write(serialPort,
  94.                         boost::asio::buffer(&write_msgs_.front(), 1),
  95.                         boost::bind(&minicom_client::write_complete,
  96.                                 this,
  97.                                 boost::asio::placeholders::error));
  98.         }
  99.        
  100.         void write_complete(const boost::system::error_code& error)
  101.         { // the asynchronous read operation has now completed or failed and returned an error
  102.                 if (!error)
  103.                 { // write completed, so send next write data
  104.                         write_msgs_.pop_front(); // remove the completed data
  105.                         if (!write_msgs_.empty()) // if there is anthing left to be written
  106.                                 write_start(); // then start sending the next item in the buffer
  107.                 }
  108.                 else
  109.                         do_close(error);
  110.         }
  111.        
  112.         void do_close(const boost::system::error_code& error)
  113.         { // something has gone wrong, so close the socket & make this object inactive
  114.                 if (error == boost::asio::error::operation_aborted) // if this call is the result of a timer cancel()
  115.                         return; // ignore it because the connection cancelled the timer
  116.                 if (error)
  117.                         cerr << "Error: " << error.message() << endl; // show the error message
  118.                 else
  119.                         cout << "Error: Connection did not succeed.\n";
  120.                 cout << "Press Enter to exit\n";
  121.                 serialPort.close();
  122.                 active_ = false;
  123.         }
  124.  
  125. private:
  126.         bool active_; // remains true while this object is still operating
  127.         boost::asio::io_service& io_service_; // the main IO service that runs this connection
  128.         boost::asio::serial_port serialPort; // the serial port this instance is connected to
  129.         char read_msg_[max_read_length]; // data read from the socket
  130.         deque<char> write_msgs_; // buffered write data
  131. };
  132.  
  133. int main(int argc, char* argv[])
  134. {
  135. // on Unix POSIX based systems, turn off line buffering of input, so cin.get() returns after every keypress
  136. // On other systems, you'll need to look for an equivalent
  137. #ifdef POSIX
  138.         termios stored_settings;
  139.         tcgetattr(0, &stored_settings);
  140.         termios new_settings = stored_settings;
  141.         new_settings.c_lflag &= (~ICANON);
  142.         new_settings.c_lflag &= (~ISIG); // don't automatically handle control-C
  143.         tcsetattr(0, TCSANOW, &new_settings);
  144. #endif
  145.         try
  146.         {
  147.                 if (argc != 3)
  148.                 {
  149.                         cerr << "Usage: minicom <baud> <device>\n";
  150.                         return 1;
  151.                 }
  152.                 boost::asio::io_service io_service;
  153.                 // define an instance of the main class of this program
  154.                 minicom_client c(io_service, boost::lexical_cast<unsigned int>(argv[1]), argv[2]);
  155.                 // run the IO service as a separate thread, so the main thread can block on standard input
  156.                 boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
  157.                 while (c.active()) // check the internal state of the connection to make sure it's still running
  158.                 {
  159.                         char ch;
  160.                         cin.get(ch); // blocking wait for standard input
  161.                         if (ch == 3) // ctrl-C to end program
  162.                                 break;
  163.                         c.write(ch);
  164.                 }
  165.                 c.close(); // close the minicom client connection
  166.                 t.join(); // wait for the IO service thread to close
  167.         }
  168.         catch (exception& e)
  169.         {
  170.                 cerr << "Exception: " << e.what() << "\n";
  171.         }
  172. #ifdef POSIX // restore default buffering of standard input
  173.         tcsetattr(0, TCSANOW, &stored_settings);
  174. #endif
  175.         return 0;
  176. }
Advertisement
Add Comment
Please, Sign In to add comment