diff --git a/SocExplorer_Plugins.pro b/SocExplorer_Plugins.pro --- a/SocExplorer_Plugins.pro +++ b/SocExplorer_Plugins.pro @@ -10,6 +10,7 @@ SUBDIRS = \ genericrwplugin \ memctrlrplugin \ memcheckplugin + unix:SUBDIRS += spwplugin OTHER_FILES += SocExplorer-plugins.spec diff --git a/spwplugin/GR-ESB/gr_esb_bridge.cpp b/spwplugin/GR-ESB/gr_esb_bridge.cpp --- a/spwplugin/GR-ESB/gr_esb_bridge.cpp +++ b/spwplugin/GR-ESB/gr_esb_bridge.cpp @@ -85,7 +85,8 @@ void GR_ESB_bridge::setIP(QString ip) void GR_ESB_bridge::setVirtualLink(QString vlink) { - vlink = vlink.section("Virtual link",0,0); + //vlink = vlink.section(,0,0); + vlink.remove("Virtual link"); bool success; int vlinkTmp = vlink.toInt(&success); if(success) @@ -105,20 +106,169 @@ void GR_ESB_bridge::setVirtualLink(qint3 unsigned int GR_ESB_bridge::Write(unsigned int *Value, unsigned int count, unsigned int address) { - // TODO write ME! - Q_UNUSED(count) - Q_UNUSED(Value) - Q_UNUSED(address) - return 0; + char writeBuffer[RMAP_WRITE_PACKET_MIN_SZ((RMAP_MAX_XFER_SIZE*4))]; + char *RMAPAckBuff; + int transactionID = 0; + int written=0; + SocExplorerEngine::message(this->plugin,"Enter Write function",2); + QProgressBar* progress=NULL; + SocExplorerAutoProgressBar autopb; + if(count>RMAP_MAX_XFER_SIZE) + { + progress= SocExplorerEngine::getProgressBar("Writing on SPW @0x"+QString::number(address,16)+" %v of "+QString::number(count)+" words ",count); + autopb.setProgressBar(progress); + } + //Quite stupide loop, I guess that I always get the number of byte I asked for! + while(count>=RMAP_MAX_XFER_SIZE) + { + for(int i=0;i<(RMAP_MAX_XFER_SIZE);i++) + { + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+0] = (char)(((unsigned int)Value[i+written]>>24)&0xFF); + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+1] = (char)(((unsigned int)Value[i+written]>>16)&0xFF); + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+2] = (char)(((unsigned int)Value[i+written]>>8)&0xFF); + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+3] = (char)(((unsigned int)Value[i+written])&0xFF); + } + transactionID=manager->getRMAPtransactionID(); + SocExplorerEngine::message(this->plugin,QString("Sending Write request with ID=%1").arg(transactionID),2); + RMAP_build_tx_request_header( + this->manager->destinationLogicalAddress, + this->manager->destinationKey, + this->manager->sourceLogicalAddress, + transactionID, + address+(written*4), + RMAP_MAX_XFER_SIZE*4, + writeBuffer); + manager->sendPacket(writeBuffer,RMAP_WRITE_PACKET_MIN_SZ(RMAP_MAX_XFER_SIZE*4)); + manager->getRMAPanswer(transactionID,&RMAPAckBuff); + free(RMAPAckBuff); + written+=RMAP_MAX_XFER_SIZE; + count-=RMAP_MAX_XFER_SIZE; + progress->setValue(written); + qApp->processEvents(); + } + if(count>0) + { + for(int i=0;i<((int)count);i++) + { + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+0] = (char)(((unsigned int)Value[i+written]>>24)&0xFF); + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+1] = (char)(((unsigned int)Value[i+written]>>16)&0xFF); + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+2] = (char)(((unsigned int)Value[i+written]>>8)&0xFF); + writeBuffer[RMAP_WRITE_HEADER_MIN_SZ+(i*4)+3] = (char)(((unsigned int)Value[i+written])&0xFF); + } + transactionID=manager->getRMAPtransactionID(); + SocExplorerEngine::message(this->plugin,QString("Sending Write request with ID=%1").arg(transactionID),2); + RMAP_build_tx_request_header( + this->manager->destinationLogicalAddress, + this->manager->destinationKey, + this->manager->sourceLogicalAddress, + transactionID, + address+(written*4), + count*4, + writeBuffer); + manager->sendPacket(writeBuffer,RMAP_WRITE_PACKET_MIN_SZ(count*4)); + manager->getRMAPanswer(transactionID,&RMAPAckBuff); + free(RMAPAckBuff); + written+=count; + if(progress!=NULL) + { + progress->setValue(written); + qApp->processEvents(); + } + } + return written; } unsigned int GR_ESB_bridge::Read(unsigned int *Value, unsigned int count, unsigned int address) { - // TODO write ME! - Q_UNUSED(Value) - Q_UNUSED(count) - Q_UNUSED(address) - return 0; + char requestBuffer[RMAP_READ_HEADER_MIN_SZ]; + char* RMAP_AnswerBuffer; + requestBuffer[0]=this->manager->linkNumber;//Link number + int transactionID = 0; + int read=0; + QProgressBar* progress=NULL; + SocExplorerAutoProgressBar autopb; + if(count>RMAP_MAX_XFER_SIZE) + { + progress= SocExplorerEngine::getProgressBar("Reading on SPW @0x"+QString::number(address,16)+" %v of "+QString::number(count)+" words ",count); + autopb.setProgressBar(progress); + } + SocExplorerEngine::message(this->plugin,QString("Enter read function, count=%1, RMAP_MAX_XFER_SIZE=%2").arg(count).arg(RMAP_MAX_XFER_SIZE),2); + + //Quite stupide loop, I guess that I always get the number of byte I asked for! + while((int)count>=(int)RMAP_MAX_XFER_SIZE) + { + transactionID = manager->getRMAPtransactionID(); + SocExplorerEngine::message(this->plugin,QString("New transactionID:%1").arg(transactionID),2); + RMAP_build_rx_request_header( + this->manager->destinationLogicalAddress, + this->manager->destinationKey, + this->manager->sourceLogicalAddress, + transactionID, + address+(read*4), + RMAP_MAX_XFER_SIZE*4, + requestBuffer); + manager->sendPacket(requestBuffer,RMAP_READ_HEADER_MIN_SZ); + int len=manager->getRMAPanswer(transactionID,&RMAP_AnswerBuffer); + if(len==-1) + { + this->toggleBridgeConnection(); + return 0; + } + for(int i=0;i<((len-13)/4);i++) + { + Value[read+i] = 0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+12]); + Value[read+i] = (Value[read+i]<<8) + (0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+13])); + Value[read+i] = (Value[read+i]<<8) + (0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+14])); + Value[read+i] = (Value[read+i]<<8) + (0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+15])); + } + free(RMAP_AnswerBuffer); + read+=RMAP_MAX_XFER_SIZE; + count-=RMAP_MAX_XFER_SIZE; + if(progress!=NULL) + { + progress->setValue(read); + qApp->processEvents(); + } + } + if((int)count>0) + { + transactionID = manager->getRMAPtransactionID(); + SocExplorerEngine::message(this->plugin,QString("New transactionID: %1").arg(transactionID),2); + SocExplorerEngine::message(this->plugin,QString("Building request with:"),2); + SocExplorerEngine::message(this->plugin,QString("Address = %1").arg(address+(read*4),8,16),2); + SocExplorerEngine::message(this->plugin,QString("Size = %1").arg(count*4),2); + SocExplorerEngine::message(this->plugin,QString("Size + 13 = %1").arg((count*4)+13),2); + RMAP_build_rx_request_header( + this->manager->destinationLogicalAddress, + this->manager->destinationKey, + this->manager->sourceLogicalAddress, + transactionID, + address+(read*4), + count*4, + requestBuffer); + manager->sendPacket(requestBuffer,RMAP_READ_HEADER_MIN_SZ); + int len=manager->getRMAPanswer(transactionID,&RMAP_AnswerBuffer); + if(len==-1) + { + this->toggleBridgeConnection(); + return 0; + } + for(int i=0;i<((len-13)/4);i++) + { + Value[read+i] = 0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+12]); + Value[read+i] = (Value[read+i]<<8) + (0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+13])); + Value[read+i] = (Value[read+i]<<8) + (0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+14])); + Value[read+i] = (Value[read+i]<<8) + (0x0FF & ((unsigned int)RMAP_AnswerBuffer[(4*i)+15])); + } + free(RMAP_AnswerBuffer); + read+=count; + if(progress!=NULL) + { + progress->setValue(read); + qApp->processEvents(); + } + } + return read; } int GR_ESB_bridge::pushRMAPPacket(char *packet, int size) @@ -128,40 +278,139 @@ int GR_ESB_bridge::pushRMAPPacket(char * GR_ESB_Manager::GR_ESB_Manager(socexplorerplugin *plugin, QObject *parent) - :QThread((QObject*)parent) + :abstractSpwManager(plugin, parent) { - this->Read_soc = new QTcpSocket(this); - this->Write_soc = new QTcpSocket(this); - this->RMAPtimeout = 2000; - this->handleMutex = new QMutex(QMutex::NonRecursive); - this->RMAP_AnswersSem = new QSemaphore(0); - this->RMAP_AnswersMtx=new QMutex(QMutex::Recursive); - this->RMAP_pending_transaction_IDsMtx=new QMutex(QMutex::Recursive); - this->plugin = plugin; - connected = false; - this->moveToThread(this); + this->sourceLogicalAddress=32; + this->destinationLogicalAddress=254; + this->destinationKey=2; + connect(&(this->Read_soc),SIGNAL(readyRead()),this,SLOT(readyRead())); } GR_ESB_Manager::~GR_ESB_Manager() { +} +void GR_ESB_Manager::__processPacket(packetBuffer_t *packet) +{ + if(packet->complete) + { + if(packet->buffer[1]==(char)SPW_PROTO_ID_RMAP) //RMAP packet + { + RMAP_Answer* RMapPacket; + SocExplorerEngine::message(this->plugin,"Got RMAP packet",2); + SocExplorerEngine::message(this->plugin,QString("Rmap packet size %1").arg(packet->PacketLen),2); + char* packetbuffer = (char*)malloc(packet->PacketLen); + if(packetbuffer) + { + memcpy(packetbuffer,packet->buffer,packet->PacketLen); + this->handleMutex->unlock(); + if(packet->PacketLen==8) + { + RMapPacket=new RMAP_Answer(RMAP_get_transactionID(packetbuffer),packetbuffer,packet->PacketLen); + } + else + { + RMapPacket=new RMAP_Answer(RMAP_get_transactionID(packetbuffer),packetbuffer,packet->PacketLen); + } + RMAP_AnswersMtx->lock(); + RMAP_Answers.append(RMapPacket); + RMAP_AnswersMtx->unlock(); + RMAP_AnswersSem->release(); + } + } + else //any non-rmap packet will be pushed to the network + { + char* packetbuffer = (char*)malloc(packet->PacketLen); + if(packetbuffer) + { + memcpy(packetbuffer,packet->buffer,packet->PacketLen); + emit emitPacket(packetbuffer,packet->PacketLen); + SocExplorerEngine::message(this->plugin,"Got SPW packet",2); + } + } + } + +} + +QByteArray GR_ESB_Manager::__processData(const QByteArray &data, packetBuffer_t *buffer) +{ + if(buffer->complete) + { + if(Q_UNLIKELY(data.size()<=4)) + return data; + buffer->PacketLen= ((int)data.at(3)& 0x0FF) + (((int)data.at(2)& 0x0FF)<<8) + (((int)data.at(1)& 0x0FF)<<16); + if(buffer->PacketLen>(data.size()-4)) + { + memcpy(buffer->buffer,data.data()+4,data.size()-4); + buffer->complete=false; + buffer->index=data.size()-4; + } + else + { + memcpy(buffer->buffer,data.data()+4,data.size()-4); + buffer->PacketLen = data.size()-4; + buffer->index=data.size()-4; + buffer->complete=true; + __processPacket(buffer); + int len = buffer->PacketLen; + buffer->PacketLen = 0; + buffer->index=0; + if((data.size()-4-len)) + { + return __processData(data.right((data.size()-4-len)),buffer); + } + } + + } + else + { + if(buffer->PacketLen>(data.size()+buffer->index)) + { + memcpy(buffer->buffer+buffer->index,data.data(),data.size()); + buffer->complete=false; + buffer->index+=data.size(); + } + else + { + memcpy(buffer->buffer+buffer->index,data.data(),buffer->PacketLen-buffer->index); + buffer->complete=true; + buffer->index+=data.size(); + __processPacket(buffer); + int len = buffer->PacketLen; + buffer->PacketLen = 0; + buffer->index=0; + if((data.size()-len)) + { + return __processData(data.right((data.size()-len)),buffer); + } + } + } + return QByteArray(); } void GR_ESB_Manager::run() { + char bufferData[(RMAP_MAX_XFER_SIZE*4)+50]; + packetBuffer_t buffer={bufferData,0,0,true}; SocExplorerEngine::message(this->plugin,"Starting GRESB pooling thread",1); + QByteArray data; while (!this->isInterruptionRequested()) { if(this->connected) { - handleMutex->lock(); - SocExplorerEngine::message(this->plugin,"Looking for new RMAP packets",4); + SocExplorerEngine::message(this->plugin,"Looking for new RMAP packets",8); + if(!incomingPackets.isEmpty()) + { + incomingPacketsMutex.lock(); + data.append(incomingPackets.dequeue()); + this->incomingPacketsMutex.unlock(); + data = __processData(data,&buffer); + } } else { //do some sanity checks! - usleep(RMAPtimeout/2); } usleep(1000); @@ -172,21 +421,23 @@ void GR_ESB_Manager::run() bool GR_ESB_Manager::connectBridge() { int timeout=60; - if(this->Read_soc->state()==QTcpSocket::UnconnectedState) + this->connected = false; + if(this->Read_soc.state()==QTcpSocket::UnconnectedState) { - this->Read_soc->connectToHost(IP,gresb_Conf[virtualLinkIndex].Read_port); - this->Read_soc->waitForConnected(30000); + this->Read_soc.connectToHost(IP,gresb_Conf[virtualLinkIndex].Receive_port); + this->Read_soc.waitForConnected(30000); } - if(this->Write_soc->state()==QTcpSocket::UnconnectedState) + if(this->Write_soc.state()==QTcpSocket::UnconnectedState) { - this->Write_soc->connectToHost(IP,gresb_Conf[virtualLinkIndex].Write_port); - this->Write_soc->waitForConnected(30000); + this->Write_soc.connectToHost(IP,gresb_Conf[virtualLinkIndex].Transmit_port); + this->Write_soc.waitForConnected(30000); } - while((this->Read_soc->state()!=QTcpSocket::ConnectedState) && (this->Write_soc->state()!=QTcpSocket::ConnectedState)) + while((this->Read_soc.state()!=QTcpSocket::ConnectedState) && (this->Write_soc.state()!=QTcpSocket::ConnectedState)) { usleep(100000); if(timeout--==0)return false; } + this->connected = true; return true; } @@ -194,17 +445,17 @@ bool GR_ESB_Manager::connectBridge() bool GR_ESB_Manager::disconnectBridge() { int timeout=60; - if(this->Read_soc->state()!=QTcpSocket::UnconnectedState) + if(this->Read_soc.state()!=QTcpSocket::UnconnectedState) { - this->Read_soc->disconnectFromHost(); - this->Read_soc->waitForDisconnected(30000); + this->Read_soc.disconnectFromHost(); + this->Read_soc.waitForDisconnected(30000); } - if(this->Write_soc->state()!=QTcpSocket::UnconnectedState) + if(this->Write_soc.state()!=QTcpSocket::UnconnectedState) { - this->Write_soc->disconnectFromHost(); - this->Write_soc->waitForDisconnected(30000); + this->Write_soc.disconnectFromHost(); + this->Write_soc.waitForDisconnected(30000); } - while((this->Read_soc->state()!=QTcpSocket::UnconnectedState) && (this->Write_soc->state()!=QTcpSocket::UnconnectedState)) + while((this->Read_soc.state()!=QTcpSocket::UnconnectedState) && (this->Write_soc.state()!=QTcpSocket::UnconnectedState)) { usleep(100000); if(timeout--==0)return false; @@ -212,31 +463,52 @@ bool GR_ESB_Manager::disconnectBridge() return true; } -int GR_ESB_Manager::getRMAPtransactionID() -{ - // TODO write ME! - return -1; -} - -int GR_ESB_Manager::getRMAPanswer(int transactionID, char **buffer) -{ - // TODO write ME! - Q_UNUSED(transactionID) - Q_UNUSED(buffer) - return -1; -} bool GR_ESB_Manager::sendPacket(char *packet, int size) { - // TODO write ME! - Q_UNUSED(packet) - Q_UNUSED(size) - return false; + bool result = false; + char protocoleIdentifier; + SocExplorerEngine::message(this->plugin,"Sending SPW packet",2); + if(Q_UNLIKELY(this->Write_soc.state()!=QAbstractSocket::ConnectedState)) + { + SocExplorerEngine::message(this->plugin,"Socket closed",2); + //TODO handle disconnection + } + char* SPWpacket = (char*)malloc(size+4); + if(SPWpacket!=NULL) + { + SPWpacket[0]=0; //Protocol = spw + memcpy(SPWpacket+4,packet,size); + SPWpacket[1]=(size>>16) & 0x0FF; + SPWpacket[2]=(size>>8) & 0x0FF; + SPWpacket[3]=size & 0x0FF; + this->handleMutex->lock(); + result = ((size+4) == this->Write_soc.write(SPWpacket,size+4)); + this->Write_soc.flush(); + this->handleMutex->unlock(); + free(SPWpacket); + } + if (Q_UNLIKELY(!result)) + { + SocExplorerEngine::message(this->plugin,"ERR sending the READ command ",2); + return false; + } + else + { + emit bytesTransmittedToSpw( size-1 ); // -1 is for removing the first bytes added to the packet to route to the right link + // read the protocole identifier + protocoleIdentifier = packet[2]; + if (protocoleIdentifier == SPW_PROTO_ID_CCSDS) + emit ccsdsPacketTransmittedToSpw(); + SocExplorerEngine::message(this->plugin,"Packet sent",2); + } + return true; } -void GR_ESB_Manager::pushRmapPacket(char *packet, int len) +void GR_ESB_Manager::readyRead() { - // TODO write ME! - Q_UNUSED(packet) - Q_UNUSED(len) + incomingPacketsMutex.lock(); + incomingPackets.append(Read_soc.readAll()); + incomingPacketsMutex.unlock(); } + diff --git a/spwplugin/GR-ESB/gr_esb_bridge.h b/spwplugin/GR-ESB/gr_esb_bridge.h --- a/spwplugin/GR-ESB/gr_esb_bridge.h +++ b/spwplugin/GR-ESB/gr_esb_bridge.h @@ -5,56 +5,64 @@ #include #include #include +#include struct gresb_Conf_str { - qint32 Read_port; - qint32 Write_port; + qint32 Transmit_port; + qint32 Receive_port; }; const struct gresb_Conf_str gresb_Conf[]= { - {3000,3001}, //Virtual link 0 - {3002,3003}, //Virtual link 1 - {3004,3005}, //Virtual link 2 - {3006,3007}, //Virtual link 3 - {3008,3009}, //Virtual link 4 - {3010,3011} //Virtual link 5 +{3000,3001}, //Virtual link 0 +{3002,3003}, //Virtual link 1 +{3004,3005}, //Virtual link 2 +{3006,3007}, //Virtual link 3 +{3008,3009}, //Virtual link 4 +{3010,3011} //Virtual link 5 }; -class GR_ESB_Manager: public QThread +class GR_ESB_Manager: public abstractSpwManager { Q_OBJECT + + typedef struct packetBuffer_t + { + char* buffer; + int PacketLen; + int index; + bool complete; + }packetBuffer_t; + public: explicit GR_ESB_Manager(socexplorerplugin *plugin = 0,QObject* parent=0); ~GR_ESB_Manager(); void run(); bool connectBridge(); bool disconnectBridge(); - int getRMAPtransactionID(); - int getRMAPanswer(int transactionID,char** buffer); bool sendPacket(char* packet,int size); signals: void emitPacket(char* packet,int size); private: - QMutex* handleMutex,*RMAP_AnswersMtx,*RMAP_pending_transaction_IDsMtx; - QSemaphore* RMAP_AnswersSem; void pushRmapPacket(char* packet,int len); - socexplorerplugin* plugin; - bool connected; char* SPWPacketBuff; - QList RMAP_Answers; - QList RMAP_pending_transaction_IDs; + + void __processPacket(packetBuffer_t *packet); + QByteArray __processData(const QByteArray &data, packetBuffer_t* buffer); +private slots: + void readyRead(); public: - QTcpSocket* Read_soc; - QTcpSocket* Write_soc; + QTcpSocket Read_soc; + QTcpSocket Write_soc; + QMutex incomingPacketsMutex; + QQueue incomingPackets; QString IP; int virtualLinkIndex; - int RMAPtimeout; }; diff --git a/spwplugin/GR-ESB/gr_esb_ui.ui b/spwplugin/GR-ESB/gr_esb_ui.ui --- a/spwplugin/GR-ESB/gr_esb_ui.ui +++ b/spwplugin/GR-ESB/gr_esb_ui.ui @@ -6,8 +6,8 @@ 0 0 - 968 - 392 + 978 + 518 @@ -30,7 +30,188 @@ Config - + + + + <html><head/><body><p>Set the RMAP target address, this address will be used as destination address for all the RMAP transfers.</p><p>This is you SOC spw address.</p></body></html> + + + + + + 254 + + + 3 + + + + + + + + + + + 75 + true + + + + Transmitted + + + + + + + - + + + + + + + - + + + + + + + Bytes + + + + + + + - + + + + + + + - + + + + + + + + 75 + true + + + + Received + + + + + + + Packets + + + + + + + Reset stats + + + + + + + + + + <html><head/><body><p>Set the Space Wire Brick destination Key, the default value is 32 (0x20).</p></body></html> + + + + + + 32 + + + 3 + + + + + + + <html><head/><body><p>Set the RMAP timeout, when waiting for a RMAP answer the driver will give up after this time if it doesn't get any answer.</p></body></html> + + + Qt::ImhDigitsOnly + + + + + + 500 + + + 5 + + + + + + + + SPW0 + + + + + SPW1 + + + + + SPW2 + + + + + + + + Destination address + + + + + + + <html><head/><body><p>Set the RMAP target key, this key will be used for all the RMAP transfers.</p><p>This is you SOC spw key.</p></body></html> + + + + + + 2 + + + 3 + + + + + + + GR-ESB Virtual link + + + + @@ -64,33 +245,21 @@ - - + + - GR-ESB Virtual link + Source address - - - - - SPW0 - - - - - SPW1 - - - - - SPW2 - - + + + + RMAP timeout(ms) + - + @@ -100,6 +269,13 @@ + + + + Destination key + + + @@ -107,7 +283,7 @@ - + Connect @@ -125,7 +301,7 @@ - + @@ -137,7 +313,7 @@ QWebView QWidget -
QWebView
+
QtWebKitWidgets/QWebView
1
diff --git a/spwplugin/StarDundee/stardundeespw_usb.cpp b/spwplugin/StarDundee/stardundeespw_usb.cpp --- a/spwplugin/StarDundee/stardundeespw_usb.cpp +++ b/spwplugin/StarDundee/stardundeespw_usb.cpp @@ -40,11 +40,11 @@ stardundeeSPW_USB::stardundeeSPW_USB(soc Q_UNUSED(parent) this->manager = new stardundeeSPW_USB_Manager(parent,this); makeGUI(parent); - this->manager->start(); connect(this->manager,SIGNAL(emitPacket(char*,int)),this,SIGNAL(pushPacketOverTCP(char*,int))); connect(this->manager, SIGNAL(bytesReceivedFromSpw(uint)), this, SIGNAL(BytesReceivedFromSpw(uint))); connect(this->manager, SIGNAL(bytesTransmittedToSpw(uint)), this, SIGNAL(BytesTransmittedToSpw(uint))); connect(this->manager, SIGNAL(ccsdsPacketTransmittedToSpw()), this, SIGNAL(CCSDSPacketTransmittedToSpw())); + this->manager->start(); } stardundeeSPW_USB::~stardundeeSPW_USB() @@ -215,8 +215,11 @@ unsigned int stardundeeSPW_USB::Read(uns free(RMAP_AnswerBuffer); read+=RMAP_MAX_XFER_SIZE; count-=RMAP_MAX_XFER_SIZE; - progress->setValue(read); - qApp->processEvents(); + if(progress!=NULL) + { + progress->setValue(read); + qApp->processEvents(); + } } if((int)count>0) { @@ -329,7 +332,6 @@ void stardundeeSPW_USB::makeGUI(socexplo { Q_UNUSED(parent) this->p_GUI = new StarDundeeGUI(); - // this->mainLayout = new QGridLayout(this->p_GUI); connect(((StarDundeeGUI*)this->p_GUI),SIGNAL(connectClicked()),this,SLOT(toggleBridgeConnection())); connect(this->manager,SIGNAL(updateAvailableBrickCount(int)),((StarDundeeGUI*)this->p_GUI),SLOT(updateAvailableBrickCount(int))); connect(((StarDundeeGUI*)this->p_GUI),SIGNAL(brickSelectionChanged(int)),this,SLOT(brickSelectionChanged(int))); @@ -400,16 +402,8 @@ void stardundeeSPW_USB::sendPacketComing } stardundeeSPW_USB_Manager::stardundeeSPW_USB_Manager(socexplorerplugin *plugin, QObject *parent) - :QThread((QObject*)parent) + :abstractSpwManager(plugin, parent) { - this->RMAPtimeout = 2000; - this->handleMutex = new QMutex(QMutex::NonRecursive); -// this->handleMutex = new QMutex(QMutex::Recursive); - this->RMAP_AnswersSem = new QSemaphore(0); - this->RMAP_AnswersMtx=new QMutex(QMutex::Recursive); - this->RMAP_pending_transaction_IDsMtx=new QMutex(QMutex::Recursive); - this->plugin = plugin; - connected = false; // TODO remove this crap! this->initDialog(); // this->moveToThread(this); @@ -417,10 +411,6 @@ stardundeeSPW_USB_Manager::stardundeeSPW stardundeeSPW_USB_Manager::~stardundeeSPW_USB_Manager() { - this->terminate(); - while (!this->isFinished()) { - this->usleep(1000); - } } void stardundeeSPW_USB_Manager::run() @@ -867,7 +857,7 @@ void stardundeeSPW_USB_Manager::initiali unsigned int stardundeeSPW_USB_Manager::getLinkStatus(unsigned char link) { U32 statusControl, errorStatus, portType; - U32 linkStatus, operatingSpeed, outputPortConnection; + U32 linkStatus=0, operatingSpeed, outputPortConnection; char isLinkRunning, isAutoStart, isStart, isDisabled, isTristate; // Read the link status control register @@ -912,9 +902,9 @@ unsigned int stardundeeSPW_USB_Manager:: bool stardundeeSPW_USB_Manager::disconnectBridge() { this->handleMutex->lock(); + USBSpaceWire_UnregisterReceiveOnAllPorts(hDevice); // Stop receiving on all ports USBSpaceWire_Close(hDevice); // Close the device SocExplorerEngine::message(this->plugin,"stardundee *** Close *** USBSpaceWire_Close, device: " + QString::number(0),0); - USBSpaceWire_UnregisterReceiveOnAllPorts(hDevice); // Stop receiving on all ports this->handleMutex->unlock(); this->RMAP_pending_transaction_IDsMtx->lock(); this->RMAP_pending_transaction_IDs.clear(); @@ -926,84 +916,6 @@ bool stardundeeSPW_USB_Manager::disconne return true; } -int stardundeeSPW_USB_Manager::getRMAPtransactionID() -{ - this->RMAP_pending_transaction_IDsMtx->lock(); - int ID=0; - bool found=true; - while(ID<511) - { - for(int i=0;iRMAP_pending_transaction_IDsMtx->unlock(); - return ID; -} - -int stardundeeSPW_USB_Manager::getRMAPanswer(int transactionID, char **buffer) -{ - QTime timeout; - *buffer=NULL; - int count=0; - SocExplorerEngine::message(this->plugin,"Looking for RMAP answer",2); - timeout.start(); - while (*buffer==NULL) - { - this->RMAP_AnswersMtx->lock(); - SocExplorerEngine::message(this->plugin,"Got exclusive access on RMAP_Answers stack",2); - SocExplorerEngine::message(this->plugin,QString("%1 packet(s) available in RMAP_Answers stack").arg(RMAP_Answers.count()),2); - for(int i=0;iplugin,QString("Packet %1 ID=%2").arg(i).arg(RMAP_Answers[i]->transactionID),2); - if(RMAP_Answers[i]->transactionID==transactionID) - { - this->RMAP_pending_transaction_IDsMtx->lock(); - SocExplorerEngine::message(this->plugin,"Got exclusive access on RMAP_pending_transaction_ID stack",2); - for(int j=0;jRMAP_pending_transaction_IDsMtx->unlock(); - *buffer = RMAP_Answers[i]->data; - count = RMAP_Answers[i]->len; - RMAP_Answer* tmp=RMAP_Answers[i]; - RMAP_Answers.removeAt(i); - delete tmp; - } - } - this->RMAP_AnswersMtx->unlock(); - //if no answer found in the stack wait until a new packet is pushed - SocExplorerEngine::message(this->plugin,"waiting until a new packet is pushed",2); - if(*buffer==NULL) - { - while (0==this->RMAP_AnswersSem->available()) - { - SocExplorerEngine::message(this->plugin,QString("this->RMAP_AnswersSem->available() = %1").arg(this->RMAP_AnswersSem->available()),2); - if(timeout.elapsed()>=RMAPtimeout) - { - SocExplorerEngine::message(this->plugin,"Timeout reached giving up!",2); - return -1; - } - usleep(1000); - } - this->RMAP_AnswersSem->acquire(); - } - } - return count; -} - bool stardundeeSPW_USB_Manager::sendPacket(char *packet, int size) { char protocoleIdentifier; @@ -1032,15 +944,6 @@ bool stardundeeSPW_USB_Manager::sendPack return true; } -void stardundeeSPW_USB_Manager::pushRmapPacket(char *packet, int len) -{ - char* packetbuffer = (char*)malloc(len); - memcpy(packetbuffer,packet,len); - RMAP_Answer* RMPAPpacket=new RMAP_Answer(RMAP_get_transactionID(packetbuffer+1),packetbuffer,len); - RMAP_AnswersMtx->lock(); - RMAP_Answers.append(RMPAPpacket); - RMAP_AnswersMtx->unlock(); -} void stardundeeSPW_USB_Manager::sendTimecodePeriodically( bool onOff ) { diff --git a/spwplugin/StarDundee/stardundeespw_usb.h b/spwplugin/StarDundee/stardundeespw_usb.h --- a/spwplugin/StarDundee/stardundeespw_usb.h +++ b/spwplugin/StarDundee/stardundeespw_usb.h @@ -41,7 +41,7 @@ #define BRICK_IS_SET_AS_AN_INTERFACE true #define BRICK_IS_SET_AS_A_ROUTER false -class stardundeeSPW_USB_Manager: public QThread +class stardundeeSPW_USB_Manager: public abstractSpwManager { Q_OBJECT public: @@ -58,8 +58,6 @@ public: void setTimecodeFrequency(double requestedFrequency); unsigned int getLinkStatus(unsigned char link); bool disconnectBridge(); - int getRMAPtransactionID(); - int getRMAPanswer(int transactionID,char** buffer); bool sendPacket(char* packet,int size); signals: @@ -75,15 +73,8 @@ public slots: int getLinkNumber( void ); private: - QMutex *handleMutex,*RMAP_AnswersMtx,*RMAP_pending_transaction_IDsMtx; - QSemaphore* RMAP_AnswersSem; - void pushRmapPacket(char* packet,int len); + //QSemaphore* RMAP_AnswersSem; star_device_handle hDevice; - socexplorerplugin* plugin; - bool connected; - char* SPWPacketBuff; - QList RMAP_Answers; - QList RMAP_pending_transaction_IDs; QLabel *starDundeeStatusQueryDialogLabel; QPushButton *starDundeeStatusQueryRetryButton; @@ -96,13 +87,8 @@ private: public: int selectedBrick; - int linkNumber; int brickList; int linkSpeed; - int sourceLogicalAddress; - int destinationLogicalAddress; - int destinationKey; - int RMAPtimeout; double timecodeFrequency; bool interfaceMode; // 1 => interface mode, 0 => router mode }; diff --git a/spwplugin/abstractspwbridge.cpp b/spwplugin/abstractspwbridge.cpp --- a/spwplugin/abstractspwbridge.cpp +++ b/spwplugin/abstractspwbridge.cpp @@ -20,6 +20,8 @@ -- Mail : alexis.jeandet@member.fsf.org ----------------------------------------------------------------------------*/ #include "abstractspwbridge.h" +#include +#include abstractSpwBridge::abstractSpwBridge(socexplorerplugin *parent) :QObject((QObject*)parent) @@ -54,3 +56,124 @@ bool abstractSpwBridge::disconnectBridge + + + +abstractSpwManager::abstractSpwManager(socexplorerplugin *plugin, QObject *parent) + :QThread((QObject*)parent) +{ + this->RMAPtimeout = 2000; + this->handleMutex = new QMutex(QMutex::NonRecursive); + this->RMAP_AnswersSem = new QSemaphore(0); + this->RMAP_AnswersMtx=new QMutex(QMutex::Recursive); + this->RMAP_pending_transaction_IDsMtx=new QMutex(QMutex::Recursive); + this->plugin = plugin; + connected = false; +} + +abstractSpwManager::~abstractSpwManager() +{ + this->terminate(); + while (!this->isFinished()) + { + this->usleep(1000); + } +} + +int abstractSpwManager::getRMAPtransactionID() +{ + this->RMAP_pending_transaction_IDsMtx->lock(); + int ID=0; + bool found=true; + while(ID<511) + { + for(int i=0;iRMAP_pending_transaction_IDsMtx->unlock(); + return ID; +} + +int abstractSpwManager::getRMAPanswer(int transactionID, char **buffer) +{ + + QTime timeout; + *buffer=NULL; + int count=0; + SocExplorerEngine::message(this->plugin,"Looking for RMAP answer",2); + qApp->processEvents(); + timeout.start(); + while (*buffer==NULL) + { + this->RMAP_AnswersMtx->lock(); + SocExplorerEngine::message(this->plugin,"Got exclusive access on RMAP_Answers stack",2); + SocExplorerEngine::message(this->plugin,QString("%1 packet(s) available in RMAP_Answers stack").arg(RMAP_Answers.count()),2); + for(int i=0;iplugin,QString("Packet %1 ID=%2").arg(i).arg(RMAP_Answers[i]->transactionID),2); + if(RMAP_Answers[i]->transactionID==transactionID) + { + this->RMAP_pending_transaction_IDsMtx->lock(); + SocExplorerEngine::message(this->plugin,"Got exclusive access on RMAP_pending_transaction_ID stack",2); + for(int j=0;jRMAP_pending_transaction_IDsMtx->unlock(); + *buffer = RMAP_Answers[i]->data; + count = RMAP_Answers[i]->len; + RMAP_Answer* tmp=RMAP_Answers[i]; + RMAP_Answers.removeAt(i); + delete tmp; + } + } + this->RMAP_AnswersMtx->unlock(); + //if no answer found in the stack wait until a new packet is pushed + SocExplorerEngine::message(this->plugin,"waiting until a new packet is pushed",2); + if(*buffer==NULL) + { + while (0==this->RMAP_AnswersSem->available()) + { + SocExplorerEngine::message(this->plugin,QString("this->RMAP_AnswersSem->available() = %1").arg(this->RMAP_AnswersSem->available()),2); + if(timeout.elapsed()>=RMAPtimeout) + { + SocExplorerEngine::message(this->plugin,"Timeout reached giving up!",2); + return -1; + } + usleep(1000); + qApp->processEvents(); + } + this->RMAP_AnswersSem->acquire(); + } + } + return count; +} + +int abstractSpwManager::getLinkNumber() +{ + return this->linkNumber; +} + +void abstractSpwManager::pushRmapPacket(char *packet, int len) +{ + char* packetbuffer = (char*)malloc(len); + memcpy(packetbuffer,packet,len); + RMAP_Answer* RMPAPpacket=new RMAP_Answer(RMAP_get_transactionID(packetbuffer+1),packetbuffer,len); + RMAP_AnswersMtx->lock(); + RMAP_Answers.append(RMPAPpacket); + RMAP_AnswersMtx->unlock(); +} + + diff --git a/spwplugin/abstractspwbridge.h b/spwplugin/abstractspwbridge.h --- a/spwplugin/abstractspwbridge.h +++ b/spwplugin/abstractspwbridge.h @@ -23,6 +23,9 @@ #define ABSTRACTSPWBRIDGE_H #include +#include +#include +#include #include #define RMAP_MAX_XFER_SIZE 4000 //slightly less than 16kBytes #include @@ -65,4 +68,43 @@ private: }; +class abstractSpwManager: public QThread +{ + Q_OBJECT +public: + explicit abstractSpwManager(socexplorerplugin *plugin = 0,QObject* parent=0); + ~abstractSpwManager(); + virtual void run(){} + virtual bool connectBridge()=0; + virtual bool disconnectBridge()=0; + int getRMAPtransactionID(); + int getRMAPanswer(int transactionID,char** buffer); + virtual bool sendPacket(char* packet,int size)=0; + int RMAPtimeout; + int linkNumber; + int sourceLogicalAddress; + int destinationLogicalAddress; + int destinationKey; +signals: + void emitPacket(char* packet,int size); + void bytesReceivedFromSpw( unsigned int ); + void bytesTransmittedToSpw( unsigned int); + void ccsdsPacketTransmittedToSpw( void ); + +public slots: + int getLinkNumber(); + +protected: + QList RMAP_Answers; + QList RMAP_pending_transaction_IDs; + QMutex *handleMutex,*RMAP_AnswersMtx,*RMAP_pending_transaction_IDsMtx; + QSemaphore* RMAP_AnswersSem; + socexplorerplugin* plugin; + bool connected; + void pushRmapPacket(char* packet,int len); + +}; + + + #endif // ABSTRACTSPWBRIDGE_H diff --git a/spwplugin/spwplugin.pro b/spwplugin/spwplugin.pro --- a/spwplugin/spwplugin.pro +++ b/spwplugin/spwplugin.pro @@ -12,7 +12,7 @@ QMAKE_CFLAGS += -std=c++11 win32:CONFIG += dll win32:CONFIG -= static -VERSION=0.6.1 +VERSION=0.6.2 TARGET = spwplugin DEFINES += PLUGIN=spwplugin DEFINES += PLUGINHEADER="\"\\\"spwplugin.h"\\\"\" @@ -24,10 +24,6 @@ DEFINES += driver_can_be_child=0 DEFINES += driver_VID=0 DEFINES += driver_PID=0 -#STARTDUNDEEPATH=/home/spacewire/usb/spw_usb_driver_v2.68/ - -#LIBS += $$STARTDUNDEEPATH/lib/x86_64/libSpaceWireUSBAPI.so \ -# $$STARTDUNDEEPATH/lib/x86_64/libConfigLibraryUSB.so INCLUDEPATH += \ $${PWD} \