All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/connection/SerialDevice.cpp
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"   // Windows (win32) 環境
00021 #else
00022 #include "SerialDevice_lin.cpp"   // Linux, Mac 環境 (共通)
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 }