cmt1.cpp

00001 /*! \file Cmt1.cpp
00002 
00003         For information about objects in this file, see the appropriate header:
00004         \ref Cmt1.h
00005 
00006         \section FileCopyright Copyright Notice 
00007         Copyright (C) Xsens Technologies B.V., 2006.  All rights reserved.
00008         
00009         This source code is intended for use only by Xsens Technologies BV and
00010         those that have explicit written permission to use it from
00011         Xsens Technologies BV.
00012         
00013         THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
00014         KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
00015         IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
00016         PARTICULAR PURPOSE.
00017         
00018         \section FileChangelog        Changelog
00019         \par 2006-04-12, v0.0.1
00020         \li Job Mulder:        Created
00021         \par 2006-07-21, v0.1.0
00022         \li Job Mulder:        Updated file for release 0.1.0
00023 */
00024 
00025 #include "cmt1.h"
00026 #include <errno.h>
00027 #ifndef _WIN32
00028 #        include <stdlib.h>
00029 #        include <unistd.h>                // close
00030 #        include <sys/ioctl.h>        // ioctl
00031 #        include <fcntl.h>                // open, O_RDWR
00032 #        include <string.h>                // strcpy
00033 #        include <sys/param.h>
00034 // We have to redefine PATH_MAX from 4096 to CMT_MAX_FILENAME_LENGTH to mainain compatibility
00035 // The PATH_MAX definition is used by realpath() to determine the maximum path length. According
00036 // to the realpath (3) man page, the function is best avoided and it might be necessary to
00037 // write a custom function for it (couldn't find a proper replacement).
00038 #        undef PATH_MAX
00039 #        define PATH_MAX CMT_MAX_FILENAME_LENGTH
00040 #else
00041 #   include <io.h>
00042 #endif
00043 
00044 #ifndef _CRT_SECURE_NO_DEPRECATE
00045 #        define _CRT_SECURE_NO_DEPRECATE
00046 #        ifdef _WIN32
00047 #                pragma warning(disable:4996)
00048 #        endif
00049 #endif
00050 
00051 #ifdef _WIN32
00052 #        define FSEEK(x)                _fseeki64(m_handle, x, SEEK_SET)
00053 #        define FSEEK_R(x)        _fseeki64(m_handle, x, SEEK_END)
00054 #        define FTELL()                _ftelli64(m_handle)
00055 #else
00056 #        define FSEEK(x)                fseeko(m_handle, x, SEEK_SET)
00057 #        define FSEEK_R(x)        fseeko(m_handle, x, SEEK_END)
00058 #        define FTELL()                ftello(m_handle)
00059 #endif
00060 
00061 // The namespace of all Xsens software since 2006.
00062 namespace xsens {
00063 
00064 #ifndef _WIN32
00065 int _wcsnicmp(const wchar_t* s1, const wchar_t* s2,int count)
00066 {
00067         for (int i = 0; i < count; ++i, ++s1, ++s2)
00068                 if (*s1 == L'\0')
00069                         if (*s2 == L'\0')
00070                                 return 0;
00071                         else
00072                                 return -1;
00073                 else
00074                         if (*s2 == L'\0')
00075                                 return 1;
00076                         else
00077                                 if (*s1 < *s2)
00078                                         return -1;
00079                                 else if (*s1 > *s2)
00080                                         return 1;
00081         return 0;
00082 }
00083 #endif
00084 
00085 
00086 #if defined(_DEBUG) || defined(_LOG_ALWAYS)
00087         #if !defined(_LOG_TO_DBVIEW)
00088                 #ifdef _LOG_TO_STDOUT
00089                 #else        // !dbview && !stdout
00090                         FILE* debug_log_fp = NULL;
00091                         int32_t debug_log_valid = 0;
00092                         
00093                         FILE* debug_qlog_fp = NULL;
00094                         int32_t debug_qlog_valid = 0;
00095                 #endif
00096         #endif
00097 
00098 // write to a log file/screen/debug-stream
00099 void CMTLOG(const char *str, ...)
00100 {
00101         #ifdef _LOG_TO_STDOUT
00102                 va_list ptr;
00103                 va_start(ptr,str);
00104                 vprintf(str,ptr);
00105         #else
00106         #ifdef _LOG_TO_DBVIEW
00107                 char buf[2048];
00108 
00109                 va_list ptr;
00110                 va_start(ptr,str);
00111                 vsprintf(buf,str,ptr);
00112 
00113                 OutputDebugString(buf);
00114         #else
00115                 if (debug_log_valid == 0)
00116                 {
00117                         fopen_s(&debug_log_fp,"debug_log_cmt.log","w");
00118                         if (debug_log_fp != NULL)
00119                                 debug_log_valid = 1;
00120                         else
00121                                 debug_log_valid = -1;
00122                 }
00123                 if (debug_log_valid == 1)
00124                 {
00125                         char buf[2048];
00126 
00127                         va_list ptr;
00128                         va_start(ptr,str);
00129                         int32_t sz = vsprintf_s(buf,str,ptr);
00130 
00131                         uint32_t nw = getTimeOfDay();
00132                         fprintf(debug_log_fp,"%5u.%03u %s",nw/1000,nw%1000,buf);
00133                         //fwrite(buf,1,sz,debug_log_fp);
00134                         fflush(debug_log_fp);
00135                 }
00136         #endif
00137         #endif
00138 }
00139 #endif
00140 
00141 // maybe log to nothing at this level
00142 #ifdef _LOG_CMT1
00143         #define CMT1LOG                CMTLOG
00144 #else
00145         #define CMT1LOG(...)
00146 #endif
00147 
00148 //////////////////////////////////////////////////////////////////////////////////////////
00149 ///////////////////////////////////////// Cmt1s  /////////////////////////////////////////
00150 //////////////////////////////////////////////////////////////////////////////////////////
00151 
00152 //////////////////////////////////////////////////////////////////////////////////////////
00153 // Default constructor, initializes all members to their default values.
00154 Cmt1s::Cmt1s() :
00155         m_onBytesReceived(NULL)
00156 {
00157         m_port = 0;
00158         m_isOpen = false;
00159         m_lastResult = XRV_OK;
00160         m_timeout = CMT1_DEFAULT_TIMEOUT;
00161         m_endTime = 0;
00162         m_baudrate = 0;
00163 
00164         #ifdef _LOG_RX_TX
00165                 rx_log = NULL;
00166                 tx_log = NULL;
00167         #endif
00168 }
00169 
00170 //////////////////////////////////////////////////////////////////////////////////////////
00171 // Destructor, de-initializes, frees memory allocated for buffers, etc.
00172 Cmt1s::~Cmt1s()
00173 {
00174         close();
00175 }
00176 
00177 //////////////////////////////////////////////////////////////////////////////////////////
00178 // Close the serial communication port.
00179 XsensResultValue Cmt1s::close (void)
00180 {
00181         #ifdef _LOG_RX_TX
00182                 if (rx_log != NULL)
00183                         fclose(rx_log);
00184                 if (tx_log != NULL)
00185                         fclose(tx_log);
00186                 rx_log = NULL;
00187                 tx_log = NULL;
00188         #endif
00189         if (!m_isOpen)
00190                 return m_lastResult = XRV_NOPORTOPEN;
00191         
00192         #ifdef _WIN32
00193                 ::FlushFileBuffers(m_handle);
00194                 // read all data before closing the handle, a Flush is not enough for FTDI devices unfortunately
00195                 // we first need to set the COMM timeouts to instantly return when no more data is available
00196                         COMMTIMEOUTS cto;
00197                         ::GetCommTimeouts(m_handle,&cto);
00198                         cto.ReadIntervalTimeout = MAXDWORD;
00199                         cto.ReadTotalTimeoutConstant = 0;
00200                         cto.ReadTotalTimeoutMultiplier = 0;
00201                         ::SetCommTimeouts(m_handle,&cto);
00202                         char buffer[1024];
00203                         uint32_t length;
00204                         do {
00205                                 ::ReadFile(m_handle, buffer, 1024, &length, NULL);
00206                         } while (length > 0);
00207                 BOOL murf = ::CloseHandle(m_handle);
00208         #else
00209                 ::close(m_handle);
00210         #endif
00211         m_isOpen = false;
00212         m_endTime = 0;
00213 
00214         return m_lastResult = XRV_OK;
00215 }
00216 
00217 //////////////////////////////////////////////////////////////////////////////////////////
00218 // Manipulate the Serial control lines
00219 XsensResultValue Cmt1s::escape (const CmtControlLine mask, const CmtControlLine state)
00220 {
00221         if (!m_isOpen)
00222                 return (m_lastResult = XRV_NOPORTOPEN);
00223 #ifdef _WIN32
00224         BOOL rv = 0;
00225         if (mask & CMT_CONTROL_DTR)
00226         {
00227                 if (state & CMT_CONTROL_DTR)
00228                         rv = EscapeCommFunction(m_handle,SETDTR);
00229                 else
00230                         rv = EscapeCommFunction(m_handle,CLRDTR);
00231         }
00232 
00233         if (mask & CMT_CONTROL_RTS)
00234         {
00235                 if (state & CMT_CONTROL_RTS)
00236                         rv = EscapeCommFunction(m_handle,SETRTS);
00237                 else
00238                         rv = EscapeCommFunction(m_handle,CLRRTS);
00239         }
00240         if (rv)
00241                 return m_lastResult = XRV_OK;
00242         else
00243                 return m_lastResult = XRV_ERROR;
00244 #else
00245         bool rv = true;
00246         int32_t status;
00247         if (mask & CMT_CONTROL_DTR)
00248         {
00249                 if (ioctl(m_handle, TIOCMGET, &status) == -1)
00250                 {
00251                         if (state & CMT_CONTROL_DTR) status |= TIOCM_DTR;
00252                         else status &= ~TIOCM_DTR;
00253                         rv = (ioctl(m_handle, TIOCMSET, &status) == -1);
00254                 }
00255                 else
00256                         rv = false;
00257         }
00258         if (rv && (mask & CMT_CONTROL_RTS))
00259         {
00260                 if (ioctl(m_handle, TIOCMGET, &status) == -1)
00261                 {
00262                         if (state & CMT_CONTROL_RTS) status |= TIOCM_RTS;
00263                         else status &= ~TIOCM_RTS;
00264                         rv = (ioctl(m_handle, TIOCMSET, &status) == -1);
00265                 }
00266                 else
00267                         rv = false;
00268         }
00269         if (rv)
00270                 return m_lastResult = XRV_OK;
00271         else
00272                 return m_lastResult = XRV_ERROR;
00273 #endif
00274 }
00275 
00276 //////////////////////////////////////////////////////////////////////////////////////////
00277 // Flush all data to be transmitted / received.
00278 XsensResultValue Cmt1s::flushData (void)
00279 {
00280         #ifdef _WIN32
00281                 // Remove any 'old' data in buffer
00282                 PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
00283         #else
00284                 tcflush(m_handle, TCIOFLUSH);
00285         #endif
00286         m_endTime = 0;
00287         return (m_lastResult = XRV_OK);
00288 }
00289 
00290 //////////////////////////////////////////////////////////////////////////////////////////
00291 // Open a communication channel to the given serial port name.
00292 XsensResultValue Cmt1s::open(  const char *portName,
00293                                                 const uint32_t baudRate,
00294                                                 uint32_t readBufSize,
00295                                                 uint32_t writeBufSize)
00296 {
00297         m_endTime = 0;
00298 
00299         CMT1LOG("L1: Open port %s at %d baud\n", portName, baudRate);
00300 
00301         if (m_isOpen)
00302         {
00303                 CMT1LOG("L1: Port already open\n");
00304                 return (m_lastResult = XRV_ALREADYOPEN);
00305         }
00306         m_baudrate = baudRate;
00307         
00308 #ifdef _WIN32
00309         char winPortName[32];
00310         
00311         // Open port
00312         sprintf(winPortName, "\\\\.\\%s", portName);
00313         m_handle = CreateFile(winPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
00314                                                                         OPEN_EXISTING, 0, NULL);
00315         if (m_handle == INVALID_HANDLE_VALUE)
00316         {
00317                 CMT1LOG("L1: Port cannot be opened\n");
00318                 return (m_lastResult = XRV_INPUTCANNOTBEOPENED);
00319         }
00320 
00321         // Once here, port is open
00322         m_isOpen = true;
00323 
00324         //Get the current state & then change it
00325         GetCommState(m_handle, &m_commState);        // Get current state
00326 
00327         m_commState.BaudRate = baudRate;                        // Setup the baud rate
00328         m_commState.Parity = NOPARITY;                                // Setup the Parity
00329         m_commState.ByteSize = 8;                                        // Setup the data bits
00330         m_commState.StopBits = TWOSTOPBITS;                        // Setup the stop bits
00331         m_commState.fDsrSensitivity = FALSE;                // Setup the flow control 
00332         m_commState.fOutxCtsFlow = FALSE;                        // NoFlowControl:
00333         m_commState.fOutxDsrFlow = FALSE;
00334         m_commState.fOutX = FALSE;
00335         m_commState.fInX = FALSE;
00336         if (!SetCommState(m_handle, (LPDCB)&m_commState)) {// Set new state
00337                 // Bluetooth ports cannot always be opened with 2 stopbits
00338                 // Now try to open port with 1 stopbit. 
00339                 m_commState.StopBits = ONESTOPBIT;
00340                 if (!SetCommState(m_handle, (LPDCB)&m_commState)) {
00341                         CloseHandle(m_handle);
00342                         m_handle = INVALID_HANDLE_VALUE;
00343                         m_isOpen = false;
00344                         return (m_lastResult = XRV_INPUTCANNOTBEOPENED);
00345                 }
00346         }
00347         m_port = atoi(&portName[3]);
00348         sprintf(m_portname, "%s", portName);
00349 
00350         setTimeout(m_timeout);
00351 
00352         // Other initialization functions
00353         EscapeCommFunction(m_handle, SETRTS);                // Enable RTS (for Xbus Master use)
00354         // Set DTR (Calibration sensors need DTR to startup, won't hurt otherwise
00355         EscapeCommFunction(m_handle, SETDTR);
00356         SetupComm(m_handle,readBufSize,writeBufSize);        // Set queue size
00357 
00358         // Remove any 'old' data in buffer
00359         //PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
00360         PurgeComm(m_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
00361 #else // !_WIN32
00362         (void)readBufSize;
00363         (void)writeBufSize;
00364         // Open port
00365         m_handle = ::open(portName, O_RDWR | O_NOCTTY);
00366         // O_RDWR: Read+Write
00367         // O_NOCTTY: Raw input, no "controlling terminal"
00368         // O_NDELAY: Don't care about DCD signal
00369 
00370         if (m_handle < 0) {
00371                 // Port not open
00372                 return m_lastResult = XRV_INPUTCANNOTBEOPENED;
00373         }
00374 
00375         // Once here, port is open
00376         m_isOpen = true;
00377 
00378         /* Start configuring of port for non-canonical transfer mode */
00379         // Get current options for the port
00380         tcgetattr(m_handle, &m_commState);
00381         
00382         // Set baudrate. 
00383         cfsetispeed(&m_commState, baudRate);
00384         cfsetospeed(&m_commState, baudRate);
00385         
00386         // Enable the receiver and set local mode
00387         m_commState.c_cflag |= (CLOCAL | CREAD);
00388         // Set character size to data bits and set no parity Mask the characte size bits
00389         m_commState.c_cflag &= ~(CSIZE|PARENB);
00390         m_commState.c_cflag |= CS8;                // Select 8 data bits
00391         m_commState.c_cflag |= CSTOPB;        // send 2 stop bits
00392         // Disable hardware flow control
00393         m_commState.c_cflag &= ~CRTSCTS;
00394         m_commState.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
00395         // Disable software flow control
00396         m_commState.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
00397         // Set Raw output
00398         m_commState.c_oflag &= ~OPOST;
00399         // Timeout 0.001 sec for first byte, read minimum of 0 bytes
00400         m_commState.c_cc[VMIN]     = 0;
00401         m_commState.c_cc[VTIME]    = (m_timeout+99)/100;        // 1
00402 
00403         // Set the new options for the port
00404         tcsetattr(m_handle,TCSANOW, &m_commState);
00405         
00406         m_port = 1;
00407         sprintf(m_portname, "%s", portName);
00408 
00409         tcflush(m_handle, TCIOFLUSH);
00410 
00411         // setting RTS and DTR; RTS for Xbus Master, DTR for calibration sensors
00412         int cmbits;
00413         if (ioctl(m_handle, TIOCMGET, &cmbits) < 0)
00414         {
00415                 return (m_lastResult = XRV_ERROR);
00416         }
00417         
00418         cmbits |= TIOCM_RTS|TIOCM_DTR;
00419         
00420         if (ioctl(m_handle, TIOCMSET, &cmbits) < 0)
00421         {
00422                 return (m_lastResult = XRV_ERROR);
00423         }
00424 #endif // !_WIN32
00425 
00426         CMT1LOG("L1: Port opened\n");
00427         return (m_lastResult = XRV_OK);
00428 }
00429 
00430 #ifdef _WIN32
00431 //////////////////////////////////////////////////////////////////////////////////////////
00432 // Open a communication channel to the given COM port number.
00433 XsensResultValue Cmt1s::open (        const uint32_t portNumber,
00434                                                 const uint32_t baudRate,
00435                                                 uint32_t readBufSize,
00436                                                 uint32_t writeBufSize)
00437 {
00438         char comFileName[32];
00439         
00440         // Create file name
00441         sprintf(comFileName, "COM%d", portNumber);
00442         
00443         return Cmt1s::open(comFileName, baudRate, readBufSize, writeBufSize); 
00444 }
00445 #endif        
00446 
00447 //////////////////////////////////////////////////////////////////////////////////////////
00448 // Read data from the serial port and put it into the data buffer.
00449 XsensResultValue Cmt1s::readData (const uint32_t maxLength, uint8_t* data,
00450                                                                                                         uint32_t* length)
00451 {
00452         CMT1LOG("L1: readData, maxlength=%u, length=%p\n",maxLength,length);
00453         uint32_t ln;
00454         if (length == NULL)
00455                 length = &ln;
00456 
00457         if (!m_isOpen)
00458                 return (m_lastResult = XRV_NOPORTOPEN);
00459 
00460 #ifdef _WIN32
00461         BOOL rres = ::ReadFile(m_handle, data, maxLength, length, NULL);
00462         CMT1LOG("L1: readData, ReadFile returns %u (%u)\n",rres,*length);
00463         if (m_onBytesReceived != NULL && *length > 0)
00464         {
00465                 CmtBinaryData* bytes = (CmtBinaryData*) malloc(sizeof(CmtBinaryData));
00466                 bytes->m_size = *length;
00467                 bytes->m_portNr = m_port;
00468                 memcpy(bytes->m_data,data,*length);
00469 #ifdef _LOG_CALLBACKS
00470                 CMTLOG("C1: onBytesReceived(%d,(%d,%d),%p)\n",(int32_t) m_onBytesReceivedInstance, (int32_t) bytes->m_size, (int32_t) bytes->m_portNr, m_onBytesReceivedParam);
00471 #endif
00472                 m_onBytesReceived(m_onBytesReceivedInstance,CMT_CALLBACK_ONBYTESRECEIVED,bytes,m_onBytesReceivedParam);
00473         }
00474 
00475         if (!rres)
00476         {
00477                 CMT1LOG("L1: readData, ReadFile returned error %u\n",::GetLastError());
00478                 return (m_lastResult = XRV_ERROR);
00479         }
00480 #else
00481         *length = read(m_handle, data, maxLength);
00482 #endif
00483 
00484 #ifdef _LOG_RX_TX
00485         if (*length > 0)
00486         {
00487                 if (rx_log == NULL)
00488                 {
00489                         char fname[CMT_MAX_FILENAME_LENGTH];
00490                         sprintf(fname,"rx_%03d_%d.log",(int32_t) m_port,m_baudrate);
00491                         rx_log = fopen(fname,"wb");
00492                 }
00493                 fwrite(data,1,*length,rx_log);
00494         }
00495 #endif
00496 
00497         CMT1LOG((length[0]?"L1: readData returned success, read %u of %u bytes, first: %02x\n":"L1: readData returned success, read %u bytes\n"),length[0],maxLength,data[0]);
00498         return (m_lastResult = XRV_OK);
00499 }
00500 
00501 //////////////////////////////////////////////////////////////////////////////////////////
00502 // Set the callback function for when bytes have been received
00503 XsensResultValue Cmt1s::setCallbackFunction(CmtCallbackType tp, int32_t instance, CmtCallbackFunction func, void* param)
00504 {
00505         if (tp == CMT_CALLBACK_ONBYTESRECEIVED)
00506         {
00507                 m_onBytesReceived = func;
00508                 m_onBytesReceivedInstance = instance;
00509                 m_onBytesReceivedParam = param;
00510                 return m_lastResult = XRV_OK;
00511         }
00512         return m_lastResult = XRV_INVALIDPARAM;
00513 }
00514 
00515 //////////////////////////////////////////////////////////////////////////////////////////
00516 // Set the default timeout value to use in blocking operations.
00517 XsensResultValue Cmt1s::setTimeout (const uint32_t ms)
00518 {
00519         CMT1LOG("L1: Setting timeout to %u ms\n",ms);
00520 
00521         m_timeout = ms;
00522 #ifdef _WIN32
00523         // Set COM timeouts
00524         COMMTIMEOUTS commTimeouts;
00525 
00526         GetCommTimeouts(m_handle,&commTimeouts);        // Fill CommTimeouts structure
00527 
00528         // immediate return if data is available, wait 1ms otherwise
00529         if (m_timeout > 0)
00530         {
00531                 commTimeouts.ReadIntervalTimeout = 0;
00532                 commTimeouts.ReadTotalTimeoutConstant = m_timeout;        // ms time
00533                 commTimeouts.ReadTotalTimeoutMultiplier = 0; 
00534                 commTimeouts.WriteTotalTimeoutConstant = m_timeout;
00535                 commTimeouts.WriteTotalTimeoutMultiplier = 0;
00536         }
00537         else
00538         {
00539         // immediate return whether data is available or not
00540                 commTimeouts.ReadIntervalTimeout = MAXDWORD;
00541                 commTimeouts.ReadTotalTimeoutConstant = 0;
00542                 commTimeouts.ReadTotalTimeoutMultiplier = 0; 
00543                 commTimeouts.WriteTotalTimeoutConstant = 0;
00544                 commTimeouts.WriteTotalTimeoutMultiplier = 0;
00545         }
00546 
00547         SetCommTimeouts(m_handle, &commTimeouts);        // Set CommTimeouts structure
00548 #else
00549         // Timeout 0.1 sec for first byte, read minimum of 0 bytes
00550         m_commState.c_cc[VMIN]     = 0;
00551         m_commState.c_cc[VTIME]    = (m_timeout+99)/100;                // ds time
00552 
00553         // Set the new options for the port if it is open
00554         if (m_isOpen)
00555                 tcsetattr(m_handle,TCSANOW, &m_commState);
00556 #endif
00557         return (m_lastResult = XRV_OK);
00558 }
00559 
00560 //////////////////////////////////////////////////////////////////////////////////////////
00561 // Wait for data to arrive or a timeout to occur.
00562 XsensResultValue Cmt1s::waitForData (const uint32_t maxLength,
00563                                                           uint8_t* data, uint32_t* length)
00564 {
00565         CMT1LOG("L1: waitForData, mto=%u, length=%p\n",m_timeout,length);
00566         uint32_t timeout = m_timeout;
00567 
00568         uint32_t ln;
00569         if (length == NULL)
00570                 length = &ln;
00571         uint32_t eTime = getTimeOfDay(NULL) + timeout;
00572         uint32_t newLength = 0;
00573 
00574         *length = 0;
00575         while ((*length < maxLength) && (getTimeOfDay() <= eTime))
00576         {
00577                 readData(maxLength - *length, data + *length, &newLength);
00578                 *length += newLength;
00579         }
00580         CMT1LOG("L1: waitForData result: read %u of %u bytes\n",length[0],maxLength);
00581 
00582         if (length[0] < maxLength)
00583                 return (m_lastResult = XRV_TIMEOUT);
00584         else
00585                 return (m_lastResult = XRV_OK);
00586 }
00587 
00588 //////////////////////////////////////////////////////////////////////////////////////////
00589 // Write the data to the serial port.
00590 XsensResultValue Cmt1s::writeData (const uint32_t length,  const uint8_t* data,
00591                                                                 uint32_t* written)
00592 {
00593         uint32_t bytes;
00594         if (written == NULL)
00595                 written = &bytes;
00596 
00597         if (!m_isOpen)
00598                 return (m_lastResult = XRV_NOPORTOPEN);
00599 
00600 #ifdef _WIN32
00601         if (WriteFile(m_handle, data, length, written, NULL))
00602         {
00603 #ifdef _LOG_RX_TX
00604                 if (written[0] > 0)
00605                 {
00606                         if (tx_log == NULL)
00607                         {
00608                                 char fname[CMT_MAX_FILENAME_LENGTH];
00609                                 sprintf(fname,"tx_%03d_%d.log",(int32_t) m_port,m_baudrate);
00610                                 tx_log = fopen(fname,"wb");
00611                         }
00612                         fwrite(data,1,*written,tx_log);
00613                 }
00614 #endif
00615                 return (m_lastResult = XRV_OK);
00616         }
00617         else
00618                 return (m_lastResult = XRV_ERROR);
00619 #else
00620         *written = write(m_handle, data, length);
00621 //        if (*written == length)
00622                 return (m_lastResult = XRV_OK);
00623 //        else
00624 //                return (m_lastResult = XRV_ERROR);
00625 #endif
00626 }
00627 
00628 //////////////////////////////////////////////////////////////////////////////////////////
00629 ///////////////////////////////////////// Cmt1f  /////////////////////////////////////////
00630 //////////////////////////////////////////////////////////////////////////////////////////
00631 
00632 //////////////////////////////////////////////////////////////////////////////////////////
00633 // Default constructor, initializes all members to their default values.
00634 Cmt1f::Cmt1f()
00635 {
00636         m_readPos = 0;
00637         m_writePos = 0;
00638         m_lastResult = XRV_OK;
00639         m_reading = true;
00640         m_isOpen = false;
00641         m_filename[0] = '\0';
00642         m_fileSize = 0;
00643         m_readOnly = false;
00644         m_unicode = false;
00645 }
00646 
00647 //////////////////////////////////////////////////////////////////////////////////////////
00648 // Destructor.
00649 Cmt1f::~Cmt1f()
00650 {
00651         close();
00652 }
00653 
00654 //////////////////////////////////////////////////////////////////////////////////////////
00655 // Write data to the end of the file.
00656 XsensResultValue Cmt1f::appendData (const uint32_t length,  const void* data)
00657 {
00658         if (!m_isOpen)
00659                 return m_lastResult = XRV_NOFILEOPEN;
00660         if (m_readOnly)
00661                 return m_lastResult = XRV_READONLY;
00662 
00663         if (m_reading || m_writePos != m_fileSize)
00664         {
00665                 m_reading = false;
00666                 FSEEK_R(0);
00667         }
00668         fwrite(data, 1, length, m_handle);
00669         m_writePos = FTELL();
00670         m_fileSize = m_writePos;
00671 
00672         return (m_lastResult = XRV_OK);
00673 }
00674 
00675 //////////////////////////////////////////////////////////////////////////////////////////
00676 // Close the file.
00677 XsensResultValue Cmt1f::close (void)
00678 {
00679         if (m_isOpen)
00680         {
00681         #ifdef _WIN32
00682                 fflush(m_handle);
00683                 fclose(m_handle);
00684         #else
00685                 ::fflush(m_handle);
00686                 ::fclose(m_handle);
00687         #endif
00688         }
00689         m_isOpen = false;
00690         m_readPos = 0;
00691         m_writePos = 0;
00692         m_reading = true;
00693         m_isOpen = false;
00694         m_fileSize = 0;
00695         m_readOnly = false;
00696 
00697         return m_lastResult = XRV_OK;
00698 }
00699 
00700 //////////////////////////////////////////////////////////////////////////////////////////
00701 // Close the file and delete it.
00702 XsensResultValue Cmt1f::closeAndDelete(void)
00703 {
00704         if (m_isOpen)
00705         {
00706         #ifdef _WIN32
00707                 fflush(m_handle);
00708                 fclose(m_handle);
00709         #else
00710                 ::fflush(m_handle);
00711                 ::fclose(m_handle);
00712         #endif
00713                 if (m_readOnly)
00714                         m_lastResult = XRV_READONLY;
00715                 else
00716                 {
00717 #ifdef _WIN32
00718                         if (m_unicode)
00719                         {
00720                                 if (_wremove(m_filename_w) != 0)
00721                                         m_lastResult = XRV_READONLY;
00722                                 else
00723                                         m_lastResult = XRV_OK;
00724                         }
00725                         else
00726 #endif
00727                         {
00728 #ifdef _WIN32
00729                                 if (_unlink(m_filename) != 0)
00730 #else
00731                                 if (unlink(m_filename) != 0)
00732 #endif
00733                                         m_lastResult = XRV_READONLY;
00734                                 else
00735                                         m_lastResult = XRV_OK;
00736                         }
00737                 }
00738         }
00739         else
00740                 m_lastResult = XRV_NOFILEOPEN;
00741 
00742         m_isOpen = false;
00743         m_readPos = 0;
00744         m_writePos = 0;
00745         m_reading = true;
00746         m_isOpen = false;
00747         m_fileSize = 0;
00748         m_readOnly = false;
00749 
00750         return m_lastResult;
00751 }
00752 
00753 //////////////////////////////////////////////////////////////////////////////////////////
00754 // Create a new file.
00755 XsensResultValue Cmt1f::create (const char* filename)
00756 {
00757         if (m_isOpen)
00758                 return m_lastResult = XRV_ALREADYOPEN;
00759 
00760         //! \test does this work for non-existing files? Or do we need a check and create?
00761         m_handle = fopen(filename, "w+b");        // open for update (r/w)
00762         if (m_handle == NULL)
00763                 return m_lastResult = XRV_OUTPUTCANNOTBEOPENED;
00764 
00765         #ifdef _WIN32
00766                 if (_fullpath(m_filename,filename,CMT_MAX_FILENAME_LENGTH) == NULL)
00767                 {
00768                         fclose(m_handle);
00769                         remove(filename);
00770                         return m_lastResult = XRV_INVALIDPARAM;
00771                 }
00772         #else
00773                 // based on the assumption that this doesn't concern the serial port, handle
00774                 // it the same way using realpath(). Apparently realpath() doesn't require a  
00775                 // maximum length. One would possibly want to write a wrapper for it.
00776                 if (realpath(filename, m_filename) == NULL)
00777         {
00778             fclose(m_handle);
00779             remove(filename);
00780             return m_lastResult = XRV_INVALIDPARAM;
00781         }
00782         #endif
00783         mbstowcs(m_filename_w,m_filename,CMT_MAX_FILENAME_LENGTH);
00784         m_unicode = false;
00785 
00786         m_isOpen = true;
00787         m_readPos = 0;
00788         m_writePos = 0;
00789         m_fileSize = 0;
00790         m_reading = true;
00791         m_readOnly = false;
00792         return m_lastResult = XRV_OK;
00793 }
00794 
00795 //////////////////////////////////////////////////////////////////////////////////////////
00796 // Create a new file.
00797 XsensResultValue Cmt1f::create (const wchar_t* filename)
00798 {
00799         if (m_isOpen)
00800                 return m_lastResult = XRV_ALREADYOPEN;
00801 
00802 #ifdef _WIN32
00803         //! \test does this work for non-existing files? Or do we need a check and create?
00804         m_handle = _wfopen(filename, L"w+b");        // open for update (r/w)
00805         if (m_handle == NULL)
00806                 return m_lastResult = XRV_OUTPUTCANNOTBEOPENED;
00807 
00808         if (_wfullpath(m_filename_w,filename,CMT_MAX_FILENAME_LENGTH) == NULL)
00809         {
00810                 fclose(m_handle);
00811                 _wremove(filename);
00812                 return m_lastResult = XRV_INVALIDPARAM;
00813         }
00814         wcstombs(m_filename,m_filename_w,CMT_MAX_FILENAME_LENGTH);
00815 
00816         m_isOpen = true;
00817         m_readPos = 0;
00818         m_writePos = 0;
00819         m_fileSize = 0;
00820         m_reading = true;
00821         m_readOnly = false;
00822 #else
00823         char tFilename[CMT_MAX_FILENAME_LENGTH*2];
00824         wcstombs(tFilename, filename, CMT_MAX_FILENAME_LENGTH);
00825         XsensResultValue res = create(tFilename);
00826         if (res != XRV_OK)
00827                 return res;
00828 #endif
00829         m_unicode = true;
00830         return m_lastResult = XRV_OK;
00831 }
00832 
00833 //////////////////////////////////////////////////////////////////////////////////////////
00834 // Delete the given data from the file.
00835 XsensResultValue Cmt1f::deleteData (const CmtFilePos start, const uint32_t length)
00836 {
00837         if (!m_isOpen)
00838                 return m_lastResult = XRV_NOFILEOPEN;
00839         if (m_readOnly)
00840                 return m_lastResult = XRV_READONLY;
00841 
00842         gotoWrite();
00843 
00844         CmtFilePos wPos = start;
00845         CmtFilePos rPos = wPos + length;
00846 
00847         size_t read1;
00848         CmtFilePos endPos = (start + (CmtFilePos) length);
00849         if (endPos < m_fileSize)
00850         {
00851                 CmtFilePos remaining = m_fileSize - endPos;
00852                 char buffer[512];
00853 
00854                 // copy data
00855                 FSEEK(rPos);
00856 
00857                 while (remaining > 0)
00858                 {
00859                         if (remaining >= 512)
00860                                 read1 = fread(buffer,1,512,m_handle);
00861                         else
00862                                 read1 = fread(buffer,1,(size_t) remaining,m_handle);
00863 
00864                         remaining -= read1;
00865                         rPos += read1;
00866 
00867                         // write block to the correct position
00868                         FSEEK(wPos);
00869                         wPos += fwrite(buffer, 1, read1, m_handle);
00870                         FSEEK(rPos);
00871                 }
00872                 m_fileSize -= length;
00873         }
00874         else
00875         {
00876                 m_fileSize = start;
00877         }
00878 
00879 #ifdef _WIN32
00880         int32_t rv = _chsize(_fileno(m_handle),(int32_t) m_fileSize);
00881 #else
00882         int32_t rv = ftruncate(fileno(m_handle),(int32_t) m_fileSize);
00883 #endif
00884         int32_t eno = 0;
00885         if (rv != 0)
00886                 eno = errno;
00887         m_writePos = start;
00888         FSEEK(wPos);
00889         if (rv != 0)
00890         {
00891                 switch(eno)
00892                 {
00893                 case EACCES:
00894                         return m_lastResult = XRV_BUSY;
00895                 case EBADF:
00896                         return m_lastResult = XRV_INVALIDINSTANCE;
00897                 case ENOSPC:
00898                         return m_lastResult = XRV_OUTOFMEMORY;
00899                 case EINVAL:
00900                         return m_lastResult = XRV_INVALIDPARAM;
00901                 default:
00902                         return m_lastResult = XRV_ERROR;
00903                 }
00904         }
00905 
00906         return m_lastResult = XRV_OK;
00907 }        
00908 
00909 //////////////////////////////////////////////////////////////////////////////////////////
00910 // Find a string of bytes in the file
00911 XsensResultValue Cmt1f::find (const void* needleV, const uint32_t needleLength, CmtFilePos& pos)
00912 {
00913         if (!m_isOpen)
00914                 return m_lastResult = XRV_NOFILEOPEN;
00915 
00916         const char* needle = (const char*) needleV;
00917 
00918         gotoRead();
00919 
00920         pos = 0;
00921 
00922         char buffer[512];
00923         uint32_t bufferPos, needlePos = 0;
00924         size_t readBytes;
00925         if (m_readPos & 0x1FF)                                                                                // read a block of data
00926                 readBytes = fread(buffer,1,(512-((size_t) m_readPos & 0x1FF)),m_handle);
00927         else
00928                 readBytes = fread(buffer,1,512,m_handle);                // read a block of data
00929         
00930         while (readBytes > 0)
00931         {
00932                 m_readPos += readBytes;
00933                 bufferPos = 0;
00934                 
00935                 while (bufferPos < readBytes && needlePos < needleLength)
00936                 {
00937                         if (buffer[bufferPos] == needle[needlePos])
00938                         {
00939                                 // found a byte
00940                                 ++needlePos;
00941                         }
00942                         else
00943                         {
00944                                 if (needlePos > 0)
00945                                         needlePos = 0;
00946                                 else
00947                                 if (buffer[bufferPos] == needle[0])
00948                                 {
00949                                         // found a byte
00950                                         needlePos = 1;
00951                                 }
00952                         }
00953                         ++bufferPos;
00954                 }
00955                 if (needlePos < needleLength)
00956                         readBytes = fread(buffer,1,512,m_handle);        // read next block
00957                 else
00958                 {
00959                         m_readPos = m_readPos + bufferPos - readBytes - needleLength; // or without needleLength
00960                         pos = m_readPos; // - needleLength;
00961                         FSEEK(m_readPos);
00962                         return m_lastResult = XRV_OK;
00963                 }
00964         }
00965         return m_lastResult = XRV_ENDOFFILE;
00966 }
00967 
00968 //////////////////////////////////////////////////////////////////////////////////////////
00969 // Flush all data to be written.
00970 XsensResultValue Cmt1f::flushData (void)
00971 {
00972         fflush(m_handle);
00973 
00974         return m_lastResult = XRV_OK;
00975 }
00976 
00977 //////////////////////////////////////////////////////////////////////////////////////////
00978 // Retrieve the filename that was last successfully opened.
00979 XsensResultValue Cmt1f::getName(char* filename) const
00980 {
00981         strcpy(filename, m_filename);
00982         return m_lastResult = XRV_OK;
00983 }
00984 
00985 //////////////////////////////////////////////////////////////////////////////////////////
00986 // Retrieve the filename that was last successfully opened.
00987 XsensResultValue Cmt1f::getName(wchar_t* filename) const
00988 {
00989 #ifdef _WIN32
00990         wcscpy(filename, m_filename_w);
00991 #else
00992         mbstowcs(filename, m_filename, CMT_MAX_FILENAME_LENGTH);
00993 #endif
00994         return m_lastResult = XRV_OK;
00995 }
00996 
00997 //////////////////////////////////////////////////////////////////////////////////////////
00998 // Change from writing to reading mode
00999 void Cmt1f::gotoRead(void)
01000 {
01001         if (m_reading)
01002                 return;
01003 
01004         FSEEK(m_readPos);
01005         m_reading = true;
01006 }
01007 
01008 //////////////////////////////////////////////////////////////////////////////////////////
01009 // Change from reading to writing mode
01010 void Cmt1f::gotoWrite(void)
01011 {
01012         if (!m_reading)
01013                 return;
01014 
01015         FSEEK(m_writePos);
01016         m_reading = false;
01017 }
01018 
01019 //////////////////////////////////////////////////////////////////////////////////////////
01020 // Insert the given data into the file.
01021 XsensResultValue Cmt1f::insertData (const CmtFilePos start, const uint32_t length, const void* data)
01022 {
01023         if (!m_isOpen)
01024                 return m_lastResult = XRV_NOFILEOPEN;
01025         if (m_readOnly)
01026                 return m_lastResult = XRV_READONLY;
01027 
01028         gotoWrite();
01029 
01030         CmtFilePos rPos = start;
01031         CmtFilePos wPos = rPos + length;
01032 
01033         size_t read1, read2;
01034         CmtFilePos remaining = m_fileSize - start;
01035         size_t bsize = (length > 512)?length:512;
01036         char* buffer1 = (char*) malloc(bsize);
01037         char* buffer2 = (char*) malloc(bsize);
01038         char* btemp;
01039 
01040         // copy data
01041         FSEEK(rPos);
01042 
01043         if (remaining >= (CmtFilePos) bsize)
01044                 read1 = fread(buffer1,1,bsize,m_handle);
01045         else
01046                 read1 = fread(buffer1,1,(size_t) remaining,m_handle);
01047 
01048         remaining -= read1;
01049         rPos += read1;
01050 
01051         while(remaining > 0)
01052         {
01053                 // move data to correct buffer
01054                 read2 = read1;
01055                 btemp = buffer1; buffer1 = buffer2; buffer2 = btemp;
01056 
01057                 // read next block
01058                 if (remaining >= (CmtFilePos) bsize)
01059                         read1 = fread(buffer1,1,bsize,m_handle);
01060                 else
01061                         read1 = fread(buffer1,1,(size_t) remaining,m_handle);
01062 
01063                 remaining -= read1;
01064                 rPos += read1;
01065 
01066                 // write block to the correct position
01067                 FSEEK(wPos);
01068                 wPos += fwrite(buffer2, 1, read2, m_handle);
01069                 FSEEK(rPos);
01070         }
01071 
01072         FSEEK(wPos);
01073         wPos += fwrite(buffer1, 1, read1, m_handle);
01074 
01075         FSEEK(start);
01076         m_writePos = start + fwrite(data, 1, length, m_handle);
01077         m_fileSize += length;
01078 
01079         free(buffer1);
01080         free(buffer2);
01081         return m_lastResult = XRV_OK;
01082 }
01083 
01084 //////////////////////////////////////////////////////////////////////////////////////////
01085 // Open a file.
01086 XsensResultValue Cmt1f::open(const char* filename, const bool create, const bool readOnly)
01087 {
01088         if (m_isOpen)
01089                 return m_lastResult = XRV_ALREADYOPEN;
01090 
01091         //! \test does this work for non-existing files? Or do we need a check and create?
01092         m_readOnly = readOnly;
01093         if (readOnly)
01094                 m_handle = fopen(filename, "rb");        // open for read only (r)
01095         else
01096                 m_handle = fopen(filename, "r+b");        // open for update (r/w)
01097         if (m_handle == NULL)
01098         {
01099                 if (create)
01100                         m_handle = fopen(filename, "w+b");        // create for update (r/w)
01101                 else
01102                 {
01103                         m_handle = fopen(filename, "rb");        // open for read only (r)
01104                         m_readOnly = true;
01105                 }
01106         }
01107         if (m_handle == NULL)
01108                 return m_lastResult = XRV_INPUTCANNOTBEOPENED;
01109 
01110         #ifdef _WIN32
01111                 if (_fullpath(m_filename,filename,CMT_MAX_FILENAME_LENGTH) == NULL)
01112                 {
01113                         fclose(m_handle);
01114                         return m_lastResult = XRV_INVALIDPARAM;
01115                 }
01116         #else
01117             // use the same trick again.
01118                 if (realpath(filename, m_filename) == NULL)
01119                 {
01120                     fclose(m_handle);
01121                     return m_lastResult = XRV_INVALIDPARAM;
01122                 }
01123         #endif
01124         mbstowcs(m_filename_w,m_filename,CMT_MAX_FILENAME_LENGTH);
01125         m_unicode = false;
01126 
01127         m_isOpen = true;
01128         m_readPos = 0;
01129         m_writePos = 0;
01130         m_reading = true;
01131         FSEEK_R(0);
01132         m_fileSize = FTELL();
01133         FSEEK(0);
01134         return (m_lastResult = XRV_OK);
01135 }
01136 
01137 //////////////////////////////////////////////////////////////////////////////////////////
01138 // Open a file.
01139 XsensResultValue Cmt1f::open(const wchar_t* filename, const bool create, const bool readOnly)
01140 {
01141         if (m_isOpen)
01142                 return m_lastResult = XRV_ALREADYOPEN;
01143 
01144 #ifdef _WIN32
01145         //! \test does this work for non-existing files? Or do we need a check and create?
01146         m_readOnly = readOnly;
01147         if (readOnly)
01148                 m_handle = _wfopen(filename, L"rb");        // open for read only (r)
01149         else
01150                 m_handle = _wfopen(filename, L"r+b");        // open for update (r/w)
01151         if (m_handle == NULL)
01152         {
01153                 if (create)
01154                         m_handle = _wfopen(filename, L"w+b");        // create for update (r/w)
01155                 else
01156                 {
01157                         m_handle = _wfopen(filename, L"rb");        // open for read only (r)
01158                         m_readOnly = true;
01159                 }
01160         }
01161         if (m_handle == NULL)
01162                 return m_lastResult = XRV_INPUTCANNOTBEOPENED;
01163 
01164         if (_wfullpath(m_filename_w,filename,CMT_MAX_FILENAME_LENGTH) == NULL)
01165         {
01166                 fclose(m_handle);
01167                 return m_lastResult = XRV_INVALIDPARAM;
01168         }
01169         wcstombs(m_filename,m_filename_w,CMT_MAX_FILENAME_LENGTH);
01170 
01171         m_isOpen = true;
01172         m_readPos = 0;
01173         m_writePos = 0;
01174         m_reading = true;
01175         FSEEK_R(0);
01176         m_fileSize = FTELL();
01177         FSEEK(0);
01178 #else
01179         char tFilename[CMT_MAX_FILENAME_LENGTH*2];
01180         wcstombs(tFilename,filename,CMT_MAX_FILENAME_LENGTH*2);
01181         XsensResultValue res = open(tFilename,create,readOnly);
01182         if (res != XRV_OK)
01183                 return res;
01184 #endif
01185         m_unicode = true;
01186         return m_lastResult = XRV_OK;
01187 }
01188 
01189 //////////////////////////////////////////////////////////////////////////////////////////
01190 // Read data from the file and put it into the data buffer.
01191 XsensResultValue Cmt1f::readData(const uint32_t maxLength, void* data, uint32_t* length)
01192 {
01193         if (!m_isOpen)
01194                 return m_lastResult = XRV_NOFILEOPEN;
01195 
01196         if (maxLength == 0)
01197                 return m_lastResult = XRV_OK;
01198 
01199         uint32_t len;
01200         if (length == NULL)
01201                 length = &len;
01202 
01203         gotoRead();
01204 
01205         length[0] = (uint32_t) fread(data,1,maxLength,m_handle);
01206         if (length[0] == 0)
01207                 return (m_lastResult = XRV_ENDOFFILE);
01208 
01209         m_readPos += length[0];
01210         return m_lastResult = XRV_OK;
01211 }
01212 
01213 //////////////////////////////////////////////////////////////////////////////////////////
01214 // Read data from the file until the terminator and put it into the data buffer.
01215 XsensResultValue Cmt1f::readData (const uint32_t maxLength, const char terminator, void* dataV, uint32_t* length)
01216 {
01217         if (!m_isOpen)
01218                 return m_lastResult = XRV_NOFILEOPEN;
01219 
01220         uint32_t len;
01221         if (length == NULL)
01222                 length = &len;
01223 
01224         char* data = (char*) dataV;
01225         int32_t readChar;
01226 
01227         gotoRead();
01228 
01229         *length = 0;
01230         readChar = (uint32_t) fgetc(m_handle);
01231 
01232         while (!feof(m_handle) && !ferror(m_handle))
01233         {
01234                 data[*length] = (char) readChar;
01235                 ++(*length);
01236                 ++m_readPos;
01237 
01238                 if (((char) readChar == terminator) || ((*length) >= maxLength))
01239                         return m_lastResult = XRV_OK;
01240         }
01241         return m_lastResult = XRV_ENDOFFILE;
01242 }
01243 
01244 //////////////////////////////////////////////////////////////////////////////////////////
01245 // Set the new absolute read position
01246 XsensResultValue Cmt1f::setReadPos (const CmtFilePos pos)
01247 {
01248         if (!m_isOpen)
01249                 return m_lastResult = XRV_NOFILEOPEN;
01250 
01251         if (m_readPos != pos)
01252         {
01253                 m_readPos = pos;
01254                 if (m_reading)
01255                         FSEEK(m_readPos);
01256         }
01257 
01258         return m_lastResult = XRV_OK;
01259 }
01260 
01261 //////////////////////////////////////////////////////////////////////////////////////////
01262 // Set the new absolute write position
01263 XsensResultValue Cmt1f::setWritePos(const CmtFilePos pos)
01264 {
01265         if (!m_isOpen)
01266                 return m_lastResult = XRV_NOFILEOPEN;
01267         if (m_readOnly)
01268                 return m_lastResult = XRV_READONLY;
01269 
01270         if (pos == -1)
01271         {
01272                 if (m_reading)
01273                         m_reading = false;
01274                 FSEEK_R(0);
01275                 m_writePos = FTELL();
01276         }
01277         else
01278         {
01279                 if (m_writePos != pos)
01280                 {
01281                         m_writePos = pos;
01282                         if (!m_reading)
01283                                 FSEEK(m_writePos);
01284                 }
01285         }
01286 
01287         return m_lastResult = XRV_OK;
01288 }
01289 
01290 //////////////////////////////////////////////////////////////////////////////////////////
01291 // Write data to the file.
01292 XsensResultValue Cmt1f::writeData (const uint32_t length,  const void* data)
01293 {
01294         if (!m_isOpen)
01295                 return m_lastResult = XRV_NOFILEOPEN;
01296         if (m_readOnly)
01297                 return m_lastResult = XRV_READONLY;
01298 
01299         gotoWrite();
01300         size_t writeRes = fwrite(data, 1, length, m_handle);
01301         if (writeRes == (size_t)EOF || writeRes < length)
01302         {
01303                 int32_t err = (int32_t)errno;
01304                 switch (err)
01305                 {
01306                 case 0:                        break;
01307                 case ENOSPC:        return m_lastResult = XRV_INSUFFICIENTSPACE;
01308                 case ENOMEM:        return m_lastResult = XRV_OUTOFMEMORY;
01309                 default:                return m_lastResult = XRV_ERROR;
01310                 }
01311         }
01312         m_writePos += writeRes;
01313 
01314         if (m_writePos > m_fileSize)
01315                 m_fileSize = m_writePos;
01316 
01317         return m_lastResult = XRV_OK;
01318 }
01319 
01320 }        // end of xsens namespace
Generated on Sun May 8 08:41:32 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3