|
|
/*------------------------------------------------------------------------------
|
|
|
███████╗ ██████╗ ██████╗ ███████╗██╗ ██╗██████╗ ██╗ ██████╗ ██████╗ ███████╗██████╗
|
|
|
██╔════╝██╔═══██╗██╔════╝ ██╔════╝╚██╗██╔╝██╔══██╗██║ ██╔═══██╗██╔══██╗██╔════╝██╔══██╗
|
|
|
███████╗██║ ██║██║ █████╗ ╚███╔╝ ██████╔╝██║ ██║ ██║██████╔╝█████╗ ██████╔╝
|
|
|
╚════██║██║ ██║██║ ██╔══╝ ██╔██╗ ██╔═══╝ ██║ ██║ ██║██╔══██╗██╔══╝ ██╔══██╗
|
|
|
███████║╚██████╔╝╚██████╗ ███████╗██╔╝ ██╗██║ ███████╗╚██████╔╝██║ ██║███████╗██║ ██║
|
|
|
╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
|
|
|
|
|
|
-- This file is a part of the SOC Explorer Software
|
|
|
-- Copyright (C) 2018, Plasma Physics Laboratory - CNRS
|
|
|
--
|
|
|
-- 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
-------------------------------------------------------------------------------*/
|
|
|
/*-- Author : Alexis Jeandet
|
|
|
-- Mail : alexis.jeandet@lpp.polytechnique.fr
|
|
|
----------------------------------------------------------------------------*/
|
|
|
#ifndef ISOCEXPLORERPLUGIN_H
|
|
|
#define ISOCEXPLORERPLUGIN_H
|
|
|
#include <QtPlugin>
|
|
|
#include <QWidget>
|
|
|
#include <QAction>
|
|
|
#include <QDockWidget>
|
|
|
#include <QMainWindow>
|
|
|
#include <QList>
|
|
|
#include <QMenu>
|
|
|
#include <socexplorer.h>
|
|
|
#include <QObject>
|
|
|
#include <QVariant>
|
|
|
#include <QVariantList>
|
|
|
#include <malloc.h>
|
|
|
#include <QFile>
|
|
|
#include <stdint.h>
|
|
|
#include <QTextStream>
|
|
|
#include <abstractbinfile.h>
|
|
|
#include <srec/srecfile.h>
|
|
|
#include <BinFile/binaryfile.h>
|
|
|
|
|
|
class ISocexplorerPlugin : public QDockWidget
|
|
|
{
|
|
|
Q_OBJECT
|
|
|
public:
|
|
|
//! Default plugin constructor, any plugin should call this constructor.
|
|
|
ISocexplorerPlugin(QWidget *parent = Q_NULLPTR,bool createPyObject=true):QDockWidget(parent)
|
|
|
{
|
|
|
Q_UNUSED(createPyObject)
|
|
|
closeAction=Q_NULLPTR;
|
|
|
menu=Q_NULLPTR;
|
|
|
ChildsMenu=Q_NULLPTR;
|
|
|
this->Connected = false;
|
|
|
this->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetVerticalTitleBar);
|
|
|
}
|
|
|
//! Tells if the plugin is connected, it is used to enable or disable all childrens interfaces.
|
|
|
virtual bool isConnected(){return this->Connected;}
|
|
|
//! Gives the associated Vendor IDentifier, usefull to automatically associate plugins with found
|
|
|
//! hardware while board enumeration.
|
|
|
virtual uint64_t baseAddress(){return this->BaseAddress;}
|
|
|
//! Sets the base address of the current instance, for example if your plugin is supposed to drive
|
|
|
//! an UART it will correspond to the address of it's first register. This address have at least to
|
|
|
//! be set by SocExplorer and it can be user accessible if you want.
|
|
|
virtual void setBaseAddress(uint64_t baseAddress){this->BaseAddress = baseAddress;}
|
|
|
|
|
|
QList<ISocexplorerPlugin*> childs;
|
|
|
ISocexplorerPlugin* parent;
|
|
|
QAction* closeAction;
|
|
|
QString instanceName(){return _instanceName;}
|
|
|
QString instance(){return instanceName();}
|
|
|
QMenu* menu;
|
|
|
QMenu* ChildsMenu;
|
|
|
|
|
|
signals:
|
|
|
//! Signal emited each time the plugin is about to be closed.
|
|
|
void closePlugin(ISocexplorerPlugin* driver);
|
|
|
void activateSig(bool flag);
|
|
|
void registerObject(QObject* object,const QString& instanceName);
|
|
|
|
|
|
public slots:
|
|
|
virtual int registermenu(QMenu* menu)
|
|
|
{
|
|
|
this->menu = menu->addMenu(this->_instanceName);
|
|
|
this->closeAction = this->menu->addAction(tr("Close plugin"));
|
|
|
QObject::connect(this->closeAction,SIGNAL(triggered()),this,SLOT(closeMe()));
|
|
|
this->ChildsMenu = this->menu->addMenu(QString("Childs"));
|
|
|
for(int i=0;i<this->childs.count();i++)
|
|
|
{
|
|
|
this->childs.at(i)->registermenu(this->ChildsMenu);
|
|
|
}
|
|
|
emit this->registerObject((QObject*)this,this->instanceName());
|
|
|
return 0;
|
|
|
}
|
|
|
virtual void postInstantiationTrigger(){}
|
|
|
//! Write slot this is the way your children plugins ask you for writing data.
|
|
|
//! If your plugin is supposed to have childern drivers you should implement this methode.
|
|
|
//! By default this methode forward the write request to the parent plugin.
|
|
|
//! \param Value Pointer the data buffer.
|
|
|
//! \param count Number of 32 bits words you should to write.
|
|
|
//! \param address Address from where you should to start to write.
|
|
|
//! \return Quantity of 32 bits words writtens.
|
|
|
virtual unsigned int Write(unsigned int* Value, int count, uint64_t address)
|
|
|
{
|
|
|
if(parent!=Q_NULLPTR)
|
|
|
{
|
|
|
return parent->Write(Value,count,address);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void Write(uint64_t address, QList<QVariant> dataList)
|
|
|
{
|
|
|
unsigned int data[dataList.count()];
|
|
|
for(int i = 0;i<dataList.count();i++)
|
|
|
{
|
|
|
data[i] = (unsigned int)dataList.at(i).toUInt();
|
|
|
}
|
|
|
Write(data,dataList.count(),address);
|
|
|
}
|
|
|
//! Read slot this is the way your children plugins ask you for reading data.
|
|
|
//! If your plugin is supposed to have childern drivers you should implement this methode.
|
|
|
//! By default this methode forward the write request to the parent plugin.
|
|
|
//! \param Value Pointer the data buffer.
|
|
|
//! \param count Number of 32 bits words you should to read.
|
|
|
//! \param address Address from where you should to start to read.
|
|
|
//! \return Quantity of 32 bits words read.
|
|
|
virtual unsigned int Read(unsigned int* Value, int count, uint64_t address)
|
|
|
{
|
|
|
if(parent!=Q_NULLPTR)
|
|
|
{
|
|
|
return parent->Read(Value,count,address);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
QVariantList Read(uint64_t address, int count)
|
|
|
{
|
|
|
unsigned int data[count];
|
|
|
QVariantList result;
|
|
|
Read(data,count,address);
|
|
|
for(int i = 0;i<count;i++)
|
|
|
{
|
|
|
result.append(QVariant(static_cast<int>(data[i])));
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
virtual void closeMe(){emit this->closePlugin(this);}
|
|
|
|
|
|
virtual void activate(bool flag)
|
|
|
{
|
|
|
this->setEnabled(flag);
|
|
|
emit this->activateSig(flag);
|
|
|
}
|
|
|
|
|
|
virtual void setInstanceName(const QString& newName)
|
|
|
{
|
|
|
this->_instanceName = newName;
|
|
|
if(this->menu)
|
|
|
this->menu->setTitle(this->_instanceName);
|
|
|
this->setWindowTitle(newName);
|
|
|
this->setObjectName(newName);
|
|
|
}
|
|
|
|
|
|
virtual bool dumpMemory(uint64_t address, unsigned int count, QString file)
|
|
|
{
|
|
|
unsigned int* buffer = (unsigned int*)malloc(count*sizeof(unsigned int));
|
|
|
if(buffer!=NULL)
|
|
|
{
|
|
|
this->Read(buffer,count,address);
|
|
|
QFile outfile(file);
|
|
|
if (!outfile.open(QIODevice::ReadWrite | QIODevice::Text))
|
|
|
return false;
|
|
|
QTextStream out(&outfile);
|
|
|
for(int i=0;(unsigned int)i<count;i++)
|
|
|
out << "0x"+QString::number(address+(i*4),16) + ": 0x" + QString::number(buffer[i],16) + "\n";
|
|
|
free(buffer);
|
|
|
out.flush();
|
|
|
outfile.close();
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
virtual bool dumpMemory(uint64_t address,unsigned int count,QString file,const QString& format)
|
|
|
{
|
|
|
unsigned int* buffer = (unsigned int*)malloc(count*sizeof(unsigned int));
|
|
|
if(buffer!=NULL)
|
|
|
{
|
|
|
this->Read(buffer,count,address);
|
|
|
if(!format.compare("srec",Qt::CaseInsensitive))
|
|
|
{
|
|
|
//need to convert from in memory endianness to file endianness
|
|
|
//SREC is always big endian
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
for(int l=0;l<(count);l++)
|
|
|
{
|
|
|
buffer[l] = socexplorerBswap32(buffer[l]);
|
|
|
}
|
|
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
|
|
|
|
#endif
|
|
|
codeFragment fragment((char*)buffer,count*4,address);
|
|
|
srecFile::toSrec(QList<codeFragment*>()<<&fragment,file);
|
|
|
}
|
|
|
if(!format.compare("bin",Qt::CaseInsensitive))
|
|
|
{
|
|
|
//beware this format is not portable from a big endian host to a litle endian one
|
|
|
codeFragment fragment((char*)buffer,count*4,address);
|
|
|
binaryFile::toBinary(QList<codeFragment*>()<<&fragment,file);
|
|
|
}
|
|
|
if(!format.compare("hexa",Qt::CaseInsensitive))
|
|
|
{
|
|
|
QFile outfile(file);
|
|
|
if (!outfile.open(QIODevice::ReadWrite | QIODevice::Text))
|
|
|
return false;
|
|
|
QTextStream out(&outfile);
|
|
|
for(int i=0;(unsigned int)i<count;i++)
|
|
|
out << "0x"+QString::number(address+(i*4),16) + ": 0x" + QString::number(buffer[i],16) + "\n";
|
|
|
free(buffer);
|
|
|
out.flush();
|
|
|
outfile.close();
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
virtual bool memSet(uint64_t address, int value, unsigned int count)
|
|
|
{
|
|
|
unsigned int* buffer = static_cast<unsigned int*>(malloc(count*sizeof(unsigned int)));
|
|
|
if(buffer!=Q_NULLPTR)
|
|
|
{
|
|
|
memset(static_cast<void*>(buffer),value,count*sizeof(unsigned int));
|
|
|
this->Write(buffer,count,address);
|
|
|
free(buffer );
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
virtual bool loadbin(uint64_t address,QString file)
|
|
|
{
|
|
|
QFile infile(file);
|
|
|
if (!infile.open(QIODevice::ReadOnly))
|
|
|
return false;
|
|
|
uint32_t* buffer = (uint32_t*)malloc(infile.size());
|
|
|
if(buffer!=NULL)
|
|
|
{
|
|
|
infile.read((char*)buffer,infile.size());
|
|
|
for(int i=0;i<(infile.size()/4);i++)
|
|
|
{
|
|
|
buffer[i] = socexplorerBswap32(buffer[i]);
|
|
|
}
|
|
|
this->Write(buffer,infile.size()/4,address);
|
|
|
free(buffer);
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
virtual bool loadfile(abstractBinFile* file)
|
|
|
{
|
|
|
{
|
|
|
if(file->isopened())
|
|
|
{
|
|
|
QList<codeFragment*> fragments= file->getFragments();
|
|
|
for(int i=0;i<fragments.count();i++)
|
|
|
{
|
|
|
int size = fragments.at(i)->size/4;
|
|
|
// TODO fixme, should be the oposite
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
if(!file->litleendian)
|
|
|
{
|
|
|
uint32_t* buffer = (uint32_t*)malloc(fragments.at(i)->size);
|
|
|
memcpy(buffer,fragments.at(i)->data,fragments.at(i)->size);
|
|
|
if(buffer!=NULL)
|
|
|
{
|
|
|
for(int l=0;l<(size);l++)
|
|
|
{
|
|
|
buffer[l] = socexplorerBswap32(buffer[l]);
|
|
|
}
|
|
|
this->Write(buffer,size,fragments.at(i)->address);
|
|
|
free(buffer);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
this->Write((uint32_t*) fragments.at(i)->data,size,fragments.at(i)->address);
|
|
|
}
|
|
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
|
if(file->litleendian)
|
|
|
{
|
|
|
uint32_t* buffer = (uint32_t*)malloc(fragments.at(i)->size);
|
|
|
memcpy(buffer,fragments.at(i)->data,fragments.at(i)->size);
|
|
|
if(buffer!=NULL)
|
|
|
{
|
|
|
for(int l=0;l<(size);l++)
|
|
|
{
|
|
|
buffer[l] = socexplorerBswap32(buffer[l]);
|
|
|
}
|
|
|
this->Write(buffer,size,fragments.at(i)->address);
|
|
|
free(buffer);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
this->Write((uint32_t*) fragments.at(i)->data,size,fragments.at(i)->address);
|
|
|
}
|
|
|
#endif
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
ISocexplorerPlugin* parentPlugin(){return this->parent;}
|
|
|
ISocexplorerPlugin* toPlugin(){return static_cast<ISocexplorerPlugin*>(this);}
|
|
|
protected:
|
|
|
QString _instanceName;
|
|
|
uint64_t BaseAddress;
|
|
|
bool Connected;
|
|
|
};
|
|
|
|
|
|
Q_DECLARE_INTERFACE(ISocexplorerPlugin, "socexplorer.plugins.ISocexplorerPlugin")
|
|
|
|
|
|
#endif // ISOCEXPLORERPLUGIN_H
|
|
|
|