1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
| 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 (!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. } |
Partager