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 @@ - -
-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 -