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
00036
00037 #include "sdkcommon.h"
00038 #include "net_serial.h"
00039
00040 namespace rp{ namespace arch{ namespace net{
00041
00042 raw_serial::raw_serial()
00043 : rp::hal::serial_rxtx()
00044 , _serial_handle(NULL)
00045 , _baudrate(0)
00046 , _flags(0)
00047 {
00048 _init();
00049 }
00050
00051 raw_serial::~raw_serial()
00052 {
00053 close();
00054
00055 CloseHandle(_ro.hEvent);
00056 CloseHandle(_wo.hEvent);
00057 CloseHandle(_wait_o.hEvent);
00058 }
00059
00060 bool raw_serial::open()
00061 {
00062 return open(_portName, _baudrate, _flags);
00063 }
00064
00065 bool raw_serial::bind(const char * portname, _u32 baudrate, _u32 flags)
00066 {
00067 strncpy(_portName, portname, sizeof(_portName));
00068 _baudrate = baudrate;
00069 _flags = flags;
00070 return true;
00071 }
00072
00073 bool raw_serial::open(const char * portname, _u32 baudrate, _u32 flags)
00074 {
00075 if (isOpened()) close();
00076
00077 _serial_handle = CreateFile(
00078 portname,
00079 GENERIC_READ | GENERIC_WRITE,
00080 0,
00081 NULL,
00082 OPEN_EXISTING,
00083 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
00084 NULL
00085 );
00086
00087 if (_serial_handle == INVALID_HANDLE_VALUE) return false;
00088
00089 if (!SetupComm(_serial_handle, SERIAL_RX_BUFFER_SIZE, SERIAL_TX_BUFFER_SIZE))
00090 {
00091 close();
00092 return false;
00093 }
00094
00095 _dcb.BaudRate = baudrate;
00096 _dcb.ByteSize = 8;
00097 _dcb.Parity = NOPARITY;
00098 _dcb.StopBits = ONESTOPBIT;
00099 _dcb.fDtrControl = DTR_CONTROL_ENABLE;
00100
00101 if (!SetCommState(_serial_handle, &_dcb))
00102 {
00103 close();
00104 return false;
00105 }
00106
00107
00108 EscapeCommFunction(_serial_handle, CLRDTR);
00109
00110 if (!SetCommTimeouts(_serial_handle, &_co))
00111 {
00112 close();
00113 return false;
00114 }
00115
00116 if (!SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR ))
00117 {
00118 close();
00119 return false;
00120 }
00121
00122 if (!PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
00123 {
00124 close();
00125 return false;
00126 }
00127
00128 Sleep(30);
00129 _is_serial_opened = true;
00130 return true;
00131 }
00132
00133 void raw_serial::close()
00134 {
00135 SetCommMask(_serial_handle, 0);
00136 ResetEvent(_wait_o.hEvent);
00137
00138 CloseHandle(_serial_handle);
00139 _serial_handle = INVALID_HANDLE_VALUE;
00140
00141 _is_serial_opened = false;
00142 }
00143
00144 int raw_serial::senddata(const unsigned char * data, size_t size)
00145 {
00146 DWORD error;
00147 DWORD w_len = 0, o_len = -1;
00148 if (!isOpened()) return ANS_DEV_ERR;
00149
00150 if (data == NULL || size ==0) return 0;
00151
00152 if(ClearCommError(_serial_handle, &error, NULL) && error > 0)
00153 PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_TXCLEAR);
00154
00155 if(!WriteFile(_serial_handle, data, size, &w_len, &_wo))
00156 if(GetLastError() != ERROR_IO_PENDING)
00157 w_len = ANS_DEV_ERR;
00158
00159 return w_len;
00160 }
00161
00162 int raw_serial::recvdata(unsigned char * data, size_t size)
00163 {
00164 if (!isOpened()) return 0;
00165 DWORD r_len = 0;
00166
00167
00168 if(!ReadFile(_serial_handle, data, size, &r_len, &_ro))
00169 {
00170 if(GetLastError() == ERROR_IO_PENDING)
00171 {
00172 if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
00173 {
00174 if(GetLastError() != ERROR_IO_INCOMPLETE)
00175 r_len = 0;
00176 }
00177 }
00178 else
00179 r_len = 0;
00180 }
00181
00182 return r_len;
00183 }
00184
00185 void raw_serial::flush( _u32 flags)
00186 {
00187 PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
00188 }
00189
00190 int raw_serial::waitforsent(_u32 timeout, size_t * returned_size)
00191 {
00192 if (!isOpened() ) return ANS_DEV_ERR;
00193 DWORD w_len = 0;
00194 _word_size_t ans =0;
00195
00196 if (WaitForSingleObject(_wo.hEvent, timeout) == WAIT_TIMEOUT)
00197 {
00198 ans = ANS_TIMEOUT;
00199 goto _final;
00200 }
00201 if(!GetOverlappedResult(_serial_handle, &_wo, &w_len, FALSE))
00202 {
00203 ans = ANS_DEV_ERR;
00204 }
00205 _final:
00206 if (returned_size) *returned_size = w_len;
00207 return ans;
00208 }
00209
00210 int raw_serial::waitforrecv(_u32 timeout, size_t * returned_size)
00211 {
00212 if (!isOpened() ) return -1;
00213 DWORD r_len = 0;
00214 _word_size_t ans =0;
00215
00216 if (WaitForSingleObject(_ro.hEvent, timeout) == WAIT_TIMEOUT)
00217 {
00218 ans = ANS_TIMEOUT;
00219 }
00220 if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
00221 {
00222 ans = ANS_DEV_ERR;
00223 }
00224 if (returned_size) *returned_size = r_len;
00225 return ans;
00226 }
00227
00228 int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size)
00229 {
00230 COMSTAT stat;
00231 DWORD error;
00232 DWORD msk,length;
00233 size_t dummy_length;
00234 if (returned_size==NULL) returned_size=&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
00304 void raw_serial::_init()
00305 {
00306 memset(&_dcb, 0, sizeof(_dcb));
00307 _dcb.DCBlength = sizeof(_dcb);
00308 _serial_handle = INVALID_HANDLE_VALUE;
00309 memset(&_co, 0, sizeof(_co));
00310 _co.ReadIntervalTimeout = 0;
00311 _co.ReadTotalTimeoutMultiplier = 0;
00312 _co.ReadTotalTimeoutConstant = 0;
00313 _co.WriteTotalTimeoutMultiplier = 0;
00314 _co.WriteTotalTimeoutConstant = 0;
00315
00316 memset(&_ro, 0, sizeof(_ro));
00317 memset(&_wo, 0, sizeof(_wo));
00318 memset(&_wait_o, 0, sizeof(_wait_o));
00319
00320 _ro.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00321 _wo.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00322 _wait_o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00323
00324 _portName[0] = 0;
00325 }
00326
00327 }}}
00328
00329
00330
00331 namespace rp{ namespace hal{
00332
00333 serial_rxtx * serial_rxtx::CreateRxTx()
00334 {
00335 return new rp::arch::net::raw_serial();
00336 }
00337
00338 void serial_rxtx::ReleaseRxTx( serial_rxtx * rxtx)
00339 {
00340 delete rxtx;
00341 }
00342
00343
00344 }}