// // abi-ipc.cpp // AmbientLight // // Created by Thorsten Kummermehr on 10/9/13. // // #include #include #include #include #include #include #include #include "abi-ipc.h" using namespace K2L::Automotive::ABI; using namespace K2L::Automotive::ABI_IPC; AbiUsbIpc::AbiUsbIpc() : _isConnected( false ), _receiveThreadIsRunning( false ), _receiveCB( NULL ), _receiveCBArgument( NULL ), _rxHandle( -1 ), _txHandle( -1 ) { } AbiUsbIpc::~AbiUsbIpc() { Disconnect(); } bool AbiUsbIpc::Connect( const char *cdevRx, const char *cdevTx ) { fprintf( stdout, "Connecting to RX:%s TX:%s\n", cdevRx, cdevTx ); bool success = -1 != ( _rxHandle = open( cdevRx, O_RDONLY ) ); if( success ) { _isConnected = -1 != ( _txHandle = open( cdevTx, O_WRONLY ) ); } if( !_isConnected ) { if( -1 != _rxHandle ) { close( _rxHandle ); _rxHandle = -1; } fprintf( stderr, "Failed to open cdev\n" ); return false; } if( pthread_create( &_receiveThread, NULL, ReceiveThread, this ) ) { fprintf( stderr, "Failed to create receive thread\n" ); Disconnect(); return false; } return true; } bool AbiUsbIpc::Connect( const char *cdevRxTx ) { fprintf( stdout, "Connecting to combined RX and TX:%s\n", cdevRxTx ); _isConnected = -1 != ( _rxHandle = _txHandle = open( cdevRxTx, O_RDWR ) ); if( !_isConnected ) { fprintf( stderr, "Failed to open cdev\n" ); return false; } if( pthread_create( &_receiveThread, NULL, ReceiveThread, this ) ) { fprintf( stderr, "Failed to create receive thread\n" ); Disconnect(); return false; } return true; } void AbiUsbIpc::Disconnect( void ) { if( !_isConnected ) return; _isConnected = false; //Give the receive thread one second to shutdown for( int i = 0; i < 100; i++ ) { if( _receiveThreadIsRunning ) usleep( 10000 ); else break; } if( 0 != _rxHandle ) { close( _rxHandle ); _rxHandle = -1; } if( 0 != _txHandle ) { close( _txHandle ); _txHandle = -1; } } bool AbiUsbIpc::IsConnected() { return _isConnected; } int AbiUsbIpc::Send( const BYTE *data, DWORD length ) { if( !_isConnected ) return 0; return ( int )write( _txHandle, data, length ); } void AbiUsbIpc::SetReceivePriority( int prio ) { } void AbiUsbIpc::SetReceiveCallback( AbiIpcDevice_RxCB_t receiveCB, void *cbArg ) { if( NULL != _receiveCB ) { fprintf( stderr, "The actual implementaion of SetReceiveCallback supports only one listener. To be improved.\n" ); return; } _receiveCB = receiveCB; _receiveCBArgument = cbArg; } void *AbiUsbIpc::ReceiveThread( void *param ) { if( NULL == param ) { fprintf( stderr, "Receive thread could not be started, because the this pointer was not passed as argument\n" ); pthread_exit( 0 ); } AbiUsbIpc *that = ( AbiUsbIpc * )param; that->_receiveThreadIsRunning = true; while( that->_isConnected ) { ssize_t rc = read( that->_rxHandle, that->receiveBuffer, sizeof( that->receiveBuffer ) ); if( rc <= 0 ) { //Receive error (<0) or other side closed connection (==0) //fprintf( stdout, "Closing connection because read returned value %d\n", ( uint32_t )rc ); //if( that->_isConnected ) //{ // that->Disconnect(); //} } else { // "rc"-bytes received if( NULL != that->_receiveCB ) { that->_receiveCB( ( uint8_t * )&that->receiveBuffer, ( uint32_t )rc, that->_receiveCBArgument ); } } } that->_receiveThreadIsRunning = false; pthread_exit( 0 ); }