net_serial.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014, RoboPeak
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice, 
00009  *    this list of conditions and the following disclaimer.
00010  *
00011  * 2. Redistributions in binary form must reproduce the above copyright notice, 
00012  *    this list of conditions and the following disclaimer in the documentation 
00013  *    and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
00017  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00018  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
00019  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00021  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00022  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00023  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00025  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 /*
00029  *  RoboPeak LIDAR System
00030  *  Serial Device Driver for Win32
00031  *
00032  *  Copyright 2009 - 2014 RoboPeak Team
00033  *  http://www.robopeak.com
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     //Clear the DTR bit to let the motor spin
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             // FIXME: may cause problem here
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 }}} //end rp::arch::net
00328 
00329 
00330 //begin rp::hal
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 }} //end rp::hal


rplidar_ros
Author(s):
autogenerated on Fri Aug 28 2015 12:46:43