SXXXXXXX_PyDownloadFwViaSRIO/_OLD/Vecchia_app/FpgaBeamMeUp/qgtftptargetsim.cpp
2026-01-22 17:10:05 +01:00

409 lines
13 KiB
C++

#include "qgftfptargetsim.h"
#include <QUdpSocket>
#include <QNetworkDatagram>
#include <QTimerEvent>
#include <QTimer>
#include <QFile>
#include <QDebug>
#include "bsk_tftpd.h"
#include "bsk_tftp_pfs.h"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static bsk_download_site_t sites[]=
{
{"ZynQ", "0x94", 0, 0, 6,
{
{"BL", bsk_download_partition_t::part_null, 64*1024},
{"MM", bsk_download_partition_t::part_null, 128*1024},
{"APP0", bsk_download_partition_t::part_null, 1*1024*1024},
{"APP1", bsk_download_partition_t::part_null, 1*1024*1024},
{"PL0", bsk_download_partition_t::part_null, 1*1024*1024},
{"PL1", bsk_download_partition_t::part_null, 1*1024*1024}
}
},
{"ZynQ", "0x95", 0, 0, 7,
{
{"BL", bsk_download_partition_t::part_null, 64*1024},
{"MM", bsk_download_partition_t::part_null, 128*1024},
{"OPER", bsk_download_partition_t::part_null, 1*1024*1024},
{"PL0", bsk_download_partition_t::part_null, 1*1024*1024},
{"PL1", bsk_download_partition_t::part_null, 1*1024*1024},
{"FPGA0", bsk_download_partition_t::part_null, 0},
{"FPGA1", bsk_download_partition_t::part_null, 0}
}
},
{"DSP", "0x54", 0, 0, 4,
{
{"BL", bsk_download_partition_t::part_fsbl|bsk_download_partition_t::part_hidden, 64*1024},
{"MM", bsk_download_partition_t::part_recovery|bsk_download_partition_t::part_hidden, 128*1024},
{"OPER", bsk_download_partition_t::part_operative|bsk_download_partition_t::part_default, 1*1024*1024},
{"APP2", 0, 1*1024*1024}
}
},
{"DSP", "0x54", 0, 0, 4,
{
{"BL", bsk_download_partition_t::part_fsbl|bsk_download_partition_t::part_hidden, 64*1024},
{"MM", bsk_download_partition_t::part_recovery|bsk_download_partition_t::part_hidden, 128*1024},
{"OPER", bsk_download_partition_t::part_operative|bsk_download_partition_t::part_default, 1*1024*1024},
{"APP2", 0, 1*1024*1024}
}
},
{"DSP", "0x54", 0, 0, 4,
{
{"BL", bsk_download_partition_t::part_fsbl|bsk_download_partition_t::part_hidden, 64*1024},
{"MM", bsk_download_partition_t::part_recovery|bsk_download_partition_t::part_hidden, 128*1024},
{"OPER", bsk_download_partition_t::part_operative|bsk_download_partition_t::part_default, 1*1024*1024},
{"APP2", 0, 1*1024*1024}
}
},
{"DSP", "0x54", 0, 0, 4,
{
{"BL", bsk_download_partition_t::part_fsbl|bsk_download_partition_t::part_hidden, 64*1024},
{"MM", bsk_download_partition_t::part_recovery|bsk_download_partition_t::part_hidden, 128*1024},
{"OPER", bsk_download_partition_t::part_operative|bsk_download_partition_t::part_default, 1*1024*1024},
{"APP2", 0, 1*1024*1024}
}
}
};
class QgTftpTargetSim::Implementation
{
public:
QString name;
int site_id;
QObject* parent;
QUdpSocket tftpServer;
//static Implementation* gInstance;
QHostAddress clientAddress;
int clientPort;
//int timerId;
QTimer storeTimer;
QFile storeFile;
QByteArray storeBuffer;
bsk_download_partition_t* currentParitition;
int store_time;
int progr_time;
bsk_tftpd_context_id_t id;
const bsk_tftpd_context_info_t* tftpd_cx;
int state;
Implementation(const QString& n, int sid, QObject* p):
name(n),
site_id(sid),
parent(p),
tftpServer(p)
{
//gInstance=this;
store_time=2*1000;
progr_time=2*1000;
storeTimer.setSingleShot(true);
storeBuffer.reserve(1024*1024);
currentParitition=0;
state=0;
}
void processPendingDatagram()
{
while(tftpServer.hasPendingDatagrams())
{
QNetworkDatagram d=tftpServer.receiveDatagram();
//qDebug()<<"RCV:"<<d.data().size();
auto cAddress=d.senderAddress();
auto cPort=d.senderPort();
#if 0
if (!tftpServer.isOpen())
{
tftpServer.connectToHost(d.senderAddress(), d.senderPort());
qDebug()<<"Connect to"<<d.senderAddress()<<d.senderPort();
}
else if ((tftpServer.peerPort()!=d.senderPort()) || (tftpServer.peerAddress()!=d.senderAddress()))
{
tftpServer.connectToHost(d.senderAddress(), d.senderPort());
qDebug()<<"Connect to"<<d.senderAddress()<<d.senderPort();
}
#endif
int r=bsk_tftpd_process_packet(id, cAddress.toIPv4Address(), cPort,
d.data().constData(), d.data().size());
if (r==0)
{
clientAddress=cAddress;
clientPort=cPort;
}
else if (r!=-100)
{
qDebug()<<"Disconnect";
//tftpServer.disconnectFromHost();
}
}
}
static int bsk_tftpd_log_delegate(bsk_tftpd_context_id_t id, const char* const msg, ...)
{
const bsk_tftpd_context_info_t* cx=bsk_tftpd_context_info(id);
va_list args;
va_start(args, msg);
qDebug()<<id<<cx->name<<cx->port<<QString::vasprintf(msg, args);
va_end(args);
return 0;
}
char* progr_msg(const char* msg, int n=0)
{
static char buffer[512];
if (n==0)
{
int i=storeTimer.interval();
int r=storeTimer.remainingTime();
n=(float(i-r)/float(i))*100;
if (n>100)
n=100;
if (n<0)
n=-1;
}
sprintf(buffer, "%d %s", n, msg);
return buffer;
}
static bsk_tftpd_receive_status_t bsk_tftpd_receive_delegate(bsk_tftpd_context_id_t id, bsk_tftpd_receive_delegate_operation_t op, const void* const data, unsigned int block, unsigned int offset, unsigned int size_bytes)
{
const bsk_tftpd_context_info_t* cx=bsk_tftpd_context_info(id);
Implementation* gInstance=reinterpret_cast<Implementation*>(cx->cookie);
bsk_tftpd_receive_status_t sts={bsk_tftpd_ok, 0};
if (op==bsk_tftpd_open_read_not_supported)
{
if (strcmp(bsk_tftpd_mfs_status_query, (char*)data)==0)
{
if (gInstance->state==0)
{
sts.sts=bsk_tftpd_err_not_found;
sts.ack_msg="ready";
}
else if (gInstance->state==2)
{
sts.sts=bsk_tftpd_err_bad_id;
sts.ack_msg=gInstance->progr_msg("Erasing");
}
else if (gInstance->state==3)
{
sts.sts=bsk_tftpd_err_bad_id;
sts.ack_msg=gInstance->progr_msg("Storing");
}
else
{
sts.sts=bsk_tftpd_err_bad_id;
sts.ack_msg="busy";
}
}
else if (strcmp(bsk_tftpd_mfs_list_query, (char*)data)==0)
{
sts.sts=bsk_tftpd_err_file_exists;
sts.ack_msg=bsk_tftpd_mfs_get_list(id);
}
else
sts.sts=bsk_tftpd_err_not_found;
return sts;
}
if ((op==bsk_tftpd_open_file) && (gInstance->state>0))
{
static QString reply_msg;
static char cmsg[512];
sts.sts=bsk_tftpd_err_not_found;
int remain=gInstance->storeTimer.remainingTime();
float store_completition=100*(5000.0f/(5000.0f-float(remain)));
reply_msg=QString::asprintf("%u%% storing", int(store_completition));
strncpy(cmsg, reply_msg.toLatin1().constData(), sizeof cmsg);
sts.ack_msg=0; //cmsg;
qDebug()<<sts.sts<<sts.ack_msg;
}
else if (op==bsk_tftpd_open_file)
{
const char* fname;
gInstance->currentParitition=0;
bsk_download_partition_t* p=bsk_tftp_mfs_decode_filename(gInstance->site_id, (char*)data, &fname);
if (p==bsk_tftp_mfs_invalid_partition)
{
sts.sts=bsk_tftpd_err_not_found;
sts.ack_msg=0;
return sts;
}
gInstance->state=1;
if (p)
{
if (gInstance->storeFile.isOpen())
{
qDebug()<<"WARNING:store file is open!!!";
gInstance->storeFile.close();
}
//gInstance->storeFile.setFileName(QString("_%1_%2.dat").arg(gInstance->site_id).arg(p->name));
//gInstance->storeFile.open(QIODevice::WriteOnly);
gInstance->storeBuffer.clear();
gInstance->storeBuffer.reserve(1024*1024);
gInstance->currentParitition=p;
}
}
else if (op==bsk_tftpd_data)
{
//if (gInstance->storeFile.isOpen())
//{
// gInstance->storeFile.write((char*)data, size_bytes);
//}
gInstance->storeBuffer.append((char*)data, size_bytes);
}
else if (op==bsk_tftpd_end)
{
//if (gInstance->storeFile.isOpen())
//{
// gInstance->storeFile.write((char*)data, size_bytes);
// gInstance->storeFile.flush(); //close();
//}
if (gInstance->currentParitition)
{
if (gInstance->storeBuffer.size()>gInstance->currentParitition->max_size)
{
sts.sts=bsk_tftpd_err_no_space;
sts.ack_msg="file too big";
}
else
{
if (size_bytes)
gInstance->storeBuffer.append((char*)data, size_bytes);
sts.sts=bsk_tftpd_dont_ack;
gInstance->storeTimer.start(gInstance->store_time);
gInstance->storeFile.setFileName(QString("_%1_%2.dat").arg(gInstance->site_id).arg(gInstance->currentParitition->name));
bool ok=gInstance->storeFile.open(QIODevice::WriteOnly);
if (ok)
{
gInstance->storeFile.write(gInstance->storeBuffer);
gInstance->storeFile.close();
gInstance->state=2;
}
else
{
sts.sts=bsk_tftpd_err_access;
sts.ack_msg="error storing";
}
}
}
else
{
gInstance->state=0;
}
}
return sts;
}
static int bsk_tftpd_send_delegate(bsk_tftpd_context_id_t id, unsigned int adr, unsigned int port, const void* const data, unsigned int size)
{
const bsk_tftpd_context_info_t* cx=bsk_tftpd_context_info(id);
Implementation* gInstance=reinterpret_cast<Implementation*>(cx->cookie);
QHostAddress ha(gInstance->clientAddress);
int hp=gInstance->clientPort;
if (adr)
ha=QHostAddress(adr);
if (port)
hp=port;
qDebug()<<"TFTP: send"<<QString("%1").arg(ha.toIPv4Address(), 0, 16)<<hp<<size;
gInstance->tftpServer.writeDatagram((char*)data, size, ha, hp); //gInstance->clientAddress, gInstance->clientPort);
return 0;
}
};
//QgFtfpTargetSim::Implementation* QgFtfpTargetSim::Implementation::gInstance;
QgTftpTargetSim::QgTftpTargetSim(const QString &name, int sid, int port):
p_(*new Implementation(name, sid, this))
{
bsk_tftpd_mfs_set_site(&sites[0], 3);
p_.tftpServer.bind(QHostAddress::LocalHost, port);
connect(&p_.tftpServer, &QUdpSocket::readyRead, this, pendingDatagram);
char* kn=strdup(name.toLatin1().constData());
p_.id=bsk_tftpd_context_initialize(-1, kn, port, &p_);
p_.tftpd_cx=bsk_tftpd_context_info(p_.id);
bsk_tftpd_set_log_delegate(p_.id, Implementation::bsk_tftpd_log_delegate);
bsk_tftpd_set_receive_delegate(p_.id, Implementation::bsk_tftpd_receive_delegate);
bsk_tftpd_set_send_delegate(p_.id, Implementation::bsk_tftpd_send_delegate);
connect(&p_.storeTimer, &QTimer::timeout, this, &timerExpired);
}
QgTftpTargetSim::~QgTftpTargetSim()
{
delete &p_;
}
void QgTftpTargetSim::pendingDatagram()
{
p_.processPendingDatagram();
}
void QgTftpTargetSim::setEraseTime(int t)
{
p_.store_time=t*1000;
}
void QgTftpTargetSim::setProgTime(int t)
{
p_.progr_time=t*1000;
}
void QgTftpTargetSim::timerExpired()
{
if (p_.state==2)
{
p_.state=3;
p_.storeTimer.start(p_.progr_time);
}
else if (p_.state==3)
{
p_.storeTimer.stop();
bsk_tftpd_send_ack(p_.id, bsk_tftpd_ok, 0);
if (p_.storeFile.isOpen())
{
qDebug()<<"File stored:"<<p_.storeFile.fileName();
p_.storeFile.close();
}
else
{
qDebug()<<"File not stored:"<<p_.storeFile.fileName();
}
p_.state=0;
}
}
#if 0
void QgFtfpTargetSim::timerEvent(QTimerEvent *event)
{
if (event->timerId()==p_.timerId)
{
if (state==2)
p_.timerId=0;
bsk_tftpd_send_ack(p_.id, bsk_tftpd_ok, 0);
}
}
#endif