diff -r 6efc85c5493e -r 1c1e3599d66a doc/doxygen/html/can__uvccm__win32_8cpp-source.html --- a/doc/doxygen/html/can__uvccm__win32_8cpp-source.html Mon Feb 11 11:00:12 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ - - -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 Mon Jul 2 19:10:16 2007 for CanFestival by  - -doxygen 1.5.1
- -