00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "sdkcommon.h"
00036 #include "net_serial.h"
00037
00038 namespace rp{ namespace arch{ namespace net{
00039
00040 raw_serial::raw_serial()
00041 : rp::hal::serial_rxtx()
00042 , _serial_handle(NULL)
00043 , _baudrate(0)
00044 , _flags(0)
00045 {
00046 _init();
00047 }
00048
00049 raw_serial::~raw_serial()
00050 {
00051 close();
00052
00053 CloseHandle(_ro.hEvent);
00054 CloseHandle(_wo.hEvent);
00055 CloseHandle(_wait_o.hEvent);
00056 }
00057
00058 bool raw_serial::open()
00059 {
00060 return open(_portName, _baudrate, _flags);
00061 }
00062
00063 bool raw_serial::bind(const char * portname, _u32 baudrate, _u32 flags)
00064 {
00065 strncpy(_portName, portname, sizeof(_portName));
00066 _baudrate = baudrate;
00067 _flags = flags;
00068 return true;
00069 }
00070
00071 bool raw_serial::open(const char * portname, _u32 baudrate, _u32 flags)
00072 {
00073 if (isOpened()) close();
00074
00075 _serial_handle = CreateFile(
00076 portname,
00077 GENERIC_READ | GENERIC_WRITE,
00078 0,
00079 NULL,
00080 OPEN_EXISTING,
00081 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
00082 NULL
00083 );
00084
00085 if (_serial_handle == INVALID_HANDLE_VALUE) return false;
00086
00087 if (!SetupComm(_serial_handle, SERIAL_RX_BUFFER_SIZE, SERIAL_TX_BUFFER_SIZE))
00088 {
00089 close();
00090 return false;
00091 }
00092
00093 _dcb.BaudRate = baudrate;
00094 _dcb.ByteSize = 8;
00095 _dcb.Parity = NOPARITY;
00096 _dcb.StopBits = ONESTOPBIT;
00097 _dcb.fDtrControl = DTR_CONTROL_ENABLE;
00098
00099 if (!SetCommState(_serial_handle, &_dcb))
00100 {
00101 close();
00102 return false;
00103 }
00104
00105 if (!SetCommTimeouts(_serial_handle, &_co))
00106 {
00107 close();
00108 return false;
00109 }
00110
00111 if (!SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR ))
00112 {
00113 close();
00114 return false;
00115 }
00116
00117 if (!PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
00118 {
00119 close();
00120 return false;
00121 }
00122
00123 Sleep(30);
00124 _is_serial_opened = true;
00125
00126
00127 clearDTR();
00128
00129 return true;
00130 }
00131
00132 void raw_serial::close()
00133 {
00134 SetCommMask(_serial_handle, 0);
00135 ResetEvent(_wait_o.hEvent);
00136
00137 CloseHandle(_serial_handle);
00138 _serial_handle = INVALID_HANDLE_VALUE;
00139
00140 _is_serial_opened = false;
00141 }
00142
00143 int raw_serial::senddata(const unsigned char * data, size_t size)
00144 {
00145 DWORD error;
00146 DWORD w_len = 0, o_len = -1;
00147 if (!isOpened()) return ANS_DEV_ERR;
00148
00149 if (data == NULL || size ==0) return 0;
00150
00151 if(ClearCommError(_serial_handle, &error, NULL) && error > 0)
00152 PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_TXCLEAR);
00153
00154 if(!WriteFile(_serial_handle, data, size, &w_len, &_wo))
00155 if(GetLastError() != ERROR_IO_PENDING)
00156 w_len = ANS_DEV_ERR;
00157
00158 return w_len;
00159 }
00160
00161 int raw_serial::recvdata(unsigned char * data, size_t size)
00162 {
00163 if (!isOpened()) return 0;
00164 DWORD r_len = 0;
00165
00166
00167 if(!ReadFile(_serial_handle, data, size, &r_len, &_ro))
00168 {
00169 if(GetLastError() == ERROR_IO_PENDING)
00170 {
00171 if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
00172 {
00173 if(GetLastError() != ERROR_IO_INCOMPLETE)
00174 r_len = 0;
00175 }
00176 }
00177 else
00178 r_len = 0;
00179 }
00180
00181 return r_len;
00182 }
00183
00184 void raw_serial::flush( _u32 flags)
00185 {
00186 PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
00187 }
00188
00189 int raw_serial::waitforsent(_u32 timeout, size_t * returned_size)
00190 {
00191 if (!isOpened() ) return ANS_DEV_ERR;
00192 DWORD w_len = 0;
00193 _word_size_t ans =0;
00194
00195 if (WaitForSingleObject(_wo.hEvent, timeout) == WAIT_TIMEOUT)
00196 {
00197 ans = ANS_TIMEOUT;
00198 goto _final;
00199 }
00200 if(!GetOverlappedResult(_serial_handle, &_wo, &w_len, FALSE))
00201 {
00202 ans = ANS_DEV_ERR;
00203 }
00204 _final:
00205 if (returned_size) *returned_size = w_len;
00206 return ans;
00207 }
00208
00209 int raw_serial::waitforrecv(_u32 timeout, size_t * returned_size)
00210 {
00211 if (!isOpened() ) return -1;
00212 DWORD r_len = 0;
00213 _word_size_t ans =0;
00214
00215 if (WaitForSingleObject(_ro.hEvent, timeout) == WAIT_TIMEOUT)
00216 {
00217 ans = ANS_TIMEOUT;
00218 }
00219 if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
00220 {
00221 ans = ANS_DEV_ERR;
00222 }
00223 if (returned_size) *returned_size = r_len;
00224 return ans;
00225 }
00226
00227 int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size)
00228 {
00229 COMSTAT stat;
00230 DWORD error;
00231 DWORD msk,length;
00232 size_t dummy_length;
00233
00234 if (returned_size==NULL) returned_size=(size_t *)&dummy_length;
00235
00236
00237 if ( isOpened()) {
00238 size_t rxqueue_remaining = rxqueue_count();
00239 if (rxqueue_remaining >= data_count) {
00240 *returned_size = rxqueue_remaining;
00241 return 0;
00242 }
00243 }
00244
00245 while ( isOpened() )
00246 {
00247 msk = 0;
00248 SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR );
00249 if(!WaitCommEvent(_serial_handle, &msk, &_wait_o))
00250 {
00251 if(GetLastError() == ERROR_IO_PENDING)
00252 {
00253 if (WaitForSingleObject(_wait_o.hEvent, timeout) == WAIT_TIMEOUT)
00254 {
00255 *returned_size =0;
00256 return ANS_TIMEOUT;
00257 }
00258
00259 GetOverlappedResult(_serial_handle, &_wait_o, &length, TRUE);
00260
00261 ::ResetEvent(_wait_o.hEvent);
00262 }else
00263 {
00264 ClearCommError(_serial_handle, &error, &stat);
00265 *returned_size = stat.cbInQue;
00266 return ANS_DEV_ERR;
00267 }
00268 }
00269
00270 if(msk & EV_ERR){
00271
00272 ClearCommError(_serial_handle, &error, &stat);
00273 }
00274
00275 if(msk & EV_RXCHAR){
00276 ClearCommError(_serial_handle, &error, &stat);
00277 if(stat.cbInQue >= data_count)
00278 {
00279 *returned_size = stat.cbInQue;
00280 return 0;
00281 }
00282 }
00283 }
00284 *returned_size=0;
00285 return ANS_DEV_ERR;
00286 }
00287
00288 size_t raw_serial::rxqueue_count()
00289 {
00290 if ( !isOpened() ) return 0;
00291 COMSTAT com_stat;
00292 DWORD error;
00293 DWORD r_len = 0;
00294
00295 if(ClearCommError(_serial_handle, &error, &com_stat) && error > 0)
00296 {
00297 PurgeComm(_serial_handle, PURGE_RXABORT | PURGE_RXCLEAR);
00298 return 0;
00299 }
00300 return com_stat.cbInQue;
00301 }
00302
00303 void raw_serial::setDTR()
00304 {
00305 if ( !isOpened() ) return;
00306
00307 EscapeCommFunction(_serial_handle, SETDTR);
00308 }
00309
00310 void raw_serial::clearDTR()
00311 {
00312 if ( !isOpened() ) return;
00313
00314 EscapeCommFunction(_serial_handle, CLRDTR);
00315 }
00316
00317
00318 void raw_serial::_init()
00319 {
00320 memset(&_dcb, 0, sizeof(_dcb));
00321 _dcb.DCBlength = sizeof(_dcb);
00322 _serial_handle = INVALID_HANDLE_VALUE;
00323 memset(&_co, 0, sizeof(_co));
00324 _co.ReadIntervalTimeout = 0;
00325 _co.ReadTotalTimeoutMultiplier = 0;
00326 _co.ReadTotalTimeoutConstant = 0;
00327 _co.WriteTotalTimeoutMultiplier = 0;
00328 _co.WriteTotalTimeoutConstant = 0;
00329
00330 memset(&_ro, 0, sizeof(_ro));
00331 memset(&_wo, 0, sizeof(_wo));
00332 memset(&_wait_o, 0, sizeof(_wait_o));
00333
00334 _ro.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00335 _wo.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00336 _wait_o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00337
00338 _portName[0] = 0;
00339 }
00340
00341 }}}
00342
00343
00344
00345 namespace rp{ namespace hal{
00346
00347 serial_rxtx * serial_rxtx::CreateRxTx()
00348 {
00349 return new rp::arch::net::raw_serial();
00350 }
00351
00352 void serial_rxtx::ReleaseRxTx( serial_rxtx * rxtx)
00353 {
00354 delete rxtx;
00355 }
00356
00357
00358 }}