Go to the documentation of this file.00001
00010 #include "SerialDevice.h"
00011 #include "DetectOS.h"
00012 #include "RingBuffer.h"
00013 #include <string>
00014
00015 using namespace qrk;
00016 using namespace std;
00017
00018
00019 #if defined(WINDOWS_OS)
00020 #include "SerialDevice_win.cpp"
00021 #else
00022 #include "SerialDevice_lin.cpp"
00023 #endif
00024
00025
00026 struct SerialDevice::pImpl
00027 {
00028 string error_message_;
00029 long baudrate_;
00030 RawSerialDevice raw_;
00031 RingBuffer<char> ring_buffer_;
00032
00033
00034 pImpl(void) : error_message_("no error"), baudrate_(0)
00035 {
00036 }
00037
00038
00039 void updateRingBuffer(void)
00040 {
00041 enum { BufferSize = 2048 };
00042 char buffer[BufferSize];
00043
00044 int n = raw_.receive(buffer, BufferSize, 0);
00045 if (n > 0) {
00046 ring_buffer_.put(buffer, n);
00047 }
00048 }
00049
00050
00051 int receive(char* data, size_t count, int timeout)
00052 {
00053 if (! isConnected()) {
00054 error_message_ = "no connection.";
00055 return -1;
00056 }
00057 if (count == 0) {
00058 return 0;
00059 }
00060
00061 size_t filled = 0;
00062
00063 size_t ring_filled = ring_buffer_.size();
00064 if (ring_filled < count) {
00065 updateRingBuffer();
00066 }
00067
00068
00069 size_t read_size = std::min(count, ring_buffer_.size());
00070 ring_buffer_.get(data, read_size);
00071 filled += read_size;
00072
00073
00074 read_size = max(0, static_cast<int>(count - filled));
00075 if (read_size > 0) {
00076 int n = raw_.receive(&data[filled],
00077 static_cast<int>(read_size), timeout);
00078 if (n < 0) {
00079 error_message_ = raw_.what();
00080 return n;
00081 }
00082 filled += n;
00083 }
00084 return static_cast<int>(filled);
00085 }
00086
00087
00088 bool isConnected(void)
00089 {
00090 return raw_.isConnected();
00091 }
00092 };
00093
00094
00095 SerialDevice::SerialDevice(void) : pimpl(new pImpl)
00096 {
00097 }
00098
00099
00100 SerialDevice::~SerialDevice(void)
00101 {
00102 disconnect();
00103 }
00104
00105
00106 const char* SerialDevice::what(void) const
00107 {
00108 return pimpl->error_message_.c_str();
00109 }
00110
00111
00112 bool SerialDevice::connect(const char* device, long baudrate)
00113 {
00114 disconnect();
00115 clear();
00116 if (! pimpl->raw_.connect(device, baudrate)) {
00117 pimpl->error_message_ = pimpl->raw_.what();
00118 return false;
00119 } else {
00120 return true;
00121 }
00122 }
00123
00124
00125 void SerialDevice::disconnect(void)
00126 {
00127 return pimpl->raw_.disconnect();
00128 }
00129
00130
00131 bool SerialDevice::setBaudrate(long baudrate)
00132 {
00133 if (! pimpl->raw_.setBaudrate(baudrate)) {
00134 pimpl->error_message_ = pimpl->raw_.what();
00135 pimpl->baudrate_ = 0;
00136 return false;
00137 }
00138 pimpl->baudrate_ = baudrate;
00139 return true;
00140 }
00141
00142
00143 long SerialDevice::baudrate(void) const
00144 {
00145 return pimpl->baudrate_;
00146 }
00147
00148
00149 bool SerialDevice::isConnected(void) const
00150 {
00151 return pimpl->isConnected();
00152 }
00153
00154
00155 int SerialDevice::send(const char* data, size_t count)
00156 {
00157 if (! isConnected()) {
00158 pimpl->error_message_ = "no connection.";
00159 return 0;
00160 }
00161
00162 int n = pimpl->raw_.send(data, static_cast<int>(count));
00163 if (n < 0) {
00164 pimpl->error_message_ = pimpl->raw_.what();
00165 }
00166 return n;
00167 }
00168
00169
00170 int SerialDevice::receive(char* data, size_t count, int timeout)
00171 {
00172 if (! isConnected()) {
00173 pimpl->error_message_ = "no connection.";
00174 return 0;
00175 }
00176
00177 return pimpl->receive(data, count, timeout);
00178 }
00179
00180
00181 size_t SerialDevice::size(void) const
00182 {
00183 pimpl->updateRingBuffer();
00184 return pimpl->ring_buffer_.size();
00185 }
00186
00187
00188 void SerialDevice::flush(void)
00189 {
00190 if (! isConnected()) {
00191 pimpl->error_message_ = "no connection.";
00192 return;
00193 }
00194
00195 return pimpl->raw_.flush();
00196 }
00197
00198
00199 void SerialDevice::clear(void)
00200 {
00201 pimpl->raw_.flush();
00202 pimpl->ring_buffer_.clear();
00203 }
00204
00205
00206 void SerialDevice::ungetc(const char ch)
00207 {
00208 if (! isConnected()) {
00209 pimpl->error_message_ = "no connection.";
00210 return;
00211 }
00212
00213 pimpl->ring_buffer_.ungetc(ch);
00214 }