diff -r 003cc3c63855 -r f49e5a6b7804 doc/doxygen/html/can__uvccm__win32_8cpp-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/doxygen/html/can__uvccm__win32_8cpp-source.html Fri Jun 08 09:23:56 2007 +0200 @@ -0,0 +1,357 @@ + + +CanFestival: drivers/can_uvccm_win32/can_uvccm_win32.cpp Source File + + + + +
+
+
+
+ +

can_uvccm_win32.cpp

Go to the documentation of this file.
00001 // can_uvccm_win32 adapter (http://www.gridconnect.com)
+00002 // driver for CanFestival-3 Win32 port
+00003 // Copyright (C) 2007 Leonid Tochinski, ChattenAssociates, Inc.
+00004 
+00005 
+00006 #include <sstream>
+00007 #include <iomanip>
+00008 #if 0  // change to 1 if you use boost
+00009 #include <boost/algorithm/string/case_conv.hpp>
+00010 #else
+00011 #include <algorithm>
+00012 #endif
+00013 
+00014 extern "C" {
+00015 #include "can_driver.h"
+00016 }
+00017 class can_uvccm_win32
+00018    {
+00019    public:
+00020       class error
+00021         {
+00022         };
+00023       can_uvccm_win32(s_BOARD *board);
+00024       ~can_uvccm_win32();
+00025       bool send(const Message *m);
+00026       bool receive(Message *m);
+00027    private:
+00028       bool open_rs232(int port = 1, int baud_rate = 57600);
+00029       bool close_rs232();
+00030       bool get_can_data(const char* can_cmd_buf, long& bufsize, Message* m);
+00031       bool set_can_data(const Message& m, std::string& can_cmd);
+00032    private:
+00033       HANDLE m_port;
+00034       HANDLE m_read_event;
+00035       HANDLE m_write_event;
+00036       std::string m_residual_buffer;
+00037    };
+00038 
+00039 can_uvccm_win32::can_uvccm_win32(s_BOARD *board) : m_port(INVALID_HANDLE_VALUE),
+00040       m_read_event(0),
+00041       m_write_event(0)
+00042    {
+00043    if (strcmp( board->baudrate, "125K") || !open_rs232(1))
+00044       throw error();
+00045    }
+00046 
+00047 can_uvccm_win32::~can_uvccm_win32()
+00048    {
+00049    close_rs232();
+00050    }
+00051 
+00052 bool can_uvccm_win32::send(const Message *m)
+00053    {
+00054    if (m_port == INVALID_HANDLE_VALUE)
+00055       return false;
+00056 
+00057    // build can_uvccm_win32 command string
+00058    std::string can_cmd;
+00059    set_can_data(*m, can_cmd);
+00060 
+00061    OVERLAPPED overlapped;
+00062    ::memset(&overlapped, 0, sizeof overlapped);
+00063    overlapped.hEvent = m_write_event;
+00064    ::ResetEvent(overlapped.hEvent);
+00065 
+00066    unsigned long bytes_written = 0;
+00067    ::WriteFile(m_port, can_cmd.c_str(), (unsigned long)can_cmd.size(), &bytes_written, &overlapped);
+00068    // wait for write operation completion
+00069    enum { WRITE_TIMEOUT = 1000 };
+00070    ::WaitForSingleObject(overlapped.hEvent, WRITE_TIMEOUT);
+00071    // get number of bytes written
+00072    ::GetOverlappedResult(m_port, &overlapped, &bytes_written, FALSE);
+00073 
+00074    bool result = (bytes_written == can_cmd.size());
+00075 
+00076    return result;
+00077    }
+00078 
+00079 
+00080 bool can_uvccm_win32::receive(Message *m)
+00081    {
+00082    if (m_port == INVALID_HANDLE_VALUE)
+00083       return false;
+00084 
+00085    long res_buffer_size = (long)m_residual_buffer.size();
+00086    bool result = get_can_data(m_residual_buffer.c_str(), res_buffer_size, m);
+00087    if (result)
+00088       {
+00089       m_residual_buffer.erase(0, res_buffer_size);
+00090       return true;
+00091       }
+00092 
+00093    enum { READ_TIMEOUT = 500 };
+00094 
+00095    OVERLAPPED overlapped;
+00096    ::memset(&overlapped, 0, sizeof overlapped);
+00097    overlapped.hEvent = m_read_event;
+00098    ::ResetEvent(overlapped.hEvent);
+00099    unsigned long event_mask = 0;
+00100 
+00101    if (FALSE == ::WaitCommEvent(m_port, &event_mask, &overlapped) && ERROR_IO_PENDING == ::GetLastError())
+00102       {
+00103       if (WAIT_TIMEOUT == ::WaitForSingleObject(overlapped.hEvent, READ_TIMEOUT))
+00104          return false;
+00105       }
+00106 
+00107    // get number of bytes in the input que
+00108    COMSTAT stat;
+00109    ::memset(&stat, 0, sizeof stat);
+00110    unsigned long errors = 0;
+00111    ::ClearCommError(m_port, &errors, &stat);
+00112    if (stat.cbInQue == 0)
+00113       return false;
+00114    char buffer[3000];
+00115 
+00116    unsigned long bytes_to_read = min(stat.cbInQue, sizeof (buffer));
+00117 
+00118    unsigned long bytes_read = 0;
+00119    ::ReadFile(m_port, buffer, bytes_to_read, &bytes_read, &overlapped);
+00120    // wait for read operation completion
+00121    ::WaitForSingleObject(overlapped.hEvent, READ_TIMEOUT);
+00122    // get number of bytes read
+00123    ::GetOverlappedResult(m_port, &overlapped, &bytes_read, FALSE);
+00124    result = false;
+00125    if (bytes_read > 0)
+00126       {
+00127       m_residual_buffer.append(buffer, bytes_read);
+00128       res_buffer_size = (long)m_residual_buffer.size();
+00129       result = get_can_data(m_residual_buffer.c_str(), res_buffer_size, m);
+00130       if (result)
+00131          m_residual_buffer.erase(0, res_buffer_size);
+00132       }
+00133    return result;
+00134    }
+00135 
+00136 bool can_uvccm_win32::open_rs232(int port, int baud_rate)
+00137    {
+00138    if (m_port != INVALID_HANDLE_VALUE)
+00139       return true;
+00140 
+00141    std::ostringstream device_name;
+00142    device_name << "COM" << port;
+00143 
+00144    m_port = ::CreateFile(device_name.str().c_str(),
+00145                          GENERIC_READ | GENERIC_WRITE,
+00146                          0,   // exclusive access
+00147                          NULL,   // no security
+00148                          OPEN_EXISTING,
+00149                          FILE_FLAG_OVERLAPPED,   // overlapped I/O
+00150                          NULL); // null template
+00151 
+00152    // Check the returned handle for INVALID_HANDLE_VALUE and then set the buffer sizes.
+00153    if (m_port == INVALID_HANDLE_VALUE)
+00154       return false;
+00155 
+00156    //  SetCommMask(m_hCom,EV_RXCHAR|EV_TXEMPTY|EV_CTS|EV_DSR|EV_RLSD|EV_BREAK|EV_ERR|EV_RING); //
+00157    ::SetCommMask(m_port, EV_RXFLAG);
+00158 
+00159    COMMTIMEOUTS timeouts;
+00160    ::memset(&timeouts, 0, sizeof (timeouts));
+00161    timeouts.ReadIntervalTimeout = -1;
+00162    timeouts.ReadTotalTimeoutConstant = 0;
+00163    timeouts.ReadTotalTimeoutMultiplier = 0;
+00164    timeouts.WriteTotalTimeoutConstant = 5000;
+00165    timeouts.WriteTotalTimeoutMultiplier = 0;
+00166    SetCommTimeouts(m_port, &timeouts); //
+00167 
+00168    ::SetupComm(m_port, 1024, 512); // set buffer sizes
+00169 
+00170    // Port settings are specified in a Data Communication Block (DCB). The easiest way to initialize a DCB is to call GetCommState to fill in its default values, override the values that you want to change and then call SetCommState to set the values.
+00171    DCB dcb;
+00172    ::memset(&dcb, 0, sizeof (dcb));
+00173    ::GetCommState(m_port, &dcb);
+00174    dcb.BaudRate = baud_rate;
+00175    dcb.ByteSize = 8;
+00176    dcb.Parity = NOPARITY;
+00177    dcb.StopBits = ONESTOPBIT;
+00178    dcb.fAbortOnError = TRUE;
+00179    dcb.EvtChar = 0x0A; // '\n' character
+00180    ::SetCommState(m_port, &dcb);
+00181 
+00182    ::PurgeComm(m_port, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+00183 
+00184    m_read_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+00185    m_write_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+00186 
+00187    return true;
+00188    }
+00189 
+00190 bool can_uvccm_win32::close_rs232()
+00191    {
+00192    if (m_port != INVALID_HANDLE_VALUE)
+00193       {
+00194       ::PurgeComm(m_port, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+00195       ::CloseHandle(m_port);
+00196       m_port = INVALID_HANDLE_VALUE;
+00197       ::CloseHandle(m_read_event);
+00198       m_read_event = 0;
+00199       ::CloseHandle(m_write_event);
+00200       m_write_event = 0;
+00201       m_residual_buffer.clear();
+00202       }
+00203    return true;
+00204    }
+00205 
+00206 bool can_uvccm_win32::get_can_data(const char* can_cmd_buf, long& bufsize, Message* m)
+00207    {
+00208    if (bufsize < 5)
+00209       {
+00210       bufsize = 0;
+00211       return false;
+00212       }
+00213 
+00214    Message msg;
+00215    ::memset(&msg, 0 , sizeof (msg));
+00216    char colon = 0, type = 0, request = 0;
+00217    std::istringstream buf(std::string(can_cmd_buf, bufsize));
+00218    buf >> colon >> type >> std::hex >> msg.cob_id.w >> request;
+00219    if (colon != ':' || (type != 'S' && type != 'X'))
+00220       {
+00221       bufsize = 0;
+00222       return false;
+00223       }
+00224    if (request == 'N')
+00225       {
+00226       msg.rtr = 0;
+00227       for (msg.len = 0; msg.len < 8; ++msg.len)
+00228          {
+00229          std::string data_byte_str;
+00230          buf >> std::setw(2) >> data_byte_str;
+00231          if (data_byte_str[0] == ';')
+00232             break;
+00233          long byte_val = -1;
+00234          std::istringstream(data_byte_str) >> std::hex >> byte_val;
+00235          if (byte_val == -1)
+00236             {
+00237             bufsize = 0;
+00238             return false;
+00239             }
+00240          msg.data[msg.len] = (UNS8)byte_val;
+00241          }
+00242       if (msg.len == 8)
+00243          {
+00244          char semicolon = 0;
+00245          buf >> semicolon;
+00246          if (semicolon != ';')
+00247             {
+00248             bufsize = 0;
+00249             return false;
+00250             }
+00251          }
+00252 
+00253       }
+00254    else if (request == 'R')
+00255       {
+00256       msg.rtr = 1;
+00257       buf >> msg.len;
+00258       }
+00259    else
+00260       {
+00261       bufsize = 0;
+00262       return false;
+00263       }
+00264 
+00265    bufsize = buf.tellg();
+00266 
+00267    *m = msg;
+00268    return true;
+00269    }
+00270 
+00271 bool can_uvccm_win32::set_can_data(const Message& m, std::string& can_cmd)
+00272    {
+00273    // build can_uvccm_win32 command string
+00274    std::ostringstream can_cmd_str;
+00275    can_cmd_str << ":S" << std::hex << m.cob_id.w;
+00276    if (m.rtr == 1)
+00277       {
+00278       can_cmd_str << 'R' << (long)m.len;
+00279       }
+00280    else
+00281       {
+00282       can_cmd_str << 'N';
+00283       for (int i = 0; i < m.len; ++i)
+00284          can_cmd_str << std::hex << std::setfill('0') << std::setw(2) << (long)m.data[i];
+00285       }
+00286    can_cmd_str << ';';
+00287    can_cmd = can_cmd_str.str();
+00288 #ifdef BOOST_VERSION
+00289    boost::to_upper(can_cmd);
+00290 #else
+00291    std::transform(can_cmd.begin(),can_cmd.end(),can_cmd.begin(),::toupper);
+00292 #endif
+00293    return true;
+00294    }
+00295 
+00296 
+00297 //------------------------------------------------------------------------
+00298 extern "C"
+00299    UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m)
+00300    {
+00301    return (UNS8)(!(reinterpret_cast<can_uvccm_win32*>(fd0)->receive(m)));
+00302    }
+00303 
+00304 extern "C"
+00305    UNS8 canSend_driver(CAN_HANDLE fd0, Message *m)
+00306    {
+00307    return (UNS8)reinterpret_cast<can_uvccm_win32*>(fd0)->send(m);
+00308    }
+00309 
+00310 extern "C"
+00311    CAN_HANDLE canOpen_driver(s_BOARD *board)
+00312    {
+00313    try
+00314       {
+00315       return (CAN_HANDLE) new can_uvccm_win32(board);
+00316       }
+00317    catch (can_uvccm_win32::error&)
+00318       {
+00319       return NULL;
+00320       }
+00321    }
+00322 
+00323 extern "C"
+00324    int canClose_driver(CAN_HANDLE inst)
+00325    {
+00326    delete reinterpret_cast<can_uvccm_win32*>(inst);
+00327    return 1;
+00328    }
+00329 
+00330 
+00331    
+

Generated on Fri Jun 8 08:51:38 2007 for CanFestival by  + +doxygen 1.5.1
+ +