86 # ifndef NTCAN_BAUD_1000 89 # define NTCAN_BAUD_1000 0 90 # define NTCAN_BAUD_800 14 91 # define NTCAN_BAUD_500 2 92 # define NTCAN_BAUD_250 4 93 # define NTCAN_BAUD_125 6 94 # define NTCAN_BAUD_100 7 95 # define NTCAN_BAUD_50 9 96 # define NTCAN_BAUD_20 11 97 # define NTCAN_BAUD_10 13 154 #define SDH_CANSERIAL_ESD_DEBUG 1 160 #if SDH_CANSERIAL_ESD_DEBUG 161 # define DBG( ... ) \ 187 if ( _timeout < 0.0 )
191 pimpl->ntcan_handle = NTCAN_HANDLE(NTCAN_INVALID_HANDLE);
193 baudrate = _baudrate;
194 SetTimeout( _timeout );
196 id_write = _id_write;
198 ungetch_valid =
false;
207 if ( _timeout < 0.0 )
210 if ( _ntcan_handle ==
tDeviceHandle(NTCAN_HANDLE(NTCAN_INVALID_HANDLE)) )
214 pimpl->ntcan_handle = *(NTCAN_HANDLE*)(_ntcan_handle);
217 SetTimeout( _timeout );
219 id_write = _id_write;
221 ungetch_valid =
false;
286 if ( pimpl->ntcan_handle == NTCAN_HANDLE(NTCAN_INVALID_HANDLE) )
291 DBG( dbg <<
"Opening ESD CAN net: " << net <<
", baudrate: " << baudrate <<
", id_read: 0x" << std::hex << id_read <<
", id_write: 0x" << id_write << std::dec <<
"\n" );
292 pimpl->rc = canOpen( net,
298 &(pimpl->ntcan_handle) );
300 if (pimpl->rc != NTCAN_SUCCESS)
303 pimpl->ntcan_handle = NTCAN_HANDLE(NTCAN_INVALID_HANDLE);
307 pimpl->rc = canSetBaudrate( pimpl->ntcan_handle, BaudrateToBaudrateCode( baudrate ) );
308 if (pimpl->rc != NTCAN_SUCCESS)
309 throw new cCANSerial_ESDException(
cMsg(
"Could not set baudrate to %lu on ESD CAN net %d: %s", baudrate, net, GetLastErrorMessage() ) );
312 pimpl->rc = canIdAdd( pimpl->ntcan_handle, id_read );
313 if (pimpl->rc != NTCAN_SUCCESS)
314 throw new cCANSerial_ESDException(
cMsg(
"Could not add CAN ID 0x%03x on ESD CAN net %d: %s", (
unsigned int) id_read, net, GetLastErrorMessage() ) );
317 pimpl->m_cmsg.len = 0;
318 pimpl->m_cmsg.msg_lost = 0;
319 pimpl->m_cmsg_next = 0;
327 return ( pimpl->ntcan_handle != NTCAN_HANDLE(NTCAN_INVALID_HANDLE) );
334 if ( pimpl->ntcan_handle == NTCAN_HANDLE(NTCAN_INVALID_HANDLE) )
337 canClose( pimpl->ntcan_handle );
338 pimpl->ntcan_handle = NTCAN_HANDLE(NTCAN_INVALID_HANDLE);
346 case 1000000:
return NTCAN_BAUD_1000;
347 case 800000:
return NTCAN_BAUD_800;
348 case 500000:
return NTCAN_BAUD_500;
349 case 250000:
return NTCAN_BAUD_250;
350 case 125000:
return NTCAN_BAUD_125;
351 case 100000:
return NTCAN_BAUD_100;
352 case 50000:
return NTCAN_BAUD_50;
353 case 20000:
return NTCAN_BAUD_20;
354 case 10000:
return NTCAN_BAUD_10;
363 assert( pimpl->ntcan_handle != NTCAN_HANDLE(NTCAN_INVALID_HANDLE) );
367 len = int( strlen( ptr ) );
372 int len_cmsgs = len/8 + (((len%8)!=0) ? 1 : 0);
381 CMSG* cmsg =
new CMSG[ len_cmsgs ];
383 CMSG cmsg[ len_cmsgs ];
385 for (
int i=0; i < len_cmsgs; i++)
387 cmsg[i].id = id_write;
388 cmsg[i].len = min( 8, len-i*8 );
389 for (
int j=0; j<cmsg[i].len; j++ )
390 cmsg[i].data[ j ] = *(ptr++);
392 DBG( dbg <<
"cCANSerial_ESD::write writing CAN frame id:0x" << std::hex << cmsg[i].
id <<
" len=" <<
int(cmsg[i].len) <<
" DATA (hex):" <<
cHexByteString( (
char const*) cmsg[i].data, cmsg[i].len ) <<
" bytes_written:" << (i*8+cmsg[i].len) <<
"/" << len <<
"\n" );
399 int len_cmsgs_save = len_cmsgs;
400 pimpl->rc = canWrite( pimpl->ntcan_handle, cmsg, (int32_t*) &len_cmsgs,
NULL );
405 if (pimpl->rc != NTCAN_SUCCESS)
406 throw new cCANSerial_ESDException(
cMsg(
"Could not write %d CMSGs on ESD CAN net %d: %s", (
int)len_cmsgs, net, GetLastErrorMessage() ) );
408 if ( len_cmsgs != len_cmsgs_save )
409 throw new cCANSerial_ESDException(
cMsg(
"Could only send %d/%d CMSGs on ESD CAN net %d", (
int)len_cmsgs, (
int)len_cmsgs_save, net ) );
418 assert( pimpl->ntcan_handle != NTCAN_HANDLE(NTCAN_INVALID_HANDLE) );
420 char* data = (
char*) _data;
429 if (
long(pimpl->timeout_ms) * 1000L != timeout_us )
431 SetTimeout(
double(timeout_us) / 1E6 );
442 for ( ; pimpl->m_cmsg_next < pimpl->m_cmsg.len && bytes_read <
size; pimpl->m_cmsg_next++, bytes_read++ )
443 *data++ = pimpl->m_cmsg.data[ pimpl->m_cmsg_next ];
445 if ( bytes_read < size )
449 pimpl->m_cmsg.len = 0;
450 pimpl->m_cmsg_next = 0;
451 if ( timeout_us == 0 )
452 pimpl->rc = canTake( pimpl->ntcan_handle, &(pimpl->m_cmsg), (int32_t*) &len_cmsgs );
454 pimpl->rc = canRead( pimpl->ntcan_handle, &(pimpl->m_cmsg), (int32_t*) &len_cmsgs,
NULL );
456 if (pimpl->rc != NTCAN_SUCCESS)
459 DBG( dbg <<
"cCANSerial_ESD::Read read CAN frame id:0x" << std::hex << pimpl->m_cmsg.id <<
" len=" <<
int(pimpl->m_cmsg.len) <<
" data (hex):" <<
cHexByteString( (
char const*) pimpl->m_cmsg.data, pimpl->m_cmsg.len ) <<
" bytes_read:" << bytes_read <<
"/" << size <<
"\n" );
462 if ( len_cmsgs != 1 && timeout_us != 0 )
464 if ( len_cmsgs > 0 && pimpl->m_cmsg.id != id_read )
465 throw new cCANSerial_ESDException(
cMsg(
"Invalid CAN ID 0x%03x received, expected 0x%03x", (
unsigned int) pimpl->m_cmsg.id, (
unsigned int) id_read ) );
467 for ( ; pimpl->m_cmsg_next < pimpl->m_cmsg.len && bytes_read <
size; pimpl->m_cmsg_next++, bytes_read++ )
468 *data++ = pimpl->m_cmsg.data[ pimpl->m_cmsg_next ];
471 while ( bytes_read < size && !return_on_less_data );
480 if ( _timeout < 0.0 )
484 pimpl->timeout_ms = int32_t(_timeout * 1000.0);
486 if ( pimpl->ntcan_handle != NTCAN_HANDLE(NTCAN_INVALID_HANDLE) )
491 pimpl->rc = canIoctl( pimpl->ntcan_handle, NTCAN_IOCTL_SET_RX_TIMEOUT, &(pimpl->timeout_ms) );
493 if ( pimpl->rc != NTCAN_SUCCESS )
501 static char return_msg[512];
503 snprintf( return_msg, 511,
"error 0x%x = %d = \"%s\"", dw, dw,
ESD_strerror( (NTCAN_RESULT) dw ) );
int write(char const *ptr, int len=0)
Write data to a previously opened port.
Derived exception class for low-level CAN ESD related exceptions.
Interface of auxilliary utility functions for SDHLibrary-CPP.
ssize_t Read(void *data, ssize_t size, long timeout_us, bool return_on_less_data)
int m_cmsg_next
index of next received data byte to return to user in m_cmsg
~cCANSerial_ESD()
destructor: clean up
void Close(void)
Close the previously opened CAN ESD interface port.
void SetTimeout(double _timeout)
set the timeout for next readline() calls (negative value means: no timeout, wait for ever) ...
virtual char const * GetErrorMessage(tErrorCode dw)
Interface of class #SDH::cCANSerial_ESD, class to access CAN bus via ESD card on cygwin/linux.
dummy class for (debug) stream output of bytes as list of hex values
char const * ESD_strerror(NTCAN_RESULT rc)
virtual void SetTimeout(double _timeout)
set the timeout for next readline() calls (negative value means: no timeout, wait for ever) ...
unsigned int BaudrateToBaudrateCode(unsigned long baudrate)
Translate a baudrate given as unsigned long into a baudrate code for struct termios.
internal hardware specific implementation details of the lowlevel ESD CAN interface ...
int tErrorCode
type of the error code, DWORD on windows and int on Linux/cygwin
#define NAMESPACE_SDH_START
tDeviceHandle GetHandle()
return the internally used NTCAN_HANDLE cast to a tDeviceHandle
Interface of auxilliary utility functions for SDHLibrary-CPP.
#define CAN_ESD_TXQUEUESIZE
transmit queue size for CAN frames
#define USING_NAMESPACE_SDH
#define CAN_ESD_RXQUEUESIZE
receive queue size for CAN frames
#define NAMESPACE_SDH_END
This file contains settings to make the SDHLibrary compile on differen systems:
NTCAN_HANDLE ntcan_handle
the internal handle to the driver
Class for short, fixed maximum length text messages.
#define DEFINE_TO_CASECOMMAND(_c)
bool IsOpen(void)
Return true if interface to CAN ESD is open.
virtual tErrorCode GetErrorNumber()
NAMESPACE_SDH_START typedef void * tDeviceHandle
generic device handle for CAN devices
cCANSerial_ESD(cCANSerial_ESD const &other)
private copy constructor without implementation, since copying of cCANSerial_ESD objects makes no sen...