/*
* Remote Laboratory FPGA Viewer Part
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* ( c ) 2012 Timothy Pearson
* Raptor Engineering
* http : //www.raptorengineeringinc.com
*/
# include "define.h"
# include "part.h"
# include <kaboutdata.h> //::createAboutData()
# include <kaction.h>
# include <klocale.h>
# include <kmessagebox.h> //::start()
# include <kparts/genericfactory.h>
# include <kstatusbar.h>
# include <kstdaction.h>
# include <tqfile.h> //encodeName()
# include <tqtimer.h> //postInit() hack
# include <tqvbox.h>
# include <tqsocket.h>
# include <tqmutex.h>
# include <tqeventloop.h>
# include <tqapplication.h>
# include <tqgroupbox.h>
# include <unistd.h> //access()
# include <stdint.h>
# include "tracewidget.h"
# include "floatspinbox.h"
# include "layout.h"
# define SERVER_TIMEOUT_MS 10000
FPGALed : : FPGALed ( TQWidget * parent , const char * name )
: KLed ( parent , name ) , m_clickable ( true )
{
connect ( this , SIGNAL ( clicked ( ) ) , this , SLOT ( toggle ( ) ) ) ;
setColor ( green ) ;
setOffColor ( TQApplication : : palette ( this ) . active ( ) . base ( ) . dark ( 200 ) ) ;
}
void FPGALed : : setClickable ( bool clickable ) {
if ( ( ! clickable ) & & ( m_clickable ) ) {
disconnect ( this , SIGNAL ( clicked ( ) ) , this , SLOT ( toggle ( ) ) ) ;
}
else if ( ( clickable ) & & ( ! m_clickable ) ) {
connect ( this , SIGNAL ( clicked ( ) ) , this , SLOT ( toggle ( ) ) ) ;
}
m_clickable = clickable ;
}
void FPGALed : : mouseReleaseEvent ( TQMouseEvent * e ) {
if ( e - > button ( ) = = TQMouseEvent : : LeftButton ) {
emit ( clicked ( ) ) ;
}
}
namespace RemoteLab {
typedef KParts : : GenericFactory < RemoteLab : : FPGAViewPart > Factory ;
# define CLIENT_LIBRARY "libremotelab_fpgaviewer"
K_EXPORT_COMPONENT_FACTORY ( libremotelab_fpgaviewer , RemoteLab : : Factory )
# define LED_SIZE 20,20
FPGAViewPart : : FPGAViewPart ( TQWidget * parentWidget , const char * widgetName , TQObject * parent , const char * name , const TQStringList & )
: RemoteInstrumentPart ( parent , name ) , m_socket ( 0 ) , m_base ( 0 ) , connToServerConnecting ( false ) , connToServerState ( - 1 ) , connToServerTimeoutTimer ( NULL ) , m_interfaceMode ( BasicInterfaceMode ) ,
remoteInputModeEnabled ( false ) , m_8bitInputValue ( 0 ) , m_8bitOutputValue ( 0 )
{
// Initialize mutex
m_connectionMutex = new TQMutex ( false ) ;
// Initialize kpart
setInstance ( Factory : : instance ( ) ) ;
setWidget ( new TQVBox ( parentWidget , widgetName ) ) ;
// Create timers
m_updateTimer = new TQTimer ( this ) ;
// Create widgets
m_base = new FPGAViewBase ( widget ( ) ) ;
// Create menu actions
// Submenus
KActionCollection * const ac = actionCollection ( ) ;
m_modeSubMenu = new KActionMenu ( i18n ( " Mode " ) , ac , " mode_submenu " ) ;
m_menuActionList . append ( m_modeSubMenu ) ;
// Menu items
m_modeBasicEnabled = new KToggleAction ( i18n ( " Basic " ) , KShortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( switchToBasicMode ( ) ) , ac , " mode_basic_enabled " ) ;
m_modeSubMenu - > insert ( m_modeBasicEnabled ) ;
m_modeIntermediateEnabled = new KToggleAction ( i18n ( " Intermediate " ) , KShortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( switchToIntermediateMode ( ) ) , ac , " mode_intermediate_enabled " ) ;
m_modeSubMenu - > insert ( m_modeIntermediateEnabled ) ;
m_modeAdvancedEnabled = new KToggleAction ( i18n ( " Advanced " ) , KShortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( switchToAdvancedMode ( ) ) , ac , " mode_advanced_enabled " ) ;
m_modeSubMenu - > insert ( m_modeAdvancedEnabled ) ;
// Initialize widgets
m_base - > group8BitInputLED7 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED6 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED5 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED4 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED3 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED2 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED1 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED0 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED7 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED6 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED5 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED4 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED3 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED2 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED1 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitOutputLED0 - > setFixedSize ( LED_SIZE ) ;
m_base - > group8BitInputLED7 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED6 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED5 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED4 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED3 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED2 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED1 - > setState ( KLed : : Off ) ;
m_base - > group8BitInputLED0 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED7 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED6 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED5 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED4 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED3 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED2 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED1 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED0 - > setState ( KLed : : Off ) ;
m_base - > group8BitOutputLED7 - > setClickable ( false ) ;
m_base - > group8BitOutputLED6 - > setClickable ( false ) ;
m_base - > group8BitOutputLED5 - > setClickable ( false ) ;
m_base - > group8BitOutputLED4 - > setClickable ( false ) ;
m_base - > group8BitOutputLED3 - > setClickable ( false ) ;
m_base - > group8BitOutputLED2 - > setClickable ( false ) ;
m_base - > group8BitOutputLED1 - > setClickable ( false ) ;
m_base - > group8BitOutputLED0 - > setClickable ( false ) ;
connect ( m_base - > group8BitInputLED7 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED6 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED5 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED4 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED3 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED2 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED1 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
connect ( m_base - > group8BitInputLED0 , SIGNAL ( clicked ( ) ) , this , SLOT ( process8BitInputChanges ( ) ) ) ;
processAllGraphicsUpdates ( ) ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( postInit ( ) ) ) ;
}
FPGAViewPart : : ~ FPGAViewPart ( ) {
if ( m_connectionMutex - > locked ( ) ) {
printf ( " [WARNING] Exiting when data transfer still in progress! \n \r " ) ; fflush ( stdout ) ;
}
disconnectFromServer ( ) ;
delete m_connectionMutex ;
}
void FPGAViewPart : : processAllGraphicsUpdates ( ) {
// This is an expensive operation
// Use it sparingly!
process8BitInputChanges ( ) ;
process8BitOutputChanges ( ) ;
processLockouts ( ) ;
}
void FPGAViewPart : : process8BitInputChanges ( ) {
// Read LED status into m_8bitInputValue
m_8bitInputValue = 0 ;
if ( m_base - > group8BitInputLED7 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x80 ;
if ( m_base - > group8BitInputLED6 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x40 ;
if ( m_base - > group8BitInputLED5 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x20 ;
if ( m_base - > group8BitInputLED4 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x10 ;
if ( m_base - > group8BitInputLED3 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x08 ;
if ( m_base - > group8BitInputLED2 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x04 ;
if ( m_base - > group8BitInputLED1 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x02 ;
if ( m_base - > group8BitInputLED0 - > state ( ) = = KLed : : On ) m_8bitInputValue | = 0x01 ;
m_base - > group8BitInputValueText - > setText ( TQString ( " 0x%1 " ) . arg ( m_8bitInputValue , 0 , 16 ) ) ;
if ( remoteInputModeEnabled ) {
m_base - > group8BitInput - > setTitle ( i18n ( " 8-Bit Input Values " ) + " [ " + i18n ( " Remote Input Mode " ) + " ] " ) ;
}
else {
m_base - > group8BitInput - > setTitle ( i18n ( " 8-Bit Input Values " ) + " [ " + i18n ( " Local Input Mode " ) + " ] " ) ;
}
}
void FPGAViewPart : : process8BitOutputChanges ( ) {
// Write m_8bitOutputValue to LEDs
m_base - > group8BitOutputLED7 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED6 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED5 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED4 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED3 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED2 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED1 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputLED0 - > setState ( ( m_8bitInputValue & 0x80 ) ? KLed : : On : KLed : : Off ) ;
m_base - > group8BitOutputValueText - > setText ( TQString ( " 0x%1 " ) . arg ( m_8bitOutputValue , 0 , 16 ) ) ;
}
void FPGAViewPart : : processLockouts ( ) {
TQWidget * mainWidget = widget ( ) ;
if ( mainWidget ) {
if ( ( m_socket ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) & & ( connToServerState > 0 ) & & ( connToServerConnecting = = false ) ) {
mainWidget - > setEnabled ( true ) ;
}
else {
mainWidget - > setEnabled ( false ) ;
}
}
if ( m_interfaceMode = = BasicInterfaceMode ) {
m_modeBasicEnabled - > setChecked ( true ) ;
m_modeIntermediateEnabled - > setChecked ( false ) ;
m_modeAdvancedEnabled - > setChecked ( false ) ;
}
if ( m_interfaceMode = = IntermediateInterfaceMode ) {
m_modeBasicEnabled - > setChecked ( false ) ;
m_modeIntermediateEnabled - > setChecked ( true ) ;
m_modeAdvancedEnabled - > setChecked ( false ) ;
}
if ( m_interfaceMode = = AdvancedInterfaceMode ) {
m_modeBasicEnabled - > setChecked ( false ) ;
m_modeIntermediateEnabled - > setChecked ( false ) ;
m_modeAdvancedEnabled - > setChecked ( true ) ;
}
}
void FPGAViewPart : : switchToBasicMode ( ) {
m_interfaceMode = BasicInterfaceMode ;
processLockouts ( ) ;
}
void FPGAViewPart : : switchToIntermediateMode ( ) {
m_interfaceMode = IntermediateInterfaceMode ;
processLockouts ( ) ;
}
void FPGAViewPart : : switchToAdvancedMode ( ) {
m_interfaceMode = AdvancedInterfaceMode ;
processLockouts ( ) ;
}
void FPGAViewPart : : connectionClosed ( ) {
closeURL ( ) ;
}
void FPGAViewPart : : postInit ( ) {
connect ( m_updateTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateDisplay ( ) ) ) ;
}
bool FPGAViewPart : : openURL ( const KURL & url ) {
int ret ;
ret = connectToServer ( url . url ( ) ) ;
processLockouts ( ) ;
return ( ret ! = 0 ) ;
}
bool FPGAViewPart : : closeURL ( ) {
disconnectFromServer ( ) ;
m_url = KURL ( ) ;
return true ;
}
void FPGAViewPart : : disconnectFromServer ( ) {
if ( m_socket ) {
m_socket - > clearPendingData ( ) ;
m_socket - > close ( ) ;
delete m_socket ;
m_socket = NULL ;
}
processLockouts ( ) ;
}
void FPGAViewPart : : finishConnectingToServer ( ) {
if ( ! m_socket ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
processLockouts ( ) ;
return ;
}
if ( connToServerConnecting ) {
switch ( connToServerState ) {
case 0 :
if ( ! connToServerTimeoutTimer ) {
connToServerTimeoutTimer = new TQTimer ;
connToServerTimeoutTimer - > start ( SERVER_TIMEOUT_MS , TRUE ) ;
}
if ( ( m_socket - > state ( ) = = TQSocket : : Connecting ) | | ( m_socket - > state ( ) = = TQSocket : : HostLookup ) ) {
if ( ! connToServerTimeoutTimer - > isActive ( ) ) {
connToServerState = - 3 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish connection to remote server</qt> " ) , i18n ( " Connection Failed " ) ) ;
}
}
else {
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
printf ( " [DEBUG] Initial connection established... \n \r " ) ; fflush ( stdout ) ;
m_socket - > setDataTimeout ( SERVER_TIMEOUT_MS ) ;
m_socket - > setUsingKerberos ( true ) ;
connToServerState = 1 ;
}
else {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish connection to remote server</qt> " ) , i18n ( " Connection Failed " ) ) ;
}
}
break ;
case 1 :
if ( m_socket - > kerberosStatus ( ) = = TDEKerberosClientSocket : : KerberosInitializing ) {
// Do nothing
}
else {
if ( m_socket - > kerberosStatus ( ) ! = TDEKerberosClientSocket : : KerberosInUse ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish Kerberos protocol with remote server<p>Please verify that you currently hold a valid Kerberos ticket</qt> " ) , i18n ( " Connection Failed " ) ) ;
}
else {
connToServerState = 2 ;
}
}
break ;
case 2 :
// Connection established!
// Read magic number and proto version from server
TQDataStream ds ( m_socket ) ;
TQ_UINT32 magicnum ;
TQ_UINT32 protover ;
ds > > magicnum ;
ds > > protover ;
printf ( " [DEBUG] Got magic number %d and protocol version %d \n \r " , magicnum , protover ) ; fflush ( stdout ) ;
// Request connection to backend server
TQString response ;
ds < < TQString ( " SERV " ) ;
ds < < TQString ( CLIENT_LIBRARY ) ;
ds > > response ;
printf ( " [RAJA DEBUG 400.0] Got '%s' from the server \n \r " , response . ascii ( ) ) ; fflush ( stdout ) ;
if ( response = = " OK " ) {
connToServerState = 3 ;
connToServerConnecting = false ;
processLockouts ( ) ;
return ;
}
else if ( response = = " ERRNOCONN " ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish connection with backend server<p>Please verify that you are currently connected to a workspace</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
else if ( response = = " ERRNOTAVL " ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>The backend server is not available at this time<p>Please try a different workspace, or try again later</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
else if ( response = = " ERRNOSERV " ) {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>The active laboratory workspace does not support the requested service</qt> " ) , i18n ( " Service Unavailable " ) ) ;
close ( ) ;
return ;
}
else {
connToServerState = - 1 ;
connToServerConnecting = false ;
disconnectFromServer ( ) ;
KMessageBox : : error ( 0 , i18n ( " <qt>Unable to establish connection with remote server</qt> " ) , i18n ( " Connection Failed " ) ) ;
close ( ) ;
return ;
}
break ;
}
TQTimer : : singleShot ( 0 , this , SLOT ( finishConnectingToServer ( ) ) ) ;
}
}
int FPGAViewPart : : connectToServer ( TQString server ) {
if ( m_socket ) {
return - 1 ;
}
if ( ! m_socket ) {
m_socket = new TDEKerberosClientSocket ( this ) ;
connect ( m_socket , TQT_SIGNAL ( statusMessageUpdated ( const TQString & ) ) , this , TQT_SLOT ( setStatusMessage ( const TQString & ) ) ) ;
}
m_socket - > setServiceName ( " remotefpga " ) ;
m_socket - > setServerFQDN ( server ) ;
m_socket - > connectToHost ( server , 4004 ) ;
// Finish connecting when appropriate
connToServerState = 0 ;
connToServerConnecting = true ;
TQTimer : : singleShot ( 0 , this , SLOT ( finishConnectingToServer ( ) ) ) ;
return 0 ;
}
TQPtrList < KAction > FPGAViewPart : : menuActionList ( ) {
return m_menuActionList ;
}
void FPGAViewPart : : updateDisplay ( ) {
// RAJA FIXME
}
KAboutData * FPGAViewPart : : createAboutData ( ) {
return new KAboutData ( APP_NAME , I18N_NOOP ( APP_PRETTYNAME ) , APP_VERSION ) ;
}
} //namespace RemoteLab
# include "part.moc"