Compare commits
89 Commits
0fef710b8f
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
b4623992ef
|
|||
|
b8553067d1
|
|||
|
c0b4a014f5
|
|||
|
fffbf6e8db
|
|||
|
d627da2999
|
|||
|
1ec27e9ee3
|
|||
|
6bc074a033
|
|||
|
87b6fecfd0
|
|||
|
3a745af9bf
|
|||
|
2a4de4fe34
|
|||
|
86f0a3bedc
|
|||
|
a37213b128
|
|||
|
992b9f3063
|
|||
|
589f56ecbd
|
|||
|
bd89deceb6
|
|||
|
5c5fda62e6
|
|||
|
76f3044d21
|
|||
|
f3818e805a
|
|||
|
6ee9e305cc
|
|||
|
f7dc10c7bb
|
|||
|
b9a6566267
|
|||
|
2d526b899a
|
|||
|
f8251a3e74
|
|||
|
e42cbc31ba
|
|||
|
a1add6b61b
|
|||
|
21a0207873
|
|||
|
b1f952ec58
|
|||
|
d5495e2e84
|
|||
|
414e53e6e9
|
|||
|
35656af040
|
|||
|
8a9df4d883
|
|||
|
12a7221a2e
|
|||
|
55ea5b31e1
|
|||
|
6a0be6e469
|
|||
|
5268ad0b7a
|
|||
|
1072e349c0
|
|||
|
2d345b04c3
|
|||
|
3d51fde427
|
|||
|
9f48f4eef1
|
|||
|
d3d6cada0a
|
|||
|
40662b33aa
|
|||
|
b7a924719e
|
|||
|
5bc3250c15
|
|||
|
ed2e7ef650
|
|||
|
0f1f041cbf
|
|||
|
9aa53db35f
|
|||
|
84f5a61ddf
|
|||
|
9885971549
|
|||
|
7c86563242
|
|||
|
edc60bafb8
|
|||
|
d7ff0010bd
|
|||
|
f16e92b7d8
|
|||
|
16c40ce7fe
|
|||
|
6ceee577de
|
|||
|
56846b7643
|
|||
|
2508d365c3
|
|||
|
42675a5fe1
|
|||
|
843c234bcf
|
|||
|
e9bcf0e712
|
|||
|
2baa820683
|
|||
|
a784f3c33f
|
|||
|
9cc94f25f2
|
|||
|
|
3cfb22f590
|
||
|
|
e924f2b82d
|
||
|
|
31e761300a
|
||
|
|
fb44367da7
|
||
|
|
6de8684d89
|
||
|
|
61d2994e40
|
||
|
|
8be959eefd
|
||
|
|
e852d29824
|
||
|
|
f11f71020d
|
||
|
|
1bcd9f1113
|
||
|
|
398bb2efde
|
||
|
|
26f2655e3f
|
||
|
|
e34b2855ba
|
||
|
|
9f25995c82
|
||
|
e5273c7012
|
|||
|
e19e7c9253
|
|||
|
50fe918561
|
|||
|
9d18c40a43
|
|||
|
|
fc87693d64 | ||
|
|
5279b14975 | ||
|
|
af0c6ad421 | ||
|
|
ebd0479cd9 | ||
|
|
d1991d9abc | ||
|
|
5b0666920c | ||
|
|
cd2839e6ca | ||
|
|
dd176256bb | ||
|
|
ec09cb9625 |
@@ -1,15 +1,11 @@
|
|||||||
#include "about.h"
|
#include "about.h"
|
||||||
#include "ui_about.h"
|
#include "ui_about.h"
|
||||||
|
|
||||||
About::About(QWidget *parent) :
|
About::About(QWidget* parent) : QDialog(parent), ui(new Ui::About) {
|
||||||
QDialog(parent),
|
|
||||||
ui(new Ui::About)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->lblVersion->setText(ui->lblVersion->text() + " " + __DATE__ + " " + __TIME__);
|
ui->lblVersion->setText(ui->lblVersion->text() + " " + __DATE__ + " " + __TIME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
About::~About()
|
About::~About() {
|
||||||
{
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ namespace Ui {
|
|||||||
class About;
|
class About;
|
||||||
}
|
}
|
||||||
|
|
||||||
class About : public QDialog
|
class About : public QDialog {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit About(QWidget *parent = nullptr);
|
explicit About(QWidget* parent = nullptr);
|
||||||
~About();
|
~About();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::About *ui;
|
Ui::About* ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ABOUT_H
|
#endif // ABOUT_H
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char* argv[]) {
|
||||||
{
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.show();
|
w.show();
|
||||||
|
|||||||
@@ -1,107 +1,97 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "ui_mainwindow.h"
|
|
||||||
#include "QUdpSocket"
|
#include "QUdpSocket"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||||
: QMainWindow(parent)
|
|
||||||
, ui(new Ui::MainWindow)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
m_udpSocket = new QUdpSocket(this);
|
m_udpSocket = new QUdpSocket(this);
|
||||||
m_udpSocket->bind(QHostAddress::Any, UDP_PORT, QUdpSocket::ShareAddress);
|
m_udpSocket->bind(QHostAddress::Any, UDP_PORT, QUdpSocket::ShareAddress);
|
||||||
|
|
||||||
connect(m_udpSocket, &QUdpSocket::readyRead,
|
connect(m_udpSocket, &QUdpSocket::readyRead, this, &MainWindow::processPendingDatagrams);
|
||||||
this, &MainWindow::processPendingDatagrams);
|
|
||||||
|
|
||||||
//Timer just to ask twice (udp)
|
// Timer just to ask twice (udp)
|
||||||
m_timer = new QTimer(this);
|
m_timer = new QTimer(this);
|
||||||
m_timer->setSingleShot(true);
|
m_timer->setSingleShot(true);
|
||||||
m_timer->setInterval(500);
|
m_timer->setInterval(500);
|
||||||
connect(m_timer,&QTimer::timeout, this, &MainWindow::SendRequest);
|
connect(m_timer, &QTimer::timeout, this, &MainWindow::SendRequest);
|
||||||
|
|
||||||
//Send Request on startup
|
// Send Request on startup
|
||||||
on_pbRefresh_clicked();
|
on_pbRefresh_clicked();
|
||||||
|
|
||||||
ui->devices->setIconSize(QSize(48,48));
|
ui->devices->setIconSize(QSize(48, 48));
|
||||||
ui->devices->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->devices->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
ui->comboBox->addItem("default");
|
ui->comboBox->addItem("default");
|
||||||
ui->comboBox->addItem("192.168.69.10"); //test
|
ui->comboBox->addItem("192.168.69.10"); // test
|
||||||
if (ui->comboBox->currentText()=="default"){
|
if (ui->comboBox->currentText() == "default") {
|
||||||
ui->ChangeOwner->setDisabled(true);
|
ui->ChangeOwner->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// //Example items for screenshot:
|
// //Example items for screenshot:
|
||||||
// QListWidgetItem * item = new QListWidgetItem(QIcon(":/res/stm32.png"), "00:80:E1:05:44:21 @ 192.168.0.11 (John Doe)");
|
// QListWidgetItem * item = new QListWidgetItem(QIcon(":/res/stm32.png"), "00:80:E1:05:44:21 @ 192.168.0.11 (John
|
||||||
// ui->devices->addItem(item);
|
// Doe)"); ui->devices->addItem(item); QListWidgetItem * item2 = new QListWidgetItem(QIcon(":/res/rpi.png"),
|
||||||
// QListWidgetItem * item2 = new QListWidgetItem(QIcon(":/res/rpi.png"), "E4:5F:01:05:44:21 @ 192.168.0.11 (Jane Doe)");
|
// "E4:5F:01:05:44:21 @ 192.168.0.11 (Jane Doe)"); ui->devices->addItem(item2); QListWidgetItem * item3 = new
|
||||||
// ui->devices->addItem(item2);
|
// QListWidgetItem(QIcon(":/res/unknown.png"), "44:44:44:05:44:21 @ 192.168.0.11 (Juul Doe)");
|
||||||
// QListWidgetItem * item3 = new QListWidgetItem(QIcon(":/res/unknown.png"), "44:44:44:05:44:21 @ 192.168.0.11 (Juul Doe)");
|
// ui->devices->addItem(item3);
|
||||||
// ui->devices->addItem(item3);
|
|
||||||
connect(ui->actionAbout_Qt, &QAction::triggered, QApplication::aboutQt);
|
connect(ui->actionAbout_Qt, &QAction::triggered, QApplication::aboutQt);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow() {
|
||||||
{
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_pbRefresh_clicked()
|
void MainWindow::on_pbRefresh_clicked() {
|
||||||
{
|
|
||||||
this->func = 0;
|
this->func = 0;
|
||||||
SendRequest();
|
SendRequest();
|
||||||
m_timer->start();
|
m_timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SendRequest()
|
void MainWindow::SendRequest() {
|
||||||
{
|
|
||||||
int broadcasts_send = 0;
|
int broadcasts_send = 0;
|
||||||
int data_send = 0;
|
int data_send = 0;
|
||||||
QUdpSocket udpSocket;
|
QUdpSocket udpSocket;
|
||||||
QByteArray datagram;
|
QByteArray datagram;
|
||||||
if(this->func == 0){
|
if (this->func == 0) {
|
||||||
datagram = UDP_REQUEST"v1.0";
|
datagram = UDP_REQUEST "v1.0";
|
||||||
//Get all the Network Interface Cards of this Computer
|
// Get all the Network Interface Cards of this Computer
|
||||||
QList<QNetworkInterface> NICs = QNetworkInterface::allInterfaces();
|
QList<QNetworkInterface> NICs = QNetworkInterface::allInterfaces();
|
||||||
foreach(QNetworkInterface NIC, NICs){
|
foreach (QNetworkInterface NIC, NICs) {
|
||||||
//Get all the adresses on this NIC
|
// Get all the adresses on this NIC
|
||||||
QList<QNetworkAddressEntry> adresses = NIC.addressEntries();
|
QList<QNetworkAddressEntry> adresses = NIC.addressEntries();
|
||||||
foreach(QNetworkAddressEntry adress, adresses){
|
foreach (QNetworkAddressEntry adress, adresses) {
|
||||||
QD << NIC.name() << adress.ip();
|
QD << NIC.name() << adress.ip();
|
||||||
//If broadcast adress = null => IPv6 (no support for broadcasts)
|
// If broadcast adress = null => IPv6 (no support for broadcasts)
|
||||||
QHostAddress broadc_addr = adress.broadcast();
|
QHostAddress broadc_addr = adress.broadcast();
|
||||||
if(!broadc_addr.isNull()){
|
if (!broadc_addr.isNull()) {
|
||||||
//Send UDP packet
|
// Send UDP packet
|
||||||
udpSocket.writeDatagram(datagram, adress.broadcast(), UDP_PORT);
|
udpSocket.writeDatagram(datagram, adress.broadcast(), UDP_PORT);
|
||||||
broadcasts_send++;
|
broadcasts_send++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (this->func == 1) {
|
||||||
else if(this->func == 1){
|
|
||||||
QHostAddress addr(ui->comboBox->currentText());
|
QHostAddress addr(ui->comboBox->currentText());
|
||||||
udpSocket.writeDatagram(this->data, addr, UDP_PORT);
|
udpSocket.writeDatagram(this->data, addr, UDP_PORT);
|
||||||
data_send++;
|
data_send++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (broadcasts_send == 0 && data_send == 0) {
|
||||||
if(broadcasts_send == 0 && data_send == 0){
|
ui->pteLog->appendPlainText(
|
||||||
ui->pteLog->appendPlainText("Warning: no Network Interface Cards or valid IP adresses found (no broadcasts send)");
|
"Warning: no Network Interface Cards or valid IP adresses found (no broadcasts send)");
|
||||||
}else if(data_send != 0){
|
} else if (data_send != 0) {
|
||||||
ui->pteLog->appendPlainText(tr("Info: %1 message sent to %2").arg(data_send).arg(ui->comboBox->currentText()));
|
ui->pteLog->appendPlainText(tr("Info: %1 message sent to %2").arg(data_send).arg(ui->comboBox->currentText()));
|
||||||
}else{
|
} else {
|
||||||
ui->pteLog->appendPlainText(tr("Info: %1 broadcasts send").arg(broadcasts_send));
|
ui->pteLog->appendPlainText(tr("Info: %1 broadcasts send").arg(broadcasts_send));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::processPendingDatagrams()
|
void MainWindow::processPendingDatagrams() {
|
||||||
{
|
|
||||||
QByteArray datagram;
|
QByteArray datagram;
|
||||||
QHostAddress host;
|
QHostAddress host;
|
||||||
|
|
||||||
// just get rid of every host in the combobox, not pretty code, i know
|
// just get rid of every host in the combobox, not pretty code, i know
|
||||||
if(this->func == 0){
|
if (this->func == 0) {
|
||||||
for(int i = 1; i < ui->comboBox->count(); i++){
|
for (int i = 1; i < ui->comboBox->count(); i++) {
|
||||||
ui->comboBox->removeItem(i);
|
ui->comboBox->removeItem(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,74 +104,69 @@ void MainWindow::processPendingDatagrams()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::processDatagram(QString msg,QString host)
|
void MainWindow::processDatagram(QString msg, QString host) {
|
||||||
{
|
// Append received data to log
|
||||||
|
QString logLine = tr("Van %1: \"%2\"").arg(host).arg(msg);
|
||||||
//Append received data to log
|
|
||||||
QString logLine = tr("Van %1: \"%2\"")
|
|
||||||
.arg(host)
|
|
||||||
.arg(msg);
|
|
||||||
ui->pteLog->appendPlainText(logLine);
|
ui->pteLog->appendPlainText(logLine);
|
||||||
|
|
||||||
//We receive our own request. So a check to see if it is the request:
|
// We receive our own request. So a check to see if it is the request:
|
||||||
if(msg.indexOf(UDP_REQUEST) != -1){
|
if (msg.indexOf(UDP_REQUEST) != -1) {
|
||||||
return; //we are done here...
|
return; // we are done here...
|
||||||
}
|
}
|
||||||
|
|
||||||
// add new host to select in combobox
|
// add new host to select in combobox
|
||||||
if(this->func == 0){
|
if (this->func == 0) {
|
||||||
ui->comboBox->addItem(host);
|
ui->comboBox->addItem(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegEx for MAC adress
|
||||||
//RegEx for MAC adress
|
QRegularExpression macRegExp(
|
||||||
QRegularExpression macRegExp("([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})");
|
"([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})");
|
||||||
QRegularExpressionMatch match = macRegExp.match(msg.toUpper());
|
QRegularExpressionMatch match = macRegExp.match(msg.toUpper());
|
||||||
if(match.hasMatch()){
|
if (match.hasMatch()) {
|
||||||
QString foundOUI = match.captured(1) % match.captured(2) % match.captured(3);
|
QString foundOUI = match.captured(1) % match.captured(2) % match.captured(3);
|
||||||
QString foundMAC = match.captured(0);
|
QString foundMAC = match.captured(0);
|
||||||
QString imgName = ":/res/unknown.png";
|
QString imgName = ":/res/unknown.png";
|
||||||
/*grep STMicro oui.txt | grep base
|
/*grep STMicro oui.txt | grep base
|
||||||
0080E1 (base 16) STMicroelectronics SRL
|
0080E1 (base 16) STMicroelectronics SRL
|
||||||
10E77A (base 16) STMicrolectronics International NV*/
|
10E77A (base 16) STMicrolectronics International NV*/
|
||||||
if(foundOUI == "0080E1" || foundOUI == "10E77A") {
|
if (foundOUI == "0080E1" || foundOUI == "10E77A") {
|
||||||
imgName = ":/res/stm32.png";
|
imgName = ":/res/stm32.png";
|
||||||
}
|
}
|
||||||
/*grep Raspberry oui.txt | grep base
|
/*grep Raspberry oui.txt | grep base
|
||||||
DCA632 (base 16) Raspberry Pi Trading Ltd
|
DCA632 (base 16) Raspberry Pi Trading Ltd
|
||||||
E45F01 (base 16) Raspberry Pi Trading Ltd
|
E45F01 (base 16) Raspberry Pi Trading Ltd
|
||||||
B827EB (base 16) Raspberry Pi Foundation*/
|
B827EB (base 16) Raspberry Pi Foundation*/
|
||||||
if(foundOUI == "DCA632" || foundOUI == "E45F01" || foundOUI == "B827EB") {
|
if (foundOUI == "DCA632" || foundOUI == "E45F01" || foundOUI == "B827EB") {
|
||||||
imgName = ":/res/rpi.png";
|
imgName = ":/res/rpi.png";
|
||||||
}
|
}
|
||||||
QString needle = UDP_ANS_OWNER;
|
QString needle = UDP_ANS_OWNER;
|
||||||
QString owner = "???";
|
QString owner = "???";
|
||||||
int index = msg.indexOf(needle);
|
int index = msg.indexOf(needle);
|
||||||
if(index != -1){
|
if (index != -1) {
|
||||||
owner = msg.mid(index + needle.length());
|
owner = msg.mid(index + needle.length());
|
||||||
}else{
|
} else {
|
||||||
ui->pteLog->appendPlainText("Warning: no OWNER found in message");
|
ui->pteLog->appendPlainText("Warning: no OWNER found in message");
|
||||||
}
|
}
|
||||||
|
|
||||||
QListWidgetItem * item = searchItem(foundMAC);
|
QListWidgetItem* item = searchItem(foundMAC);
|
||||||
if(item == nullptr){
|
if (item == nullptr) {
|
||||||
item = new QListWidgetItem();
|
item = new QListWidgetItem();
|
||||||
ui->devices->addItem(item);
|
ui->devices->addItem(item);
|
||||||
}
|
}
|
||||||
item->setIcon(QIcon(imgName));
|
item->setIcon(QIcon(imgName));
|
||||||
item->setText(tr("%1 @ %2 (%3)").arg(foundMAC).arg(host).arg(owner));
|
item->setText(tr("%1 @ %2 (%3)").arg(foundMAC).arg(host).arg(owner));
|
||||||
item->setToolTip(tr("Last seen: %1").arg(QTime::currentTime().toString("H:mm:ss.zzz")));
|
item->setToolTip(tr("Last seen: %1").arg(QTime::currentTime().toString("H:mm:ss.zzz")));
|
||||||
}else{
|
} else {
|
||||||
ui->pteLog->appendPlainText("Warning: no MAC found in message");
|
ui->pteLog->appendPlainText("Warning: no MAC found in message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QListWidgetItem *MainWindow::searchItem(QString MAC)
|
QListWidgetItem* MainWindow::searchItem(QString MAC) {
|
||||||
{
|
QListWidgetItem* item = nullptr;
|
||||||
QListWidgetItem * item = nullptr;
|
for (int i = 0; i < ui->devices->count(); i++) {
|
||||||
for(int i = 0; i < ui->devices->count(); i++){
|
|
||||||
item = ui->devices->item(i);
|
item = ui->devices->item(i);
|
||||||
if(item->text().contains(MAC)){
|
if (item->text().contains(MAC)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
item = nullptr;
|
item = nullptr;
|
||||||
@@ -189,70 +174,56 @@ QListWidgetItem *MainWindow::searchItem(QString MAC)
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_devices_itemDoubleClicked(QListWidgetItem *item)
|
void MainWindow::on_devices_itemDoubleClicked(QListWidgetItem* item) {
|
||||||
{
|
// Copy the IP to the clipboard
|
||||||
//Copy the IP to the clipboard
|
|
||||||
QString itemText = item->text();
|
QString itemText = item->text();
|
||||||
int start = itemText.indexOf('@')+2;
|
int start = itemText.indexOf('@') + 2;
|
||||||
int end = itemText.indexOf('(')-1;
|
int end = itemText.indexOf('(') - 1;
|
||||||
QString ip = itemText.mid(start,end - start);
|
QString ip = itemText.mid(start, end - start);
|
||||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
QClipboard* clipboard = QGuiApplication::clipboard();
|
||||||
clipboard->setText(ip);
|
clipboard->setText(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_devices_customContextMenuRequested(const QPoint &pos)
|
void MainWindow::on_devices_customContextMenuRequested(const QPoint& pos) {
|
||||||
{
|
// create menu
|
||||||
//create menu
|
QAction copyAction(QIcon(":/res/copy-icon.png"), "Copy IP");
|
||||||
QAction copyAction(QIcon(":/res/copy-icon.png"),"Copy IP");
|
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
menu.addAction(©Action);
|
menu.addAction(©Action);
|
||||||
|
|
||||||
//execute menu
|
// execute menu
|
||||||
QAction * action = menu.exec(ui->devices->mapToGlobal(pos));
|
QAction* action = menu.exec(ui->devices->mapToGlobal(pos));
|
||||||
if(action == ©Action){
|
if (action == ©Action) {
|
||||||
QListWidgetItem *item = ui->devices->itemAt(pos);
|
QListWidgetItem* item = ui->devices->itemAt(pos);
|
||||||
if(item){
|
if (item) {
|
||||||
on_devices_itemDoubleClicked(item);
|
on_devices_itemDoubleClicked(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionAbout_triggered()
|
void MainWindow::on_actionAbout_triggered() {
|
||||||
{
|
|
||||||
About ab(this);
|
About ab(this);
|
||||||
ab.exec();
|
ab.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_name_textEdited(const QString &arg1)
|
void MainWindow::on_name_textEdited(const QString& arg1) {
|
||||||
{
|
|
||||||
this->name = arg1;
|
this->name = arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_surname_textEdited(const QString& arg1) {
|
||||||
|
|
||||||
void MainWindow::on_surname_textEdited(const QString &arg1)
|
|
||||||
{
|
|
||||||
this->surname = arg1;
|
this->surname = arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_comboBox_currentIndexChanged(int index) {
|
||||||
void MainWindow::on_comboBox_currentIndexChanged(int index)
|
if (index == 0) {
|
||||||
{
|
|
||||||
if(index == 0){
|
|
||||||
ui->ChangeOwner->setDisabled(true);
|
ui->ChangeOwner->setDisabled(true);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
ui->ChangeOwner->setDisabled(false);
|
ui->ChangeOwner->setDisabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_ChangeOwner_clicked() {
|
||||||
void MainWindow::on_ChangeOwner_clicked()
|
|
||||||
{
|
|
||||||
this->data = ("func1:name: " + this->name + ", surname: " + this->surname + "").toUtf8();
|
this->data = ("func1:name: " + this->name + ", surname: " + this->surname + "").toUtf8();
|
||||||
this->func = 1;
|
this->func = 1;
|
||||||
SendRequest();
|
SendRequest();
|
||||||
m_timer->start();
|
m_timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,52 +6,53 @@
|
|||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#define QD qDebug() << __FILE__ << __LINE__
|
#define QD qDebug() << __FILE__ << __LINE__
|
||||||
|
|
||||||
#include "about.h"
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include "about.h"
|
||||||
|
|
||||||
// UDP protocol:
|
// UDP protocol:
|
||||||
//REQ= Where are you?v1.0
|
// REQ= Where are you?v1.0
|
||||||
//ANS= XX:XX:XX:XX:XX:XX is present and my owner is YYYYYY ZZZZZZ
|
// ANS= XX:XX:XX:XX:XX:XX is present and my owner is YYYYYY ZZZZZZ
|
||||||
#define UDP_PORT 64000
|
#define UDP_PORT 64000
|
||||||
#define UDP_REQUEST "Where are you?"
|
#define UDP_REQUEST "Where are you?"
|
||||||
#define UDP_ANS_OWNER "my owner is "
|
#define UDP_ANS_OWNER "my owner is "
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class MainWindow; }
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MainWindow(QWidget *parent = nullptr);
|
MainWindow(QWidget* parent = nullptr);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SendRequest();
|
void SendRequest();
|
||||||
void processPendingDatagrams();
|
void processPendingDatagrams();
|
||||||
|
|
||||||
void on_pbRefresh_clicked();
|
void on_pbRefresh_clicked();
|
||||||
void on_devices_itemDoubleClicked(QListWidgetItem *item);
|
void on_devices_itemDoubleClicked(QListWidgetItem* item);
|
||||||
void on_devices_customContextMenuRequested(const QPoint &pos);
|
void on_devices_customContextMenuRequested(const QPoint& pos);
|
||||||
|
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
|
|
||||||
void on_name_textEdited(const QString &arg1);
|
void on_name_textEdited(const QString& arg1);
|
||||||
|
|
||||||
void on_surname_textEdited(const QString &arg1);
|
void on_surname_textEdited(const QString& arg1);
|
||||||
|
|
||||||
void on_comboBox_currentIndexChanged(int index);
|
void on_comboBox_currentIndexChanged(int index);
|
||||||
|
|
||||||
void on_ChangeOwner_clicked();
|
void on_ChangeOwner_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow* ui;
|
||||||
QTimer * m_timer;
|
QTimer* m_timer;
|
||||||
QUdpSocket *m_udpSocket = nullptr;
|
QUdpSocket* m_udpSocket = nullptr;
|
||||||
void processDatagram(QString msg, QString host);
|
void processDatagram(QString msg, QString host);
|
||||||
QListWidgetItem *searchItem(QString MAC);
|
QListWidgetItem* searchItem(QString MAC);
|
||||||
QString name;
|
QString name;
|
||||||
QString surname;
|
QString surname;
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
project(WSAA_tests LANGUAGES CXX C)
|
project(WSAA_tests LANGUAGES CXX C)
|
||||||
|
|
||||||
|
|||||||
104
docs/tcp_cmd_interface.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# TCP CMD Interface
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The tcp cmd interface is a way to control the device over TCP. It is a simple protocol that allows the user to send commands to the device and receive responses. The protocol looks like bash commands. The commands are separated by a new line character (`\n`). The response is sent after the command is executed. The response is also terminated by a new line character (`\n`).
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
* [Introduction](#introduction)
|
||||||
|
* [Table of contents](#table-of-contents)
|
||||||
|
* [Usage of TCP CMD Interface](#usage-of-tcp-cmd-interface)
|
||||||
|
* [Connecting to the device](#connecting-to-the-device)
|
||||||
|
* [Sending commands](#sending-commands)
|
||||||
|
* [Available commands](#available-commands)
|
||||||
|
* [`help`](#help)
|
||||||
|
* [`text`](#text)
|
||||||
|
* [`bgcolor`](#bgcolor)
|
||||||
|
* [`color`](#color)
|
||||||
|
* [`listImages`](#listimages)
|
||||||
|
* [`setImage`](#setimage)
|
||||||
|
* [`setGif`](#setgif)
|
||||||
|
|
||||||
|
## Usage of TCP CMD Interface
|
||||||
|
### Connecting to the device
|
||||||
|
The device can be connected to using a TCP client. The device will listen on port 23. The device will send a welcome message when a client connects.
|
||||||
|
|
||||||
|
On Linux, the device can be connected to using the `nc` command:
|
||||||
|
```bash
|
||||||
|
nc <ip-address> 23
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sending commands
|
||||||
|
Commands can be sent to the device by typing them in the terminal and pressing enter. The device will execute the command and send a response.
|
||||||
|
|
||||||
|
### Available commands
|
||||||
|
#### `help`
|
||||||
|
The `help` command will print a list of available commands.
|
||||||
|
```bash
|
||||||
|
$> help
|
||||||
|
help : shows a list of commands
|
||||||
|
text "<text>" : puts text on the lcd
|
||||||
|
color (<a>) <r> <g> <b> : set the background color of the lcd
|
||||||
|
textColor (<a>) <r> <g> <b> : set the color of the text
|
||||||
|
listImages : shows a list with images in the filesystem
|
||||||
|
setImage <image_name> : put an image on the screen
|
||||||
|
setGif <image_name> : put a gif on the screen
|
||||||
|
exit : closes the connection
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `text`
|
||||||
|
The `text` command will print the given text on the screen. The text can be one or multiple words. one word does'n need quotes, multiple words do. The text will rapp around when it reaches the end of the screen.
|
||||||
|
```bash
|
||||||
|
$> text "Hello World!"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `bgcolor`
|
||||||
|
The `bgcolor` command will set the background color of the screen. The color can be provided in 2 ways: as three numbers between 0 and 255 and one hex value. The first number is the red value, the second is the green value and the third is the blue value. It also has the possible to set the alpha value as the first parameter, this is optional.
|
||||||
|
```bash
|
||||||
|
bgcolor 255 0 0
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
bgcolor 0xFF0000
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `color`
|
||||||
|
The `color` command will set the color of the text. The color can be provided in 2 ways: as three numbers between 0 and 255 and one hex value. The first number is the red value, the second is the green value and the third is the blue value. It also has the possible to set the alpha value as the first parameter, this is optional.
|
||||||
|
```bash
|
||||||
|
color 255 0 0
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
color 0xFF0000
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `listImages`
|
||||||
|
The `listImages` command will print a list of images that are present in the filesystem.
|
||||||
|
```bash
|
||||||
|
$> listImages
|
||||||
|
image1.bmp
|
||||||
|
image2.bmp
|
||||||
|
image3.bmp
|
||||||
|
gif1.gif
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `setImage`
|
||||||
|
The `setImage` command will put an image on the screen. The image must be present in the filesystem. If the image is not present in the filesystem, the device will send an error message. This function only works for BMP images, if you give any other file type, the device will send an error message. You can also provide the starting x and y coordinates as optional parameters. If no coordinates are provided, the image will be placed at the top left corner of the screen (0,0).
|
||||||
|
```bash
|
||||||
|
$> setImage image1.bmp
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
$> setImage image1.bmp 128 64
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `setGif`
|
||||||
|
The `setGif` command will put a gif on the screen. The gif must be present in the filesystem. If the gif is not present in the filesystem, the device will send an error message. This function only works for GIF images, if you give any other file type, the device will send an error message. You can also provide the starting x and y coordinates as optional parameters. If no coordinates are provided, the gif will be placed at the top left corner of the screen (0,0).
|
||||||
|
```bash
|
||||||
|
$> setGif gif1.gif
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
$> setGif gif1.gif 128 64
|
||||||
|
```
|
||||||
BIN
llfs-data/base.bmp
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
llfs-data/clap.gif
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
llfs-data/dafoe.bmp
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
llfs-data/fellowkids.bmp
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
llfs-data/goose.bmp
Normal file
|
After Width: | Height: | Size: 117 KiB |
122
llfs-data/index.css
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
body{
|
||||||
|
font-family:Arial;
|
||||||
|
}
|
||||||
|
h1{
|
||||||
|
font-size: 175%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 150%;
|
||||||
|
padding: 8px;
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
left: 20px;
|
||||||
|
background-color:orangered;
|
||||||
|
color: white;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 125%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
padding: 30px;
|
||||||
|
background-color: orangered;
|
||||||
|
}
|
||||||
|
header:after {
|
||||||
|
content:"";
|
||||||
|
display: block;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.logo{
|
||||||
|
width:100px;
|
||||||
|
transform:rotate(-10deg);
|
||||||
|
-moz-transform:rotate(-10deg);
|
||||||
|
-webkit-transform:rotate(-10deg);
|
||||||
|
-o-transform:rotate(-10deg);
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
.title{
|
||||||
|
color: white;
|
||||||
|
font-size: 40px;
|
||||||
|
font: 60px "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
.column {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-basis: 48%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
margin-left: 2%;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
/*Geef vorm aan de vakjes op de site*/
|
||||||
|
.card {
|
||||||
|
background-color: white;
|
||||||
|
border-radius:10px;
|
||||||
|
padding:1%;
|
||||||
|
border: 1px solid black;
|
||||||
|
margin: 2% 0;
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 30px;
|
||||||
|
}
|
||||||
|
.image {
|
||||||
|
width: 25%;
|
||||||
|
height: auto;
|
||||||
|
border: 10px solid transparent;
|
||||||
|
}
|
||||||
|
.image:hover {
|
||||||
|
border: 10px solid lightsalmon;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
#selected {
|
||||||
|
border: 10px solid lightsalmon;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.sendButton {
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 8%;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 40%;
|
||||||
|
font-size: 150%;
|
||||||
|
padding: 20px;
|
||||||
|
background-color:orangered;
|
||||||
|
color: white;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
.sendButton:hover {
|
||||||
|
background-color:white;
|
||||||
|
color: orangered ;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------------------*/
|
||||||
|
footer {
|
||||||
|
background-color: orangered;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-top:20px solid lightskyblue; /*solid is vast*/
|
||||||
|
border-bottom:20px solid lightskyblue;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.foot {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
html{
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
#myImg {
|
||||||
|
border: none;
|
||||||
|
transition: border 0.3s;
|
||||||
|
}
|
||||||
133
llfs-data/index.html
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Webservices & Applications</title>
|
||||||
|
<link href="reset.css" rel="stylesheet" />
|
||||||
|
<link href="index.css" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<header>
|
||||||
|
<img class="logo" src="st.bmp" alt="STM"/>
|
||||||
|
<p class="title">
|
||||||
|
Webservices & Applications
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form action="cgi">
|
||||||
|
<div class="content row">
|
||||||
|
<div class="column left">
|
||||||
|
<div class="card">
|
||||||
|
<h2>Adjustments</h2>
|
||||||
|
<label for="send_text">Text LCD:</label>
|
||||||
|
<input type="text" id="send_text" name="vtxt"><br><br>
|
||||||
|
<label for="send_colorTxt">Select the text color:</label>
|
||||||
|
<input type="color" id="send_colorTxt" name="vktxt" value="#0000ff"><br><br>
|
||||||
|
<label for="send_colorBack">Select the background color:</label>
|
||||||
|
<input type="color" id="send_colorBack" name="vka" value="#0000ff"><br><br>
|
||||||
|
<!--<span class="sendButton" onClick="start();">
|
||||||
|
<input type="submit" value="Send">
|
||||||
|
</span>-->
|
||||||
|
<input type="submit" value="Send" class="sendButton" onClick="start();">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column right">
|
||||||
|
<div class="card">
|
||||||
|
<h2 >Images</h2>
|
||||||
|
<label for="vfo">Choose your photo:</label>
|
||||||
|
<div class="gallery" id="gallery">
|
||||||
|
<input type="hidden" id="gallery1" name="vfo" value="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.getElementById('send_colorBack').addEventListener('input', function() { document.body.style.backgroundColor = this.value; });
|
||||||
|
document.getElementById('send_colorTxt').addEventListener('input', function() { document.getElementById('send_text').style.color = this.value; });
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Function to load images from the folder
|
||||||
|
function loadImages() {
|
||||||
|
console.log("loadImages");
|
||||||
|
const xhttp = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhttp.onload = function() {
|
||||||
|
const imageContainer = document.getElementById('gallery');
|
||||||
|
console.log(this.responseText);
|
||||||
|
images = this.responseText.split('|');
|
||||||
|
console.log(images);
|
||||||
|
for (let i = 0; i < images.length; i++) {
|
||||||
|
console.log(images[i]);
|
||||||
|
const img = document.createElement('img');;
|
||||||
|
img.src= images[i];
|
||||||
|
img.alt = images[i];
|
||||||
|
img.className = `image ${i}`;
|
||||||
|
img.value = images[i];
|
||||||
|
img.onload = () => {
|
||||||
|
imageContainer.appendChild(img);
|
||||||
|
}
|
||||||
|
img.onclick = () => {
|
||||||
|
selecteerFoto(img, i, images[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhttp.open("GET", "images.info");
|
||||||
|
xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function selecteerFoto(image, i, images) {
|
||||||
|
var gallery = document.getElementById('gallery1');
|
||||||
|
var value = gallery.getAttribute('value');
|
||||||
|
var Pictures = document.querySelectorAll('.gallery img');
|
||||||
|
Pictures.forEach(function(image) {
|
||||||
|
image.removeAttribute('id');
|
||||||
|
image.removeAttribute('name');
|
||||||
|
});
|
||||||
|
image.id = "selected";
|
||||||
|
image.name = "vfo";
|
||||||
|
image.value = images[i];
|
||||||
|
gallery.setAttribute('value', images);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function to load the images
|
||||||
|
loadImages();
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
var send_text = document.getElementById("send_text").value;
|
||||||
|
var send_colorTxt = document.getElementById("send_colorTxt").value;
|
||||||
|
var send_colorBack = document.getElementById("send_colorBack").value;
|
||||||
|
var sendPicture = document.getElementById("selected").alt;
|
||||||
|
var url = "cgi?";
|
||||||
|
|
||||||
|
var queryString = url + "vtxt=" + send_text + "&vktxt=" + encodeURIComponent(send_colorTxt) + "&vka=" + encodeURIComponent(send_colorBack) + "&vfo=" + sendPicture;
|
||||||
|
console.log(queryString);
|
||||||
|
|
||||||
|
xhr.onreadystatechange = showAnswer;
|
||||||
|
xhr.open("GET", queryString);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAnswer() {
|
||||||
|
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||||
|
alert(xhr.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<footer>
|
||||||
|
<p class="foot">
|
||||||
|
Copyright © Thomas More Mechelen-Antwerpen vzw -
|
||||||
|
Campus De Nayer - Professionele bachelor elektronica-ict –
|
||||||
|
2023
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
BIN
llfs-data/mind.gif
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
62
llfs-data/reset.css
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* http://meyerweb.com/eric/tools/css/reset/
|
||||||
|
v2.0b1 | 201101
|
||||||
|
NOTE: WORK IN PROGRESS
|
||||||
|
USE WITH CAUTION AND TEST WITH ABANDON */
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, menu, nav, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article, aside, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, menu, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
blockquote, q {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
blockquote:before, blockquote:after,
|
||||||
|
q:before, q:after {
|
||||||
|
content: '';
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remember to define visible focus styles!
|
||||||
|
:focus {
|
||||||
|
outline: ?????;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* remember to highlight inserts somehow! */
|
||||||
|
ins {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
del {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
BIN
llfs-data/webp.bmp
Normal file
|
After Width: | Height: | Size: 114 KiB |
@@ -60,11 +60,12 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the header of the output file
|
// Write the header of the output file
|
||||||
fprintf(out_file, "/**\n"
|
fprintf(out_file,
|
||||||
" * @file %s\n"
|
"/**\n"
|
||||||
" * @brief Linked list file system (llfs) data file.\n"
|
" * @file %s\n"
|
||||||
" * This file was generated by mkllfs %s.\n"
|
" * @brief Linked list file system (llfs) data file.\n"
|
||||||
" * @date %s\n */\n\n",
|
" * This file was generated by mkllfs %s.\n"
|
||||||
|
" * @date %s\n */\n\n",
|
||||||
argv[argc - 1], VERSION, __DATE__);
|
argv[argc - 1], VERSION, __DATE__);
|
||||||
|
|
||||||
// Write the headers of the output file
|
// Write the headers of the output file
|
||||||
@@ -125,7 +126,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
// Make the last file the root file of the llfs
|
// Make the last file the root file of the llfs
|
||||||
fprintf(out_file, "\n");
|
fprintf(out_file, "\n");
|
||||||
fprintf(out_file, "const struct llfs_data_file *llfs_root =%s%s;\n", (strcmp(prev_llfs_name, "NULL") == 0 ? " " : " &"), prev_llfs_name);
|
fprintf(out_file, "const struct llfs_data_file *llfs_root =%s%s;\n",
|
||||||
|
(strcmp(prev_llfs_name, "NULL") == 0 ? " " : " &"), prev_llfs_name);
|
||||||
|
|
||||||
// Print the number of files
|
// Print the number of files
|
||||||
printf("Successfully converted %d files.\r\n", file_count);
|
printf("Successfully converted %d files.\r\n", file_count);
|
||||||
|
|||||||
543
mkllfs/tinydir.h
@@ -45,63 +45,62 @@ extern "C" {
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
# define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
# endif
|
#endif
|
||||||
# include <windows.h>
|
#include <tchar.h>
|
||||||
# include <tchar.h>
|
#include <windows.h>
|
||||||
# pragma warning(push)
|
#pragma warning(push)
|
||||||
# pragma warning (disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
#else
|
#else
|
||||||
# include <dirent.h>
|
#include <dirent.h>
|
||||||
# include <libgen.h>
|
#include <libgen.h>
|
||||||
# include <sys/stat.h>
|
#include <stddef.h>
|
||||||
# include <stddef.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
# include <tchar.h>
|
#include <tchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
|
|
||||||
/* Windows UNICODE wide character support */
|
/* Windows UNICODE wide character support */
|
||||||
#if defined _MSC_VER || defined __MINGW32__
|
#if defined _MSC_VER || defined __MINGW32__
|
||||||
# define _tinydir_char_t TCHAR
|
#define _tinydir_char_t TCHAR
|
||||||
# define TINYDIR_STRING(s) _TEXT(s)
|
#define TINYDIR_STRING(s) _TEXT(s)
|
||||||
# define _tinydir_strlen _tcslen
|
#define _tinydir_strlen _tcslen
|
||||||
# define _tinydir_strcpy _tcscpy
|
#define _tinydir_strcpy _tcscpy
|
||||||
# define _tinydir_strcat _tcscat
|
#define _tinydir_strcat _tcscat
|
||||||
# define _tinydir_strcmp _tcscmp
|
#define _tinydir_strcmp _tcscmp
|
||||||
# define _tinydir_strrchr _tcsrchr
|
#define _tinydir_strrchr _tcsrchr
|
||||||
# define _tinydir_strncmp _tcsncmp
|
#define _tinydir_strncmp _tcsncmp
|
||||||
#else
|
#else
|
||||||
# define _tinydir_char_t char
|
#define _tinydir_char_t char
|
||||||
# define TINYDIR_STRING(s) s
|
#define TINYDIR_STRING(s) s
|
||||||
# define _tinydir_strlen strlen
|
#define _tinydir_strlen strlen
|
||||||
# define _tinydir_strcpy strcpy
|
#define _tinydir_strcpy strcpy
|
||||||
# define _tinydir_strcat strcat
|
#define _tinydir_strcat strcat
|
||||||
# define _tinydir_strcmp strcmp
|
#define _tinydir_strcmp strcmp
|
||||||
# define _tinydir_strrchr strrchr
|
#define _tinydir_strrchr strrchr
|
||||||
# define _tinydir_strncmp strncmp
|
#define _tinydir_strncmp strncmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined _MSC_VER || defined __MINGW32__)
|
#if (defined _MSC_VER || defined __MINGW32__)
|
||||||
# include <windows.h>
|
#include <windows.h>
|
||||||
# define _TINYDIR_PATH_MAX MAX_PATH
|
#define _TINYDIR_PATH_MAX MAX_PATH
|
||||||
#elif defined __linux__
|
#elif defined __linux__
|
||||||
# include <limits.h>
|
#include <limits.h>
|
||||||
# ifdef PATH_MAX
|
#ifdef PATH_MAX
|
||||||
# define _TINYDIR_PATH_MAX PATH_MAX
|
#define _TINYDIR_PATH_MAX PATH_MAX
|
||||||
# endif
|
#endif
|
||||||
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
# include <sys/param.h>
|
#include <sys/param.h>
|
||||||
# if defined(BSD)
|
#if defined(BSD)
|
||||||
# include <limits.h>
|
#include <limits.h>
|
||||||
# ifdef PATH_MAX
|
#ifdef PATH_MAX
|
||||||
# define _TINYDIR_PATH_MAX PATH_MAX
|
#define _TINYDIR_PATH_MAX PATH_MAX
|
||||||
# endif
|
#endif
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _TINYDIR_PATH_MAX
|
#ifndef _TINYDIR_PATH_MAX
|
||||||
@@ -110,9 +109,9 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
/* extra chars for the "\\*" mask */
|
/* extra chars for the "\\*" mask */
|
||||||
# define _TINYDIR_PATH_EXTRA 2
|
#define _TINYDIR_PATH_EXTRA 2
|
||||||
#else
|
#else
|
||||||
# define _TINYDIR_PATH_EXTRA 0
|
#define _TINYDIR_PATH_EXTRA 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _TINYDIR_FILENAME_MAX 256
|
#define _TINYDIR_FILENAME_MAX 256
|
||||||
@@ -122,16 +121,16 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define _TINYDIR_FUNC static __inline
|
#define _TINYDIR_FUNC static __inline
|
||||||
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
||||||
# define _TINYDIR_FUNC static __inline__
|
#define _TINYDIR_FUNC static __inline__
|
||||||
#elif defined(__cplusplus)
|
#elif defined(__cplusplus)
|
||||||
# define _TINYDIR_FUNC static inline
|
#define _TINYDIR_FUNC static inline
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
/* Suppress unused function warning */
|
/* Suppress unused function warning */
|
||||||
# define _TINYDIR_FUNC __attribute__((unused)) static
|
#define _TINYDIR_FUNC __attribute__((unused)) static
|
||||||
#else
|
#else
|
||||||
# define _TINYDIR_FUNC static
|
#define _TINYDIR_FUNC static
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
|
/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
|
||||||
@@ -139,52 +138,48 @@ extern "C" {
|
|||||||
|
|
||||||
/* readdir_r is a POSIX-only function, and may not be available under various
|
/* readdir_r is a POSIX-only function, and may not be available under various
|
||||||
* environments/settings, e.g. MinGW. Use readdir fallback */
|
* environments/settings, e.g. MinGW. Use readdir fallback */
|
||||||
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\
|
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
|
||||||
_POSIX_SOURCE
|
#define _TINYDIR_HAS_READDIR_R
|
||||||
# define _TINYDIR_HAS_READDIR_R
|
|
||||||
#endif
|
#endif
|
||||||
#if _POSIX_C_SOURCE >= 200112L
|
#if _POSIX_C_SOURCE >= 200112L
|
||||||
# define _TINYDIR_HAS_FPATHCONF
|
#define _TINYDIR_HAS_FPATHCONF
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#if _BSD_SOURCE || _SVID_SOURCE || \
|
#if _BSD_SOURCE || _SVID_SOURCE || (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
|
||||||
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
|
#define _TINYDIR_HAS_DIRFD
|
||||||
# define _TINYDIR_HAS_DIRFD
|
#include <sys/types.h>
|
||||||
# include <sys/types.h>
|
|
||||||
#endif
|
#endif
|
||||||
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\
|
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD && defined _PC_NAME_MAX
|
||||||
defined _PC_NAME_MAX
|
#define _TINYDIR_USE_FPATHCONF
|
||||||
# define _TINYDIR_USE_FPATHCONF
|
|
||||||
#endif
|
#endif
|
||||||
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\
|
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R || !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
|
||||||
!(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
|
#define _TINYDIR_USE_READDIR
|
||||||
# define _TINYDIR_USE_READDIR
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Use readdir by default */
|
/* Use readdir by default */
|
||||||
#else
|
#else
|
||||||
# define _TINYDIR_USE_READDIR
|
#define _TINYDIR_USE_READDIR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
|
/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#if (defined __MINGW32__) && (defined _UNICODE)
|
#if (defined __MINGW32__) && (defined _UNICODE)
|
||||||
#define _TINYDIR_DIR _WDIR
|
#define _TINYDIR_DIR _WDIR
|
||||||
#define _tinydir_dirent _wdirent
|
#define _tinydir_dirent _wdirent
|
||||||
#define _tinydir_opendir _wopendir
|
#define _tinydir_opendir _wopendir
|
||||||
#define _tinydir_readdir _wreaddir
|
#define _tinydir_readdir _wreaddir
|
||||||
#define _tinydir_closedir _wclosedir
|
#define _tinydir_closedir _wclosedir
|
||||||
#else
|
#else
|
||||||
#define _TINYDIR_DIR DIR
|
#define _TINYDIR_DIR DIR
|
||||||
#define _tinydir_dirent dirent
|
#define _tinydir_dirent dirent
|
||||||
#define _tinydir_opendir opendir
|
#define _tinydir_opendir opendir
|
||||||
#define _tinydir_readdir readdir
|
#define _tinydir_readdir readdir
|
||||||
#define _tinydir_closedir closedir
|
#define _tinydir_closedir closedir
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
|
/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
|
||||||
#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE)
|
#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE)
|
||||||
#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
|
#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
|
||||||
#else
|
#else
|
||||||
#error "Either define both alloc and free or none of them!"
|
#error "Either define both alloc and free or none of them!"
|
||||||
@@ -195,11 +190,10 @@ extern "C" {
|
|||||||
#define _TINYDIR_FREE(_ptr) free(_ptr)
|
#define _TINYDIR_FREE(_ptr) free(_ptr)
|
||||||
#endif /* !defined(_TINYDIR_MALLOC) */
|
#endif /* !defined(_TINYDIR_MALLOC) */
|
||||||
|
|
||||||
typedef struct tinydir_file
|
typedef struct tinydir_file {
|
||||||
{
|
|
||||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||||
_tinydir_char_t name[_TINYDIR_FILENAME_MAX];
|
_tinydir_char_t name[_TINYDIR_FILENAME_MAX];
|
||||||
_tinydir_char_t *extension;
|
_tinydir_char_t* extension;
|
||||||
int is_dir;
|
int is_dir;
|
||||||
int is_reg;
|
int is_reg;
|
||||||
|
|
||||||
@@ -212,80 +206,74 @@ typedef struct tinydir_file
|
|||||||
#endif
|
#endif
|
||||||
} tinydir_file;
|
} tinydir_file;
|
||||||
|
|
||||||
typedef struct tinydir_dir
|
typedef struct tinydir_dir {
|
||||||
{
|
|
||||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||||
int has_next;
|
int has_next;
|
||||||
size_t n_files;
|
size_t n_files;
|
||||||
|
|
||||||
tinydir_file *_files;
|
tinydir_file* _files;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
HANDLE _h;
|
HANDLE _h;
|
||||||
WIN32_FIND_DATA _f;
|
WIN32_FIND_DATA _f;
|
||||||
#else
|
#else
|
||||||
_TINYDIR_DIR *_d;
|
_TINYDIR_DIR* _d;
|
||||||
struct _tinydir_dirent *_e;
|
struct _tinydir_dirent* _e;
|
||||||
#ifndef _TINYDIR_USE_READDIR
|
#ifndef _TINYDIR_USE_READDIR
|
||||||
struct _tinydir_dirent *_ep;
|
struct _tinydir_dirent* _ep;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} tinydir_dir;
|
} tinydir_dir;
|
||||||
|
|
||||||
|
|
||||||
/* declarations */
|
/* declarations */
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
|
int tinydir_open(tinydir_dir* dir, const _tinydir_char_t* path);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
|
int tinydir_open_sorted(tinydir_dir* dir, const _tinydir_char_t* path);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
void tinydir_close(tinydir_dir *dir);
|
void tinydir_close(tinydir_dir* dir);
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_next(tinydir_dir *dir);
|
int tinydir_next(tinydir_dir* dir);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
|
int tinydir_readfile(const tinydir_dir* dir, tinydir_file* file);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
|
int tinydir_readfile_n(const tinydir_dir* dir, tinydir_file* file, size_t i);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
|
int tinydir_open_subdir_n(tinydir_dir* dir, size_t i);
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
|
int tinydir_file_open(tinydir_file* file, const _tinydir_char_t* path);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
void _tinydir_get_ext(tinydir_file *file);
|
void _tinydir_get_ext(tinydir_file* file);
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int _tinydir_file_cmp(const void *a, const void *b);
|
int _tinydir_file_cmp(const void* a, const void* b);
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#ifndef _TINYDIR_USE_READDIR
|
#ifndef _TINYDIR_USE_READDIR
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
|
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR* dirp);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* definitions*/
|
/* definitions*/
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
|
int tinydir_open(tinydir_dir* dir, const _tinydir_char_t* path) {
|
||||||
{
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#ifndef _TINYDIR_USE_READDIR
|
#ifndef _TINYDIR_USE_READDIR
|
||||||
int error;
|
int error;
|
||||||
int size; /* using int size */
|
int size; /* using int size */
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
_tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
|
_tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
|
||||||
#endif
|
#endif
|
||||||
_tinydir_char_t *pathp;
|
_tinydir_char_t* pathp;
|
||||||
|
|
||||||
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
|
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) {
|
||||||
{
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
|
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) {
|
||||||
{
|
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -305,26 +293,23 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
|
|||||||
_tinydir_strcpy(dir->path, path);
|
_tinydir_strcpy(dir->path, path);
|
||||||
/* Remove trailing slashes */
|
/* Remove trailing slashes */
|
||||||
pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
|
pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
|
||||||
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
|
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) {
|
||||||
{
|
|
||||||
*pathp = TINYDIR_STRING('\0');
|
*pathp = TINYDIR_STRING('\0');
|
||||||
pathp++;
|
pathp++;
|
||||||
}
|
}
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_tinydir_strcpy(path_buf, dir->path);
|
_tinydir_strcpy(path_buf, dir->path);
|
||||||
_tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
|
_tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
|
||||||
#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
|
#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
|
||||||
dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0);
|
dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0);
|
||||||
#else
|
#else
|
||||||
dir->_h = FindFirstFile(path_buf, &dir->_f);
|
dir->_h = FindFirstFile(path_buf, &dir->_f);
|
||||||
#endif
|
#endif
|
||||||
if (dir->_h == INVALID_HANDLE_VALUE)
|
if (dir->_h == INVALID_HANDLE_VALUE) {
|
||||||
{
|
errno = ENOENT;
|
||||||
errno = ENOENT;
|
|
||||||
#else
|
#else
|
||||||
dir->_d = _tinydir_opendir(path);
|
dir->_d = _tinydir_opendir(path);
|
||||||
if (dir->_d == NULL)
|
if (dir->_d == NULL) {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
@@ -336,77 +321,69 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
|
|||||||
dir->_e = _tinydir_readdir(dir->_d);
|
dir->_e = _tinydir_readdir(dir->_d);
|
||||||
#else
|
#else
|
||||||
/* allocate dirent buffer for readdir_r */
|
/* allocate dirent buffer for readdir_r */
|
||||||
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
|
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
|
||||||
if (size == -1) return -1;
|
if (size == -1)
|
||||||
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
|
return -1;
|
||||||
if (dir->_ep == NULL) return -1;
|
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
|
||||||
|
if (dir->_ep == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
error = readdir_r(dir->_d, dir->_ep, &dir->_e);
|
error = readdir_r(dir->_d, dir->_ep, &dir->_e);
|
||||||
if (error != 0) return -1;
|
if (error != 0)
|
||||||
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
if (dir->_e == NULL)
|
if (dir->_e == NULL) {
|
||||||
{
|
|
||||||
dir->has_next = 0;
|
dir->has_next = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
|
int tinydir_open_sorted(tinydir_dir* dir, const _tinydir_char_t* path) {
|
||||||
{
|
|
||||||
/* Count the number of files first, to pre-allocate the files array */
|
/* Count the number of files first, to pre-allocate the files array */
|
||||||
size_t n_files = 0;
|
size_t n_files = 0;
|
||||||
if (tinydir_open(dir, path) == -1)
|
if (tinydir_open(dir, path) == -1) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while (dir->has_next)
|
while (dir->has_next) {
|
||||||
{
|
|
||||||
n_files++;
|
n_files++;
|
||||||
if (tinydir_next(dir) == -1)
|
if (tinydir_next(dir) == -1) {
|
||||||
{
|
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
|
|
||||||
if (n_files == 0 || tinydir_open(dir, path) == -1)
|
if (n_files == 0 || tinydir_open(dir, path) == -1) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir->n_files = 0;
|
dir->n_files = 0;
|
||||||
dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
|
dir->_files = (tinydir_file*)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
|
||||||
if (dir->_files == NULL)
|
if (dir->_files == NULL) {
|
||||||
{
|
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
while (dir->has_next)
|
while (dir->has_next) {
|
||||||
{
|
tinydir_file* p_file;
|
||||||
tinydir_file *p_file;
|
|
||||||
dir->n_files++;
|
dir->n_files++;
|
||||||
|
|
||||||
p_file = &dir->_files[dir->n_files - 1];
|
p_file = &dir->_files[dir->n_files - 1];
|
||||||
if (tinydir_readfile(dir, p_file) == -1)
|
if (tinydir_readfile(dir, p_file) == -1) {
|
||||||
{
|
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tinydir_next(dir) == -1)
|
if (tinydir_next(dir) == -1) {
|
||||||
{
|
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just in case the number of files has changed between the first and
|
/* Just in case the number of files has changed between the first and
|
||||||
second reads, terminate without writing into unallocated memory */
|
second reads, terminate without writing into unallocated memory */
|
||||||
if (dir->n_files == n_files)
|
if (dir->n_files == n_files) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,16 +392,14 @@ int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
void tinydir_close(tinydir_dir *dir)
|
void tinydir_close(tinydir_dir* dir) {
|
||||||
{
|
if (dir == NULL) {
|
||||||
if (dir == NULL)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,35 +409,30 @@ void tinydir_close(tinydir_dir *dir)
|
|||||||
_TINYDIR_FREE(dir->_files);
|
_TINYDIR_FREE(dir->_files);
|
||||||
dir->_files = NULL;
|
dir->_files = NULL;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if (dir->_h != INVALID_HANDLE_VALUE)
|
if (dir->_h != INVALID_HANDLE_VALUE) {
|
||||||
{
|
FindClose(dir->_h);
|
||||||
FindClose(dir->_h);
|
}
|
||||||
}
|
dir->_h = INVALID_HANDLE_VALUE;
|
||||||
dir->_h = INVALID_HANDLE_VALUE;
|
|
||||||
#else
|
#else
|
||||||
if (dir->_d)
|
if (dir->_d) {
|
||||||
{
|
|
||||||
_tinydir_closedir(dir->_d);
|
_tinydir_closedir(dir->_d);
|
||||||
}
|
}
|
||||||
dir->_d = NULL;
|
dir->_d = NULL;
|
||||||
dir->_e = NULL;
|
dir->_e = NULL;
|
||||||
#ifndef _TINYDIR_USE_READDIR
|
#ifndef _TINYDIR_USE_READDIR
|
||||||
_TINYDIR_FREE(dir->_ep);
|
_TINYDIR_FREE(dir->_ep);
|
||||||
dir->_ep = NULL;
|
dir->_ep = NULL;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_next(tinydir_dir *dir)
|
int tinydir_next(tinydir_dir* dir) {
|
||||||
{
|
if (dir == NULL) {
|
||||||
if (dir == NULL)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!dir->has_next)
|
if (!dir->has_next) {
|
||||||
{
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -473,27 +443,23 @@ int tinydir_next(tinydir_dir *dir)
|
|||||||
#ifdef _TINYDIR_USE_READDIR
|
#ifdef _TINYDIR_USE_READDIR
|
||||||
dir->_e = _tinydir_readdir(dir->_d);
|
dir->_e = _tinydir_readdir(dir->_d);
|
||||||
#else
|
#else
|
||||||
if (dir->_ep == NULL)
|
if (dir->_ep == NULL) {
|
||||||
{
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) {
|
||||||
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
|
return -1;
|
||||||
{
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (dir->_e == NULL)
|
if (dir->_e == NULL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
dir->has_next = 0;
|
dir->has_next = 0;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if (GetLastError() != ERROR_SUCCESS &&
|
if (GetLastError() != ERROR_SUCCESS && GetLastError() != ERROR_NO_MORE_FILES) {
|
||||||
GetLastError() != ERROR_NO_MORE_FILES)
|
tinydir_close(dir);
|
||||||
{
|
errno = EIO;
|
||||||
tinydir_close(dir);
|
return -1;
|
||||||
errno = EIO;
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,11 +467,9 @@ int tinydir_next(tinydir_dir *dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
int tinydir_readfile(const tinydir_dir* dir, tinydir_file* file) {
|
||||||
{
|
const _tinydir_char_t* filename;
|
||||||
const _tinydir_char_t *filename;
|
if (dir == NULL || file == NULL) {
|
||||||
if (dir == NULL || file == NULL)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -520,20 +484,16 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
|||||||
}
|
}
|
||||||
filename =
|
filename =
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
dir->_f.cFileName;
|
dir->_f.cFileName;
|
||||||
#else
|
#else
|
||||||
dir->_e->d_name;
|
dir->_e->d_name;
|
||||||
#endif
|
#endif
|
||||||
if (_tinydir_strlen(dir->path) +
|
if (_tinydir_strlen(dir->path) + _tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) {
|
||||||
_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
|
|
||||||
_TINYDIR_PATH_MAX)
|
|
||||||
{
|
|
||||||
/* the path for the file will be too long */
|
/* the path for the file will be too long */
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX)
|
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX) {
|
||||||
{
|
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -546,17 +506,15 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
|||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
if (_tstat(
|
if (_tstat(
|
||||||
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) \
|
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|
||||||
|| ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) || ((defined __APPLE__) && (defined __MACH__)) \
|
||||||
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|
|| (defined BSD)
|
||||||
|| ((defined __APPLE__) && (defined __MACH__)) \
|
if (lstat(
|
||||||
|| (defined BSD)
|
|
||||||
if (lstat(
|
|
||||||
#else
|
#else
|
||||||
if (stat(
|
if (stat(
|
||||||
#endif
|
#endif
|
||||||
file->path, &file->_s) == -1)
|
file->path, &file->_s)
|
||||||
{
|
== -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -564,42 +522,38 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
|||||||
|
|
||||||
file->is_dir =
|
file->is_dir =
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
#else
|
#else
|
||||||
S_ISDIR(file->_s.st_mode);
|
S_ISDIR(file->_s.st_mode);
|
||||||
#endif
|
#endif
|
||||||
file->is_reg =
|
file->is_reg =
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
|
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
|
||||||
(
|
|| (!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
|
&& !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
&& !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
|
|
||||||
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
|
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
|
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
|
||||||
#endif
|
#endif
|
||||||
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
|
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
|
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
|
||||||
#endif
|
#endif
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
|
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE)
|
||||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
|
&& !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
|
||||||
#else
|
#else
|
||||||
S_ISREG(file->_s.st_mode);
|
S_ISREG(file->_s.st_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
|
int tinydir_readfile_n(const tinydir_dir* dir, tinydir_file* file, size_t i) {
|
||||||
{
|
if (dir == NULL || file == NULL) {
|
||||||
if (dir == NULL || file == NULL)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (i >= dir->n_files)
|
if (i >= dir->n_files) {
|
||||||
{
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -611,24 +565,20 @@ int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
|
int tinydir_open_subdir_n(tinydir_dir* dir, size_t i) {
|
||||||
{
|
|
||||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||||
if (dir == NULL)
|
if (dir == NULL) {
|
||||||
{
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (i >= dir->n_files || !dir->_files[i].is_dir)
|
if (i >= dir->n_files || !dir->_files[i].is_dir) {
|
||||||
{
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_tinydir_strcpy(path, dir->_files[i].path);
|
_tinydir_strcpy(path, dir->_files[i].path);
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
if (tinydir_open_sorted(dir, path) == -1)
|
if (tinydir_open_sorted(dir, path) == -1) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,66 +587,52 @@ int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
|
|||||||
|
|
||||||
/* Open a single file given its path */
|
/* Open a single file given its path */
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
|
int tinydir_file_open(tinydir_file* file, const _tinydir_char_t* path) {
|
||||||
{
|
|
||||||
tinydir_dir dir;
|
tinydir_dir dir;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
|
_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
|
||||||
_tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
|
_tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
|
||||||
_tinydir_char_t *dir_name;
|
_tinydir_char_t* dir_name;
|
||||||
_tinydir_char_t *base_name;
|
_tinydir_char_t* base_name;
|
||||||
#if (defined _MSC_VER || defined __MINGW32__)
|
#if (defined _MSC_VER || defined __MINGW32__)
|
||||||
_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
|
_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
|
||||||
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
|
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
|
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) {
|
||||||
{
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
|
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) {
|
||||||
{
|
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the parent path */
|
/* Get the parent path */
|
||||||
#if (defined _MSC_VER || defined __MINGW32__)
|
#if (defined _MSC_VER || defined __MINGW32__)
|
||||||
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
|
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
|
||||||
errno = _tsplitpath_s(
|
errno = _tsplitpath_s(path, drive_buf, _TINYDIR_DRIVE_MAX, dir_name_buf, _TINYDIR_FILENAME_MAX, file_name_buf,
|
||||||
path,
|
_TINYDIR_FILENAME_MAX, ext_buf, _TINYDIR_FILENAME_MAX);
|
||||||
drive_buf, _TINYDIR_DRIVE_MAX,
|
|
||||||
dir_name_buf, _TINYDIR_FILENAME_MAX,
|
|
||||||
file_name_buf, _TINYDIR_FILENAME_MAX,
|
|
||||||
ext_buf, _TINYDIR_FILENAME_MAX);
|
|
||||||
#else
|
#else
|
||||||
_tsplitpath(
|
_tsplitpath(path, drive_buf, dir_name_buf, file_name_buf, ext_buf);
|
||||||
path,
|
|
||||||
drive_buf,
|
|
||||||
dir_name_buf,
|
|
||||||
file_name_buf,
|
|
||||||
ext_buf);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (errno)
|
if (errno) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _splitpath_s not work fine with only filename and widechar support */
|
/* _splitpath_s not work fine with only filename and widechar support */
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
if (drive_buf[0] == L'\xFEFE')
|
if (drive_buf[0] == L'\xFEFE')
|
||||||
drive_buf[0] = '\0';
|
drive_buf[0] = '\0';
|
||||||
if (dir_name_buf[0] == L'\xFEFE')
|
if (dir_name_buf[0] == L'\xFEFE')
|
||||||
dir_name_buf[0] = '\0';
|
dir_name_buf[0] = '\0';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Emulate the behavior of dirname by returning "." for dir name if it's
|
/* Emulate the behavior of dirname by returning "." for dir name if it's
|
||||||
empty */
|
empty */
|
||||||
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
|
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') {
|
||||||
{
|
|
||||||
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
|
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
|
||||||
}
|
}
|
||||||
/* Concatenate the drive letter and dir name to form full dir name */
|
/* Concatenate the drive letter and dir name to form full dir name */
|
||||||
@@ -707,19 +643,19 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
|
|||||||
base_name = file_name_buf;
|
base_name = file_name_buf;
|
||||||
#else
|
#else
|
||||||
_tinydir_strcpy(dir_name_buf, path);
|
_tinydir_strcpy(dir_name_buf, path);
|
||||||
dir_name = dirname(dir_name_buf);
|
dir_name = dirname(dir_name_buf);
|
||||||
_tinydir_strcpy(file_name_buf, path);
|
_tinydir_strcpy(file_name_buf, path);
|
||||||
base_name = basename(file_name_buf);
|
base_name = basename(file_name_buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Special case: if the path is a root dir, open the parent dir as the file */
|
/* Special case: if the path is a root dir, open the parent dir as the file */
|
||||||
#if (defined _MSC_VER || defined __MINGW32__)
|
#if (defined _MSC_VER || defined __MINGW32__)
|
||||||
if (_tinydir_strlen(base_name) == 0)
|
if (_tinydir_strlen(base_name) == 0)
|
||||||
#else
|
#else
|
||||||
if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
|
if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
memset(file, 0, sizeof * file);
|
memset(file, 0, sizeof *file);
|
||||||
file->is_dir = 1;
|
file->is_dir = 1;
|
||||||
file->is_reg = 0;
|
file->is_reg = 0;
|
||||||
_tinydir_strcpy(file->path, dir_name);
|
_tinydir_strcpy(file->path, dir_name);
|
||||||
@@ -728,59 +664,48 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Open the parent directory */
|
/* Open the parent directory */
|
||||||
if (tinydir_open(&dir, dir_name) == -1)
|
if (tinydir_open(&dir, dir_name) == -1) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read through the parent directory and look for the file */
|
/* Read through the parent directory and look for the file */
|
||||||
while (dir.has_next)
|
while (dir.has_next) {
|
||||||
{
|
if (tinydir_readfile(&dir, file) == -1) {
|
||||||
if (tinydir_readfile(&dir, file) == -1)
|
|
||||||
{
|
|
||||||
result = -1;
|
result = -1;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (_tinydir_strcmp(file->name, base_name) == 0)
|
if (_tinydir_strcmp(file->name, base_name) == 0) {
|
||||||
{
|
|
||||||
/* File found */
|
/* File found */
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tinydir_next(&dir);
|
tinydir_next(&dir);
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found) {
|
||||||
{
|
|
||||||
result = -1;
|
result = -1;
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
tinydir_close(&dir);
|
tinydir_close(&dir);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
void _tinydir_get_ext(tinydir_file *file)
|
void _tinydir_get_ext(tinydir_file* file) {
|
||||||
{
|
_tinydir_char_t* period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
|
||||||
_tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
|
if (period == NULL) {
|
||||||
if (period == NULL)
|
|
||||||
{
|
|
||||||
file->extension = &(file->name[_tinydir_strlen(file->name)]);
|
file->extension = &(file->name[_tinydir_strlen(file->name)]);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
file->extension = period + 1;
|
file->extension = period + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
int _tinydir_file_cmp(const void *a, const void *b)
|
int _tinydir_file_cmp(const void* a, const void* b) {
|
||||||
{
|
const tinydir_file* fa = (const tinydir_file*)a;
|
||||||
const tinydir_file *fa = (const tinydir_file *)a;
|
const tinydir_file* fb = (const tinydir_file*)b;
|
||||||
const tinydir_file *fb = (const tinydir_file *)b;
|
if (fa->is_dir != fb->is_dir) {
|
||||||
if (fa->is_dir != fb->is_dir)
|
|
||||||
{
|
|
||||||
return -(fa->is_dir - fb->is_dir);
|
return -(fa->is_dir - fb->is_dir);
|
||||||
}
|
}
|
||||||
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
|
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
|
||||||
@@ -793,36 +718,34 @@ The following authored by Ben Hutchings <ben@decadent.org.uk>
|
|||||||
from https://womble.decadent.org.uk/readdir_r-advisory.html
|
from https://womble.decadent.org.uk/readdir_r-advisory.html
|
||||||
*/
|
*/
|
||||||
/* Calculate the required buffer size (in bytes) for directory *
|
/* Calculate the required buffer size (in bytes) for directory *
|
||||||
* entries read from the given directory handle. Return -1 if this *
|
* entries read from the given directory handle. Return -1 if this *
|
||||||
* this cannot be done. *
|
* this cannot be done. *
|
||||||
* *
|
* *
|
||||||
* This code does not trust values of NAME_MAX that are less than *
|
* This code does not trust values of NAME_MAX that are less than *
|
||||||
* 255, since some systems (including at least HP-UX) incorrectly *
|
* 255, since some systems (including at least HP-UX) incorrectly *
|
||||||
* define it to be a smaller value. */
|
* define it to be a smaller value. */
|
||||||
_TINYDIR_FUNC
|
_TINYDIR_FUNC
|
||||||
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
|
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR* dirp) {
|
||||||
{
|
long name_max;
|
||||||
long name_max;
|
size_t name_end;
|
||||||
size_t name_end;
|
/* parameter may be unused */
|
||||||
/* parameter may be unused */
|
(void)dirp;
|
||||||
(void)dirp;
|
|
||||||
|
|
||||||
#if defined _TINYDIR_USE_FPATHCONF
|
#if defined _TINYDIR_USE_FPATHCONF
|
||||||
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
|
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
|
||||||
if (name_max == -1)
|
if (name_max == -1)
|
||||||
#if defined(NAME_MAX)
|
#if defined(NAME_MAX)
|
||||||
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
||||||
#else
|
#else
|
||||||
return (size_t)(-1);
|
return (size_t)(-1);
|
||||||
#endif
|
#endif
|
||||||
#elif defined(NAME_MAX)
|
#elif defined(NAME_MAX)
|
||||||
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
||||||
#else
|
#else
|
||||||
#error "buffer size for readdir_r cannot be determined"
|
#error "buffer size for readdir_r cannot be determined"
|
||||||
#endif
|
#endif
|
||||||
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
|
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
|
||||||
return (name_end > sizeof(struct _tinydir_dirent) ?
|
return (name_end > sizeof(struct _tinydir_dirent) ? name_end : sizeof(struct _tinydir_dirent));
|
||||||
name_end : sizeof(struct _tinydir_dirent));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -831,8 +754,8 @@ size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# if defined (_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# pragma warning(pop)
|
#pragma warning(pop)
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -20,22 +20,24 @@
|
|||||||
#include "lcd_api.h"
|
#include "lcd_api.h"
|
||||||
|
|
||||||
// Defines used by UDP callback
|
// Defines used by UDP callback
|
||||||
#define UDP_BROADCAST_MAX_DATA_SIZE ((UDP_BROADCAST_MAX_NAME_SIZE * 2) - 2 + 25) // Define the maximum expected data size
|
#define UDP_BROADCAST_MAX_DATA_SIZE \
|
||||||
#define UDP_BROADCAST_UDP_QUESTION1 "Where are you?v1.0" // Expected question from UDP client
|
((UDP_BROADCAST_MAX_NAME_SIZE * 2) - 2 + 25) // Define the maximum expected data size
|
||||||
#define UDP_BROADCAST_MAX_FUNC_LEN 7
|
#define UDP_BROADCAST_UDP_QUESTION1 "Where are you?v1.0" // Expected question from UDP client
|
||||||
|
#define UDP_BROADCAST_MAX_FUNC_LEN 7
|
||||||
#define UDP_BROADCAST_MAX_COLON_COMMA_COUNT 4
|
#define UDP_BROADCAST_MAX_COLON_COMMA_COUNT 4
|
||||||
|
|
||||||
// Defines used by owner details
|
// Defines used by owner details
|
||||||
#define UDP_BROADCAST_MAX_REPLY_SIZE (UDP_BROADCAST_MAX_MAC_ADDR_LEN + sizeof(UDP_BROADCAST_REPLY_MIDDLE_TEXT) + (UDP_BROADCAST_MAX_NAME_SIZE * 2) + UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA)
|
#define UDP_BROADCAST_MAX_REPLY_SIZE \
|
||||||
|
(UDP_BROADCAST_MAX_MAC_ADDR_LEN + sizeof(UDP_BROADCAST_REPLY_MIDDLE_TEXT) + (UDP_BROADCAST_MAX_NAME_SIZE * 2) \
|
||||||
|
+ UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA)
|
||||||
#define UDP_BROADCAST_REPLY_MIDDLE_TEXT "is present and my owner is"
|
#define UDP_BROADCAST_REPLY_MIDDLE_TEXT "is present and my owner is"
|
||||||
|
|
||||||
#define UDP_BROADCAST_MAX_MAC_ADDR_LEN 19 // Format is: "xx:xx:xx:xx:xx:xx"
|
#define UDP_BROADCAST_MAX_MAC_ADDR_LEN 19 // Format is: "xx:xx:xx:xx:xx:xx"
|
||||||
#define UDP_BROADCAST_MAX_NAME_SIZE 21 // Code automatically leaves 1 char for '\0' (actual length = length - 1)
|
#define UDP_BROADCAST_MAX_NAME_SIZE 21 // Code automatically leaves 1 char for '\0' (actual length = length - 1)
|
||||||
#define UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA 20 // Just a bit extra
|
#define UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA 20 // Just a bit extra
|
||||||
|
|
||||||
#define UDP_BROADCAST_LCD_NAME_PRE_TEXT "New owner: "
|
#define UDP_BROADCAST_LCD_NAME_PRE_TEXT "New owner: "
|
||||||
#define UDP_BROADCAST_LCD_TEXT_SIZE (strlen(UDP_BROADCAST_LCD_NAME_PRE_TEXT) + UDP_BROADCAST_MAX_NAME_SIZE)
|
#define UDP_BROADCAST_LCD_TEXT_SIZE (strlen(UDP_BROADCAST_LCD_NAME_PRE_TEXT) + UDP_BROADCAST_MAX_NAME_SIZE)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct owner_details_t
|
* @struct owner_details_t
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
#ifndef __ANIMATEDGIF__
|
#ifndef __ANIMATEDGIF__
|
||||||
#define __ANIMATEDGIF__
|
#define __ANIMATEDGIF__
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#define memcpy_P memcpy
|
#define memcpy_P memcpy
|
||||||
#define PROGMEM
|
#define PROGMEM
|
||||||
|
|
||||||
@@ -39,9 +39,9 @@
|
|||||||
// with 256 entries
|
// with 256 entries
|
||||||
//
|
//
|
||||||
#define MAX_CODE_SIZE 12
|
#define MAX_CODE_SIZE 12
|
||||||
#define MAX_COLORS 256
|
#define MAX_COLORS 256
|
||||||
#define LZW_BUF_SIZE (6*MAX_CHUNK_SIZE)
|
#define LZW_BUF_SIZE (6 * MAX_CHUNK_SIZE)
|
||||||
#define LZW_HIGHWATER (4*MAX_CHUNK_SIZE)
|
#define LZW_HIGHWATER (4 * MAX_CHUNK_SIZE)
|
||||||
#ifdef __LINUX__
|
#ifdef __LINUX__
|
||||||
#define MAX_WIDTH 2048
|
#define MAX_WIDTH 2048
|
||||||
#else
|
#else
|
||||||
@@ -50,13 +50,13 @@
|
|||||||
// This buffer is used to store the pixel sequence in reverse order
|
// This buffer is used to store the pixel sequence in reverse order
|
||||||
// it needs to be large enough to hold the longest possible
|
// it needs to be large enough to hold the longest possible
|
||||||
// sequence (1<<MAX_CODE_SIZE)
|
// sequence (1<<MAX_CODE_SIZE)
|
||||||
#define FILE_BUF_SIZE (1<<MAX_CODE_SIZE)
|
#define FILE_BUF_SIZE (1 << MAX_CODE_SIZE)
|
||||||
|
|
||||||
#define PIXEL_FIRST 0
|
#define PIXEL_FIRST 0
|
||||||
#define PIXEL_LAST (1<<MAX_CODE_SIZE)
|
#define PIXEL_LAST (1 << MAX_CODE_SIZE)
|
||||||
#define LINK_UNUSED 5911 // 0x1717 to use memset
|
#define LINK_UNUSED 5911 // 0x1717 to use memset
|
||||||
#define LINK_END 5912
|
#define LINK_END 5912
|
||||||
#define MAX_HASH 5003
|
#define MAX_HASH 5003
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GIF_PALETTE_RGB565_LE = 0, // little endian (default)
|
GIF_PALETTE_RGB565_LE = 0, // little endian (default)
|
||||||
@@ -65,16 +65,13 @@ enum {
|
|||||||
};
|
};
|
||||||
// for compatibility with older code
|
// for compatibility with older code
|
||||||
#define LITTLE_ENDIAN_PIXELS GIF_PALETTE_RGB565_LE
|
#define LITTLE_ENDIAN_PIXELS GIF_PALETTE_RGB565_LE
|
||||||
#define BIG_ENDIAN_PIXELS GIF_PALETTE_RGB565_BE
|
#define BIG_ENDIAN_PIXELS GIF_PALETTE_RGB565_BE
|
||||||
//
|
//
|
||||||
// Draw callback pixel type
|
// Draw callback pixel type
|
||||||
// RAW = 8-bit palettized pixels requiring transparent pixel handling
|
// RAW = 8-bit palettized pixels requiring transparent pixel handling
|
||||||
// COOKED = 16 or 24-bpp fully rendered pixels ready for display
|
// COOKED = 16 or 24-bpp fully rendered pixels ready for display
|
||||||
//
|
//
|
||||||
enum {
|
enum { GIF_DRAW_RAW = 0, GIF_DRAW_COOKED };
|
||||||
GIF_DRAW_RAW = 0,
|
|
||||||
GIF_DRAW_COOKED
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GIF_SUCCESS = 0,
|
GIF_SUCCESS = 0,
|
||||||
@@ -89,134 +86,136 @@ enum {
|
|||||||
GIF_ERROR_MEMORY
|
GIF_ERROR_MEMORY
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct gif_file_tag
|
typedef struct gif_file_tag {
|
||||||
{
|
int32_t iPos; // current file position
|
||||||
int32_t iPos; // current file position
|
int32_t iSize; // file size
|
||||||
int32_t iSize; // file size
|
uint8_t* pData; // memory file pointer
|
||||||
uint8_t *pData; // memory file pointer
|
void* fHandle; // class pointer to File/SdFat or whatever you want
|
||||||
void * fHandle; // class pointer to File/SdFat or whatever you want
|
|
||||||
} GIFFILE;
|
} GIFFILE;
|
||||||
|
|
||||||
typedef struct gif_info_tag
|
typedef struct gif_info_tag {
|
||||||
{
|
|
||||||
int32_t iFrameCount; // total frames in file
|
int32_t iFrameCount; // total frames in file
|
||||||
int32_t iDuration; // duration of animation in milliseconds
|
int32_t iDuration; // duration of animation in milliseconds
|
||||||
int32_t iMaxDelay; // maximum frame delay
|
int32_t iMaxDelay; // maximum frame delay
|
||||||
int32_t iMinDelay; // minimum frame delay
|
int32_t iMinDelay; // minimum frame delay
|
||||||
} GIFINFO;
|
} GIFINFO;
|
||||||
|
|
||||||
typedef struct gif_draw_tag
|
typedef struct gif_draw_tag {
|
||||||
{
|
int iX, iY; // Corner offset of this frame on the canvas
|
||||||
int iX, iY; // Corner offset of this frame on the canvas
|
int y; // current line being drawn (0 = top line of image)
|
||||||
int y; // current line being drawn (0 = top line of image)
|
int iWidth, iHeight; // size of this frame
|
||||||
int iWidth, iHeight; // size of this frame
|
void* pUser; // user supplied pointer
|
||||||
void *pUser; // user supplied pointer
|
uint8_t* pPixels; // 8-bit source pixels for this line
|
||||||
uint8_t *pPixels; // 8-bit source pixels for this line
|
uint16_t* pPalette; // little or big-endian RGB565 palette entries (default)
|
||||||
uint16_t *pPalette; // little or big-endian RGB565 palette entries (default)
|
uint8_t* pPalette24; // RGB888 palette (optional)
|
||||||
uint8_t *pPalette24; // RGB888 palette (optional)
|
uint8_t ucTransparent; // transparent color
|
||||||
uint8_t ucTransparent; // transparent color
|
|
||||||
uint8_t ucHasTransparency; // flag indicating the transparent color is in use
|
uint8_t ucHasTransparency; // flag indicating the transparent color is in use
|
||||||
uint8_t ucDisposalMethod; // frame disposal method
|
uint8_t ucDisposalMethod; // frame disposal method
|
||||||
uint8_t ucBackground; // background color
|
uint8_t ucBackground; // background color
|
||||||
uint8_t ucIsGlobalPalette; // Flag to indicate that a global palette, rather than a local palette is being used
|
uint8_t ucIsGlobalPalette; // Flag to indicate that a global palette, rather than a local palette is being used
|
||||||
} GIFDRAW;
|
} GIFDRAW;
|
||||||
|
|
||||||
// Callback function prototypes
|
// Callback function prototypes
|
||||||
typedef int32_t (GIF_READ_CALLBACK)(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen);
|
typedef int32_t(GIF_READ_CALLBACK)(GIFFILE* pFile, uint8_t* pBuf, int32_t iLen);
|
||||||
typedef int32_t (GIF_SEEK_CALLBACK)(GIFFILE *pFile, int32_t iPosition);
|
typedef int32_t(GIF_SEEK_CALLBACK)(GIFFILE* pFile, int32_t iPosition);
|
||||||
typedef void (GIF_DRAW_CALLBACK)(GIFDRAW *pDraw);
|
typedef void(GIF_DRAW_CALLBACK)(GIFDRAW* pDraw);
|
||||||
typedef void * (GIF_OPEN_CALLBACK)(const char *szFilename, int32_t *pFileSize);
|
typedef void*(GIF_OPEN_CALLBACK)(const char* szFilename, int32_t* pFileSize);
|
||||||
typedef void (GIF_CLOSE_CALLBACK)(void *pHandle);
|
typedef void(GIF_CLOSE_CALLBACK)(void* pHandle);
|
||||||
typedef void * (GIF_ALLOC_CALLBACK)(uint32_t iSize);
|
typedef void*(GIF_ALLOC_CALLBACK)(uint32_t iSize);
|
||||||
typedef void (GIF_FREE_CALLBACK)(void *buffer);
|
typedef void(GIF_FREE_CALLBACK)(void* buffer);
|
||||||
//
|
//
|
||||||
// our private structure to hold a GIF image decode state
|
// our private structure to hold a GIF image decode state
|
||||||
//
|
//
|
||||||
typedef struct gif_image_tag
|
typedef struct gif_image_tag {
|
||||||
{
|
|
||||||
int iWidth, iHeight, iCanvasWidth, iCanvasHeight;
|
int iWidth, iHeight, iCanvasWidth, iCanvasHeight;
|
||||||
int iX, iY; // GIF corner offset
|
int iX, iY; // GIF corner offset
|
||||||
int iBpp;
|
int iBpp;
|
||||||
int iError; // last error
|
int iError; // last error
|
||||||
int iFrameDelay; // delay in milliseconds for this frame
|
int iFrameDelay; // delay in milliseconds for this frame
|
||||||
int iRepeatCount; // NETSCAPE animation repeat count. 0=forever
|
int iRepeatCount; // NETSCAPE animation repeat count. 0=forever
|
||||||
int iXCount, iYCount; // decoding position in image (countdown values)
|
int iXCount, iYCount; // decoding position in image (countdown values)
|
||||||
int iLZWOff; // current LZW data offset
|
int iLZWOff; // current LZW data offset
|
||||||
int iLZWSize; // current quantity of data in the LZW buffer
|
int iLZWSize; // current quantity of data in the LZW buffer
|
||||||
int iCommentPos; // file offset of start of comment data
|
int iCommentPos; // file offset of start of comment data
|
||||||
short sCommentLen; // length of comment
|
short sCommentLen; // length of comment
|
||||||
GIF_READ_CALLBACK *pfnRead;
|
GIF_READ_CALLBACK* pfnRead;
|
||||||
GIF_SEEK_CALLBACK *pfnSeek;
|
GIF_SEEK_CALLBACK* pfnSeek;
|
||||||
GIF_DRAW_CALLBACK *pfnDraw;
|
GIF_DRAW_CALLBACK* pfnDraw;
|
||||||
GIF_OPEN_CALLBACK *pfnOpen;
|
GIF_OPEN_CALLBACK* pfnOpen;
|
||||||
GIF_CLOSE_CALLBACK *pfnClose;
|
GIF_CLOSE_CALLBACK* pfnClose;
|
||||||
GIFFILE GIFFile;
|
GIFFILE GIFFile;
|
||||||
void *pUser;
|
void* pUser;
|
||||||
unsigned char *pFrameBuffer;
|
unsigned char* pFrameBuffer;
|
||||||
unsigned char *pPixels, *pOldPixels;
|
unsigned char *pPixels, *pOldPixels;
|
||||||
unsigned char ucLineBuf[MAX_WIDTH]; // current line
|
unsigned char ucLineBuf[MAX_WIDTH]; // current line
|
||||||
unsigned char ucFileBuf[FILE_BUF_SIZE]; // holds temp data and pixel stack
|
unsigned char ucFileBuf[FILE_BUF_SIZE]; // holds temp data and pixel stack
|
||||||
unsigned short pPalette[(MAX_COLORS * 3)/2]; // can hold RGB565 or RGB888 - set in begin()
|
unsigned short pPalette[(MAX_COLORS * 3) / 2]; // can hold RGB565 or RGB888 - set in begin()
|
||||||
unsigned short pLocalPalette[(MAX_COLORS * 3)/2]; // color palettes for GIF images
|
unsigned short pLocalPalette[(MAX_COLORS * 3) / 2]; // color palettes for GIF images
|
||||||
unsigned char ucLZW[LZW_BUF_SIZE]; // holds 6 chunks (6x255) of GIF LZW data packed together
|
unsigned char ucLZW[LZW_BUF_SIZE]; // holds 6 chunks (6x255) of GIF LZW data packed together
|
||||||
unsigned short usGIFTable[1<<MAX_CODE_SIZE];
|
unsigned short usGIFTable[1 << MAX_CODE_SIZE];
|
||||||
unsigned char ucGIFPixels[(PIXEL_LAST*2)];
|
unsigned char ucGIFPixels[(PIXEL_LAST * 2)];
|
||||||
unsigned char bEndOfFrame;
|
unsigned char bEndOfFrame;
|
||||||
unsigned char ucGIFBits, ucBackground, ucTransparent, ucCodeStart, ucMap, bUseLocalPalette;
|
unsigned char ucGIFBits, ucBackground, ucTransparent, ucCodeStart, ucMap, bUseLocalPalette;
|
||||||
unsigned char ucPaletteType; // RGB565 or RGB888
|
unsigned char ucPaletteType; // RGB565 or RGB888
|
||||||
unsigned char ucDrawType; // RAW or COOKED
|
unsigned char ucDrawType; // RAW or COOKED
|
||||||
} GIFIMAGE;
|
} GIFIMAGE;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
//
|
//
|
||||||
// The GIF class wraps portable C code which does the actual work
|
// The GIF class wraps portable C code which does the actual work
|
||||||
//
|
//
|
||||||
class AnimatedGIF
|
class AnimatedGIF {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
int open(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw);
|
int open(uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw);
|
||||||
int openFLASH(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw);
|
int openFLASH(uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw);
|
||||||
int open(const char *szFilename, GIF_OPEN_CALLBACK *pfnOpen, GIF_CLOSE_CALLBACK *pfnClose, GIF_READ_CALLBACK *pfnRead, GIF_SEEK_CALLBACK *pfnSeek, GIF_DRAW_CALLBACK *pfnDraw);
|
int open(const char* szFilename,
|
||||||
|
GIF_OPEN_CALLBACK* pfnOpen,
|
||||||
|
GIF_CLOSE_CALLBACK* pfnClose,
|
||||||
|
GIF_READ_CALLBACK* pfnRead,
|
||||||
|
GIF_SEEK_CALLBACK* pfnSeek,
|
||||||
|
GIF_DRAW_CALLBACK* pfnDraw);
|
||||||
void close();
|
void close();
|
||||||
void reset();
|
void reset();
|
||||||
void begin(unsigned char ucPaletteType = GIF_PALETTE_RGB565_LE);
|
void begin(unsigned char ucPaletteType = GIF_PALETTE_RGB565_LE);
|
||||||
void begin(int iEndian, unsigned char ucPaletteType) { begin(ucPaletteType); };
|
void begin(int iEndian, unsigned char ucPaletteType) {
|
||||||
int playFrame(bool bSync, int *delayMilliseconds, void *pUser = NULL);
|
begin(ucPaletteType);
|
||||||
|
};
|
||||||
|
int playFrame(bool bSync, int* delayMilliseconds, void* pUser = NULL);
|
||||||
int getCanvasWidth();
|
int getCanvasWidth();
|
||||||
int allocFrameBuf(GIF_ALLOC_CALLBACK *pfnAlloc);
|
int allocFrameBuf(GIF_ALLOC_CALLBACK* pfnAlloc);
|
||||||
int setDrawType(int iType);
|
int setDrawType(int iType);
|
||||||
int freeFrameBuf(GIF_FREE_CALLBACK *pfnFree);
|
int freeFrameBuf(GIF_FREE_CALLBACK* pfnFree);
|
||||||
uint8_t *getFrameBuf();
|
uint8_t* getFrameBuf();
|
||||||
int getCanvasHeight();
|
int getCanvasHeight();
|
||||||
int getLoopCount();
|
int getLoopCount();
|
||||||
int getInfo(GIFINFO *pInfo);
|
int getInfo(GIFINFO* pInfo);
|
||||||
int getLastError();
|
int getLastError();
|
||||||
int getComment(char *destBuffer);
|
int getComment(char* destBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GIFIMAGE _gif;
|
GIFIMAGE _gif;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
// C interface
|
// C interface
|
||||||
int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw);
|
int GIF_openRAM(GIFIMAGE* pGIF, uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw);
|
||||||
int GIF_openFile(GIFIMAGE *pGIF, const char *szFilename, GIF_DRAW_CALLBACK *pfnDraw);
|
int GIF_openFile(GIFIMAGE* pGIF, const char* szFilename, GIF_DRAW_CALLBACK* pfnDraw);
|
||||||
void GIF_close(GIFIMAGE *pGIF);
|
void GIF_close(GIFIMAGE* pGIF);
|
||||||
void GIF_begin(GIFIMAGE *pGIF, unsigned char ucPaletteType);
|
void GIF_begin(GIFIMAGE* pGIF, unsigned char ucPaletteType);
|
||||||
void GIF_reset(GIFIMAGE *pGIF);
|
void GIF_reset(GIFIMAGE* pGIF);
|
||||||
int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser);
|
int GIF_playFrame(GIFIMAGE* pGIF, int* delayMilliseconds, void* pUser);
|
||||||
int GIF_getCanvasWidth(GIFIMAGE *pGIF);
|
int GIF_getCanvasWidth(GIFIMAGE* pGIF);
|
||||||
int GIF_getCanvasHeight(GIFIMAGE *pGIF);
|
int GIF_getCanvasHeight(GIFIMAGE* pGIF);
|
||||||
int GIF_getComment(GIFIMAGE *pGIF, char *destBuffer);
|
int GIF_getComment(GIFIMAGE* pGIF, char* destBuffer);
|
||||||
int GIF_getInfo(GIFIMAGE *pGIF, GIFINFO *pInfo);
|
int GIF_getInfo(GIFIMAGE* pGIF, GIFINFO* pInfo);
|
||||||
int GIF_getLastError(GIFIMAGE *pGIF);
|
int GIF_getLastError(GIFIMAGE* pGIF);
|
||||||
int GIF_getLoopCount(GIFIMAGE *pGIF);
|
int GIF_getLoopCount(GIFIMAGE* pGIF);
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
// Due to unaligned memory causing an exception, we have to do these macros the slow way
|
// Due to unaligned memory causing an exception, we have to do these macros the slow way
|
||||||
#define INTELSHORT(p) ((*p) + (*(p+1)<<8))
|
#define INTELSHORT(p) ((*p) + (*(p + 1) << 8))
|
||||||
#define INTELLONG(p) ((*p) + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24))
|
#define INTELLONG(p) ((*p) + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24))
|
||||||
#define MOTOSHORT(p) (((*(p))<<8) + (*(p+1)))
|
#define MOTOSHORT(p) (((*(p)) << 8) + (*(p + 1)))
|
||||||
#define MOTOLONG(p) (((*p)<<24) + ((*(p+1))<<16) + ((*(p+2))<<8) + (*(p+3)))
|
#define MOTOLONG(p) (((*p) << 24) + ((*(p + 1)) << 16) + ((*(p + 2)) << 8) + (*(p + 3)))
|
||||||
|
|
||||||
// Must be a 32-bit target processor
|
// Must be a 32-bit target processor
|
||||||
#define REGISTER_WIDTH 32
|
#define REGISTER_WIDTH 32
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
#ifndef INC_LCD_API_H_
|
#ifndef INC_LCD_API_H_
|
||||||
#define INC_LCD_API_H_
|
#define INC_LCD_API_H_
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#define LOGGER_LEVEL_ALL
|
#define LOGGER_LEVEL_ALL
|
||||||
#include "log.h"
|
|
||||||
#include "../../Drivers/BSP/STM32746G-Discovery/stm32746g_discovery_lcd.h"
|
#include "../../Drivers/BSP/STM32746G-Discovery/stm32746g_discovery_lcd.h"
|
||||||
#include "llfs.h"
|
|
||||||
#include "gifdec.h"
|
#include "gifdec.h"
|
||||||
|
#include "llfs.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The maximum amount of GIFs that can be displayed at the same time
|
* @brief The maximum amount of GIFs that can be displayed at the same time
|
||||||
@@ -23,46 +23,45 @@
|
|||||||
*/
|
*/
|
||||||
#define LCD_MAX_GIFS 5
|
#define LCD_MAX_GIFS 5
|
||||||
|
|
||||||
#define LCD_BLUE LCD_COLOR_BLUE
|
#define LCD_BLUE LCD_COLOR_BLUE
|
||||||
#define LCD_GREEN LCD_COLOR_GREEN
|
#define LCD_GREEN LCD_COLOR_GREEN
|
||||||
#define LCD_RED LCD_COLOR_RED
|
#define LCD_RED LCD_COLOR_RED
|
||||||
#define LCD_CYAN LCD_COLOR_CYAN
|
#define LCD_CYAN LCD_COLOR_CYAN
|
||||||
#define LCD_MAGENTA LCD_COLOR_MAGENTA
|
#define LCD_MAGENTA LCD_COLOR_MAGENTA
|
||||||
#define LCD_YELLOW LCD_COLOR_YELLOW
|
#define LCD_YELLOW LCD_COLOR_YELLOW
|
||||||
#define LCD_LIGHTBLUE LCD_COLOR_LIGHTBLUE
|
#define LCD_LIGHTBLUE LCD_COLOR_LIGHTBLUE
|
||||||
#define LCD_LIGHTGREEN LCD_COLOR_LIGHTGREEN
|
#define LCD_LIGHTGREEN LCD_COLOR_LIGHTGREEN
|
||||||
#define LCD_LIGHTRED LCD_COLOR_LIGHTRED
|
#define LCD_LIGHTRED LCD_COLOR_LIGHTRED
|
||||||
#define LCD_LIGHTCYAN LCD_COLOR_LIGHTCYAN
|
#define LCD_LIGHTCYAN LCD_COLOR_LIGHTCYAN
|
||||||
#define LCD_LIGHTMAGENTA LCD_COLOR_LIGHTMAGENTA
|
#define LCD_LIGHTMAGENTA LCD_COLOR_LIGHTMAGENTA
|
||||||
#define LCD_LIGHTYELLOW LCD_COLOR_LIGHTYELLOW
|
#define LCD_LIGHTYELLOW LCD_COLOR_LIGHTYELLOW
|
||||||
#define LCD_DARKBLUE LCD_COLOR_DARKBLUE
|
#define LCD_DARKBLUE LCD_COLOR_DARKBLUE
|
||||||
#define LCD_DARKGREEN LCD_COLOR_DARKGREEN
|
#define LCD_DARKGREEN LCD_COLOR_DARKGREEN
|
||||||
#define LCD_DARKRED LCD_COLOR_DARKRED
|
#define LCD_DARKRED LCD_COLOR_DARKRED
|
||||||
#define LCD_DARKCYAN LCD_COLOR_DARKCYAN
|
#define LCD_DARKCYAN LCD_COLOR_DARKCYAN
|
||||||
#define LCD_DARKMAGENTA LCD_COLOR_DARKMAGENTA
|
#define LCD_DARKMAGENTA LCD_COLOR_DARKMAGENTA
|
||||||
#define LCD_DARKYELLOW LCD_COLOR_DARKYELLOW
|
#define LCD_DARKYELLOW LCD_COLOR_DARKYELLOW
|
||||||
#define LCD_WHITE LCD_COLOR_WHITE
|
#define LCD_WHITE LCD_COLOR_WHITE
|
||||||
#define LCD_LIGHTGRAY LCD_COLOR_LIGHTGRAY
|
#define LCD_LIGHTGRAY LCD_COLOR_LIGHTGRAY
|
||||||
#define LCD_GRAY LCD_COLOR_GRAY
|
#define LCD_GRAY LCD_COLOR_GRAY
|
||||||
#define LCD_DARKGRAY LCD_COLOR_DARKGRAY
|
#define LCD_DARKGRAY LCD_COLOR_DARKGRAY
|
||||||
#define LCD_BLACK LCD_COLOR_BLACK
|
#define LCD_BLACK LCD_COLOR_BLACK
|
||||||
#define LCD_BROWN LCD_COLOR_BROWN
|
#define LCD_BROWN LCD_COLOR_BROWN
|
||||||
#define LCD_ORANGE LCD_COLOR_ORANGE
|
#define LCD_ORANGE LCD_COLOR_ORANGE
|
||||||
#define LCD_TRANSPARENT LCD_COLOR_TRANSPARENT
|
#define LCD_TRANSPARENT LCD_COLOR_TRANSPARENT
|
||||||
|
|
||||||
#define LCD_ARGB8888 0x00000000U
|
#define LCD_ARGB8888 0x00000000U
|
||||||
#define LCD_RGB888 0x00000001U
|
#define LCD_RGB888 0x00000001U
|
||||||
#define LCD_RGB565 0x00000002U
|
#define LCD_RGB565 0x00000002U
|
||||||
#define LCD_ARGB1555 0x00000003U
|
#define LCD_ARGB1555 0x00000003U
|
||||||
|
|
||||||
#define LCD_FONT8 (&Font8)
|
#define LCD_FONT8 (&Font8)
|
||||||
#define LCD_FONT12 (&Font12)
|
#define LCD_FONT12 (&Font12)
|
||||||
#define LCD_FONT16 (&Font16)
|
#define LCD_FONT16 (&Font16)
|
||||||
#define LCD_FONT20 (&Font20)
|
#define LCD_FONT20 (&Font20)
|
||||||
#define LCD_FONT24 (&Font24)
|
#define LCD_FONT24 (&Font24)
|
||||||
|
|
||||||
|
extern LTDC_HandleTypeDef hLtdcHandler;
|
||||||
extern LTDC_HandleTypeDef hLtdcHandler;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GIFIMAGE gif;
|
GIFIMAGE gif;
|
||||||
@@ -105,7 +104,7 @@ void lcd_task(void);
|
|||||||
* @param[in] bg_color Text background color
|
* @param[in] bg_color Text background color
|
||||||
* @param[in] font Font size, see defines above in file
|
* @param[in] font Font size, see defines above in file
|
||||||
*/
|
*/
|
||||||
void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t color, uint32_t bg_color, sFONT *font);
|
void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draw BMP image on screen
|
* @brief Draw BMP image on screen
|
||||||
@@ -121,7 +120,12 @@ void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t
|
|||||||
* @param[in] y_size Height of image
|
* @param[in] y_size Height of image
|
||||||
* @param[in] color_mode Color mode (see defined color modes above in file)
|
* @param[in] color_mode Color mode (see defined color modes above in file)
|
||||||
*/
|
*/
|
||||||
void lcd_draw_raw_img(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode);
|
void lcd_draw_raw_img(const void* p_src,
|
||||||
|
uint32_t x_pos,
|
||||||
|
uint32_t y_pos,
|
||||||
|
uint32_t x_size,
|
||||||
|
uint32_t y_size,
|
||||||
|
uint32_t color_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draw BMP image on screen
|
* @brief Draw BMP image on screen
|
||||||
@@ -148,8 +152,8 @@ void lcd_draw_img_from_fs(const char* name, uint32_t x_pos, uint32_t y_pos);
|
|||||||
/**
|
/**
|
||||||
* @brief Draw BMP image on screen by specifying the llfs_file_t, the BMP image has in the file system
|
* @brief Draw BMP image on screen by specifying the llfs_file_t, the BMP image has in the file system
|
||||||
* Draw BMP image from C array to the LCD screen at position X, Y by specifying the BMP image name on the filesystem
|
* Draw BMP image from C array to the LCD screen at position X, Y by specifying the BMP image name on the filesystem
|
||||||
* Supports ARGB8888, RGB565, RGB888
|
* Supports ARGB8888, RGB565, RGB888
|
||||||
*
|
*
|
||||||
* @param file pointer to the llfs_file_t
|
* @param file pointer to the llfs_file_t
|
||||||
* @param x_pos X-position
|
* @param x_pos X-position
|
||||||
* @param y_pos Y-position
|
* @param y_pos Y-position
|
||||||
@@ -187,7 +191,8 @@ void lcd_stop_all_gifs(void);
|
|||||||
/**
|
/**
|
||||||
* @brief Draw GIF image on screen from memory
|
* @brief Draw GIF image on screen from memory
|
||||||
* Draw GIF image from memory to the LCD screen at position X, Y
|
* Draw GIF image from memory to the LCD screen at position X, Y
|
||||||
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_gif_t handle will be invalid for further use
|
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_gif_t
|
||||||
|
* handle will be invalid for further use
|
||||||
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
|
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
|
||||||
*
|
*
|
||||||
* @param src Pointer to the GIF image data
|
* @param src Pointer to the GIF image data
|
||||||
@@ -201,7 +206,8 @@ lcd_gif_t* lcd_draw_gif(uint8_t* src, size_t size, uint32_t x_pos, uint32_t y_po
|
|||||||
/**
|
/**
|
||||||
* @brief Draw GIF image on screen from filesystem
|
* @brief Draw GIF image on screen from filesystem
|
||||||
* Draw GIF image from filesystem to the LCD screen at position X, Y
|
* Draw GIF image from filesystem to the LCD screen at position X, Y
|
||||||
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t handle will be invalidated
|
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t
|
||||||
|
* handle will be invalidated
|
||||||
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
|
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
|
||||||
*
|
*
|
||||||
* @param name The filename of the GIF image
|
* @param name The filename of the GIF image
|
||||||
@@ -212,11 +218,12 @@ lcd_gif_t* lcd_draw_gif(uint8_t* src, size_t size, uint32_t x_pos, uint32_t y_po
|
|||||||
lcd_gif_t* lcd_draw_gif_from_fs(const char* name, uint32_t x_pos, uint32_t y_pos);
|
lcd_gif_t* lcd_draw_gif_from_fs(const char* name, uint32_t x_pos, uint32_t y_pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draw GIF image on screen from filesystem
|
* @brief Draw GIF image on screen from filesystem
|
||||||
* Draw GIF image from filesystem to the LCD screen at position X, Y
|
* Draw GIF image from filesystem to the LCD screen at position X, Y
|
||||||
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t handle will be invalidated
|
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t
|
||||||
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
|
* handle will be invalidated
|
||||||
*
|
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
|
||||||
|
*
|
||||||
* @param file The pointer to the llfs_file_t
|
* @param file The pointer to the llfs_file_t
|
||||||
* @param x_pos The X position on the screen
|
* @param x_pos The X position on the screen
|
||||||
* @param y_pos The Y position on the screen
|
* @param y_pos The Y position on the screen
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
#ifndef LOG_H
|
#ifndef LOG_H
|
||||||
#define LOG_H
|
#define LOG_H
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
@@ -52,24 +52,24 @@
|
|||||||
|
|
||||||
#define CLEAR_SCREEN "\033c"
|
#define CLEAR_SCREEN "\033c"
|
||||||
|
|
||||||
#define CURSOR_RESET ANSI_ESC "[H"
|
#define CURSOR_RESET ANSI_ESC "[H"
|
||||||
#define CURSOR_UP(n) ANSI_ESC "[" #n "A"
|
#define CURSOR_UP(n) ANSI_ESC "[" #n "A"
|
||||||
#define CURSOR_DOWN(n) ANSI_ESC "[" #n "B"
|
#define CURSOR_DOWN(n) ANSI_ESC "[" #n "B"
|
||||||
#define CURSOR_RIGHT(n) ANSI_ESC "[" #n "C"
|
#define CURSOR_RIGHT(n) ANSI_ESC "[" #n "C"
|
||||||
#define CURSOR_LEFT(n) ANSI_ESC "[" #n "D"
|
#define CURSOR_LEFT(n) ANSI_ESC "[" #n "D"
|
||||||
#define CURSOR_NEXT_N_LINES(n) ANSI_ESC "[" #n "E"
|
#define CURSOR_NEXT_N_LINES(n) ANSI_ESC "[" #n "E"
|
||||||
#define CURSOR_PREV_N_LINES(n) ANSI_ESC "[" #n "F"
|
#define CURSOR_PREV_N_LINES(n) ANSI_ESC "[" #n "F"
|
||||||
#define CURSOR_COL(n) ANSI_ESC "[" #n "G"
|
#define CURSOR_COL(n) ANSI_ESC "[" #n "G"
|
||||||
#define CURSOR_POS ANSI_ESC "[" #n ";" #n "H"
|
#define CURSOR_POS ANSI_ESC "[" #n ";" #n "H"
|
||||||
#define CURSOR_SAVE ANSI_ESC "7"
|
#define CURSOR_SAVE ANSI_ESC "7"
|
||||||
#define CURSOR_RESTORE ANSI_ESC "8"
|
#define CURSOR_RESTORE ANSI_ESC "8"
|
||||||
|
|
||||||
#define ERASE_FROM_CURSOR_TO_END ANSI_ESC "[0J"
|
#define ERASE_FROM_CURSOR_TO_END ANSI_ESC "[0J"
|
||||||
#define ERASE_FROM_CURSOR_TO_BEGINNING ANSI_ESC "[1J"
|
#define ERASE_FROM_CURSOR_TO_BEGINNING ANSI_ESC "[1J"
|
||||||
#define ERASE_ENTIRE_SCREEN ANSI_ESC "[2J"
|
#define ERASE_ENTIRE_SCREEN ANSI_ESC "[2J"
|
||||||
#define ERASE_FROM_CURSOR_TO_END_LINE ANSI_ESC "[0K"
|
#define ERASE_FROM_CURSOR_TO_END_LINE ANSI_ESC "[0K"
|
||||||
#define ERASE_FROM_CURSOR_TO_BEGINNING_LINE ANSI_ESC "[1K"
|
#define ERASE_FROM_CURSOR_TO_BEGINNING_LINE ANSI_ESC "[1K"
|
||||||
#define ERASE_ENTIRE_LINE ANSI_ESC "[2K"
|
#define ERASE_ENTIRE_LINE ANSI_ESC "[2K"
|
||||||
|
|
||||||
#if LOGGER_COLOR == 1
|
#if LOGGER_COLOR == 1
|
||||||
#define LOG_RESET_COLOR "\033[0m"
|
#define LOG_RESET_COLOR "\033[0m"
|
||||||
@@ -88,27 +88,37 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LOGGER_LEVEL <= 1
|
#if LOGGER_LEVEL <= 1
|
||||||
#define LOG_DEBUG(tag, fmt, ...) printf(LOG_COLOR_D"[Debug] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
|
#define LOG_DEBUG(tag, fmt, ...) \
|
||||||
|
printf(LOG_COLOR_D "[Debug] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
|
||||||
|
##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOG_DEBUG(tag, fmt, ...)
|
#define LOG_DEBUG(tag, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
#if LOGGER_LEVEL <= 2
|
#if LOGGER_LEVEL <= 2
|
||||||
#define LOG_INFO(tag, fmt, ...) printf(LOG_COLOR_I"[Info] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
|
#define LOG_INFO(tag, fmt, ...) \
|
||||||
|
printf(LOG_COLOR_I "[Info] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
|
||||||
|
##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOG_INFO(tag, fmt, ...)
|
#define LOG_INFO(tag, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
#if LOGGER_LEVEL <= 3
|
#if LOGGER_LEVEL <= 3
|
||||||
#define LOG_WARN(tag, fmt, ...) printf(LOG_COLOR_W"[Warning] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
|
#define LOG_WARN(tag, fmt, ...) \
|
||||||
|
printf(LOG_COLOR_W "[Warning] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
|
||||||
|
##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOG_WARN(tag, fmt, ...)
|
#define LOG_WARN(tag, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
#if LOGGER_LEVEL <= 4
|
#if LOGGER_LEVEL <= 4
|
||||||
#define LOG_CRIT(tag, fmt, ...) printf(LOG_COLOR_C"[Critical] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
|
#define LOG_CRIT(tag, fmt, ...) \
|
||||||
|
printf(LOG_COLOR_C "[Critical] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
|
||||||
|
##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOG_CRIT(tag, fmt, ...)
|
#define LOG_CRIT(tag, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
#if LOGGER_LEVEL <= 4
|
#if LOGGER_LEVEL <= 4
|
||||||
#define LOG_FATAL(tag, fmt, ...) printf(LOG_COLOR_F"[Fatal] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
|
#define LOG_FATAL(tag, fmt, ...) \
|
||||||
|
printf(LOG_COLOR_F "[Fatal] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
|
||||||
|
##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOG_FATAL(tag, fmt, ...)
|
#define LOG_FATAL(tag, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
@@ -117,6 +127,6 @@
|
|||||||
* Use the LOG_* macros instead e.g., LOG_DEBUG(TAG, "Debug message");
|
* Use the LOG_* macros instead e.g., LOG_DEBUG(TAG, "Debug message");
|
||||||
*/
|
*/
|
||||||
uint32_t logger_get_timestamp(void);
|
uint32_t logger_get_timestamp(void);
|
||||||
int _write(int file, char *data, int len);
|
int _write(int file, char* data, int len);
|
||||||
|
|
||||||
#endif /* LOG_H */
|
#endif /* LOG_H */
|
||||||
@@ -11,15 +11,13 @@
|
|||||||
|
|
||||||
#define MODBUSPORT 502 // 502 is the default
|
#define MODBUSPORT 502 // 502 is the default
|
||||||
|
|
||||||
|
|
||||||
#include <tcp.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <tcp.h>
|
||||||
#include "lcd_api.h"
|
#include "lcd_api.h"
|
||||||
#include "llfs.h"
|
#include "llfs.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn void modbus_init
|
* @fn void modbus_init
|
||||||
* @brief Initializes the modbus tcp
|
* @brief Initializes the modbus tcp
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
/**
|
/**
|
||||||
* @file tcp_cmd.h
|
* @file tcp_cmd.h
|
||||||
* @brief TCP CMD interface
|
* @brief This file contains the headers of the tcp command interface
|
||||||
* @author Gert R.
|
* @author Sander S.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INC_TCP_CMD_H_
|
#ifndef INC_TCP_CMD_H_
|
||||||
#define INC_TCP_CMD_H_
|
#define INC_TCP_CMD_H_
|
||||||
|
#ifndef TESTING
|
||||||
#include "lcd_api.h"
|
#include "lcd_api.h"
|
||||||
|
#else
|
||||||
|
#include "mocs.h"
|
||||||
|
#endif
|
||||||
#include "llfs.h"
|
#include "llfs.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include <tcp.h>
|
#include <tcp.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
void tcp_cmd_remove_newline(char* str, size_t len);
|
||||||
void tcp_cmd_init( void );
|
char* tcp_cmd_remove_leading_space(char* str, size_t len);
|
||||||
|
void tcp_cmd_str_tolower(char* str);
|
||||||
|
char* tcp_cmd_get_next_token(char* input, const char* delimiters, char** next);
|
||||||
|
void tcp_cmd_init(void);
|
||||||
|
err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
|
||||||
|
|
||||||
#endif /* INC_TCP_CMD_H_ */
|
#endif /* INC_TCP_CMD_H_ */
|
||||||
|
|||||||
82
project/Core/Inc/website_backend.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* @file website_backend.h
|
||||||
|
* @brief Backend for the website to operate
|
||||||
|
* @author Toon B.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_WEBSITE_BACKEND_
|
||||||
|
#define INC_WEBSITE_BACKEND_
|
||||||
|
|
||||||
|
/* Include headers C lib */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Defines */
|
||||||
|
#define LOGGER_LEVEL_ALL
|
||||||
|
#define STR_MAX 200
|
||||||
|
#define CLR_MAX 11
|
||||||
|
#define IMG_X 0
|
||||||
|
#define IMG_Y 0
|
||||||
|
#define SD_IMG "st.bmp"
|
||||||
|
|
||||||
|
/* Include headers */
|
||||||
|
#include "httpd.h"
|
||||||
|
#include "lcd_api.h"
|
||||||
|
#include "llfs.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "lwip.h"
|
||||||
|
#include "lwip/apps/fs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void wbe_init(void)
|
||||||
|
* @brief Initialise the http server. It also sets the beginning screen
|
||||||
|
* of the display.
|
||||||
|
*/
|
||||||
|
void wbe_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int fs_open_custom(struct fs_file*, const char*)
|
||||||
|
* @brief Function is called when the frontend wants to reach/open a file
|
||||||
|
* or endpoint on the backend.
|
||||||
|
*
|
||||||
|
* @param[in] file, the file pointer of the file that the frontend wants
|
||||||
|
* @param[in] name, the name of the file or endpoint that the frontend asks for
|
||||||
|
* @return[out] returns 0 if file or endpoint was not found, 1 if it was found
|
||||||
|
*/
|
||||||
|
int fs_open_custom(struct fs_file* file, const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void fs_close_custom(struct fs_file*)
|
||||||
|
* @brief Called when closing files and endpoints
|
||||||
|
*
|
||||||
|
* @param[in] file, the file pointer of the file that the frontend wants
|
||||||
|
*/
|
||||||
|
void fs_close_custom(struct fs_file* file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void httpd_cgi_handler(struct fs_file*, const char*, int, char**, char**)
|
||||||
|
* @brief When data is send from the frontend to the backend with the CGI
|
||||||
|
* tag and parameters, this function is called. With this comes parameters that
|
||||||
|
* we want to read for further use.
|
||||||
|
*
|
||||||
|
* @param[in] file, the file pointer of the file that the frontend wants
|
||||||
|
* @param[in] uri, the URI that is given to the backend from the frontend (here cgi)
|
||||||
|
* @param[in] num_parm, the number of parameters that is given with the URI
|
||||||
|
* @param[in] pc_param, contains the name of each parameter
|
||||||
|
* @param[in] pc_value, is the value of each parameter
|
||||||
|
*/
|
||||||
|
void httpd_cgi_handler(struct fs_file* file, const char* uri, int num_parm, char** pc_param, char** pc_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void wbe_display(const char*, const uint32_t, const uint32_t, const char*)
|
||||||
|
* @brief Function displays the sentence, its color, the background and the given
|
||||||
|
* image on the LCD screen.
|
||||||
|
*
|
||||||
|
* @param[in] txt, is the text string that needs to be displayed
|
||||||
|
* @param[in] txt_color, the color of the wanted string
|
||||||
|
* @param[in] background_color, color of the background of the screen
|
||||||
|
* @param[in] image, name of the wanted image to be displayed
|
||||||
|
*/
|
||||||
|
void wbe_display(const char* txt, const uint32_t txt_color, const uint32_t background_color, const char* image);
|
||||||
|
|
||||||
|
#endif /* INC_WEBSITE_BACKEND_ */
|
||||||
@@ -49,20 +49,18 @@ static void udp_broadcast_set_owner_details_mac(void) {
|
|||||||
* @see UDP_BROADCAST_LCD_NAME_PRE_TEXT in front of it
|
* @see UDP_BROADCAST_LCD_NAME_PRE_TEXT in front of it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void udp_broadcast_name_to_lcd(void){
|
static void udp_broadcast_name_to_lcd(void) {
|
||||||
char text[UDP_BROADCAST_LCD_TEXT_SIZE];
|
char text[UDP_BROADCAST_LCD_TEXT_SIZE];
|
||||||
|
|
||||||
memset(text,' ',UDP_BROADCAST_LCD_TEXT_SIZE); // Fill with spaces
|
memset(text, ' ', UDP_BROADCAST_LCD_TEXT_SIZE); // Fill with spaces
|
||||||
text[UDP_BROADCAST_LCD_TEXT_SIZE - 1] = '\0'; // Make the last a NULL byte
|
text[UDP_BROADCAST_LCD_TEXT_SIZE - 1] = '\0'; // Make the last a NULL byte
|
||||||
lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12);
|
lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12);
|
||||||
|
|
||||||
snprintf(text, UDP_BROADCAST_LCD_TEXT_SIZE, "%s%s",UDP_BROADCAST_LCD_NAME_PRE_TEXT,
|
snprintf(text, UDP_BROADCAST_LCD_TEXT_SIZE, "%s%s", UDP_BROADCAST_LCD_NAME_PRE_TEXT, udp_owner.name);
|
||||||
udp_owner.name);
|
|
||||||
|
|
||||||
lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12);
|
lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn uint8_t udp_broadcast_set_owner_details_name(owner_details_t*, const char*)
|
* @fn uint8_t udp_broadcast_set_owner_details_name(owner_details_t*, const char*)
|
||||||
* @brief set_owner_details_name() sets the owner's name in the owner_details_t struct
|
* @brief set_owner_details_name() sets the owner's name in the owner_details_t struct
|
||||||
@@ -76,13 +74,12 @@ static void udp_broadcast_name_to_lcd(void){
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static uint8_t udp_broadcast_set_owner_details_name(const char* name) {
|
static uint8_t udp_broadcast_set_owner_details_name(const char* name) {
|
||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
LOG_WARN(TAG, "%s: string given is a NULL pointer", __func__);
|
LOG_WARN(TAG, "%s: string given is a NULL pointer", __func__);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(TAG, "set: %s", name);
|
LOG_DEBUG(TAG, "set: %s", name);
|
||||||
strncpy(udp_owner.name, name, sizeof(udp_owner.name) - 1); // -1: compensate for '\0'
|
strncpy(udp_owner.name, name, sizeof(udp_owner.name) - 1); // -1: compensate for '\0'
|
||||||
|
|
||||||
udp_broadcast_name_to_lcd();
|
udp_broadcast_name_to_lcd();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -104,7 +101,7 @@ static uint8_t udp_broadcast_set_owner_details_surname(const char* surname) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(TAG, "set: %s", surname);
|
LOG_DEBUG(TAG, "set: %s", surname);
|
||||||
strncpy(udp_owner.surname, surname, sizeof(udp_owner.surname)-1); // -1: compensate for '\0'
|
strncpy(udp_owner.surname, surname, sizeof(udp_owner.surname) - 1); // -1: compensate for '\0'
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +122,7 @@ static uint8_t udp_broadcast_set_owner_details_reply(const char* reply) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(TAG, "set: %s", reply);
|
LOG_DEBUG(TAG, "set: %s", reply);
|
||||||
strncpy(udp_owner.reply, reply, sizeof(udp_owner.reply) - 1); // -1: compensate for '\0'
|
strncpy(udp_owner.reply, reply, sizeof(udp_owner.reply) - 1); // -1: compensate for '\0'
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +141,8 @@ static void udp_broadcast_format_reply(void) {
|
|||||||
udp_owner.mac_address[1], udp_owner.mac_address[2], udp_owner.mac_address[3], udp_owner.mac_address[4],
|
udp_owner.mac_address[1], udp_owner.mac_address[2], udp_owner.mac_address[3], udp_owner.mac_address[4],
|
||||||
udp_owner.mac_address[5]);
|
udp_owner.mac_address[5]);
|
||||||
|
|
||||||
snprintf(reply_buf, UDP_BROADCAST_MAX_REPLY_SIZE, "%s %s %s %s", mac_addr_str, UDP_BROADCAST_REPLY_MIDDLE_TEXT, udp_owner.surname,
|
snprintf(reply_buf, UDP_BROADCAST_MAX_REPLY_SIZE, "%s %s %s %s", mac_addr_str, UDP_BROADCAST_REPLY_MIDDLE_TEXT,
|
||||||
udp_owner.name);
|
udp_owner.surname, udp_owner.name);
|
||||||
udp_broadcast_set_owner_details_reply(reply_buf);
|
udp_broadcast_set_owner_details_reply(reply_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +160,6 @@ static void udp_broadcast_format_reply(void) {
|
|||||||
*/
|
*/
|
||||||
err_t udp_broadcast_set_owner_details(const char* name, const char* surname) {
|
err_t udp_broadcast_set_owner_details(const char* name, const char* surname) {
|
||||||
if (!udp_broadcast_set_owner_details_name(name) && !udp_broadcast_set_owner_details_surname(surname)) {
|
if (!udp_broadcast_set_owner_details_name(name) && !udp_broadcast_set_owner_details_surname(surname)) {
|
||||||
|
|
||||||
// If both return 0 it's okay
|
// If both return 0 it's okay
|
||||||
udp_broadcast_set_owner_details_mac();
|
udp_broadcast_set_owner_details_mac();
|
||||||
udp_broadcast_format_reply();
|
udp_broadcast_format_reply();
|
||||||
@@ -234,7 +230,7 @@ static uint8_t udp_broadcast_check_function(const char data[UDP_BROADCAST_MAX_DA
|
|||||||
memset(func, 0, sizeof(func));
|
memset(func, 0, sizeof(func));
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
|
||||||
memcpy(func,data,UDP_BROADCAST_MAX_FUNC_LEN - 1);
|
memcpy(func, data, UDP_BROADCAST_MAX_FUNC_LEN - 1);
|
||||||
if (strcmp(func, "func1:") != 0) {
|
if (strcmp(func, "func1:") != 0) {
|
||||||
LOG_WARN(TAG, "%s: datagram does not contain function that's currently available", __func__);
|
LOG_WARN(TAG, "%s: datagram does not contain function that's currently available", __func__);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -245,16 +241,16 @@ static uint8_t udp_broadcast_check_function(const char data[UDP_BROADCAST_MAX_DA
|
|||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (enders[2] - enders[1] < UDP_BROADCAST_MAX_NAME_SIZE + 2 && data_len - enders[3] < UDP_BROADCAST_MAX_NAME_SIZE + 2
|
if (enders[2] - enders[1] < UDP_BROADCAST_MAX_NAME_SIZE + 2
|
||||||
&& strncmp(data + enders[0], ":name", 5) == 0 && strncmp(data + enders[2], ", surname", 9) == 0) {
|
&& data_len - enders[3] < UDP_BROADCAST_MAX_NAME_SIZE + 2 && strncmp(data + enders[0], ":name", 5) == 0
|
||||||
|
&& strncmp(data + enders[2], ", surname", 9) == 0) {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
for (uint8_t i = enders[1] + 2; i < enders[2]; i++) {
|
for (uint8_t i = enders[1] + 2; i < enders[2]; i++) {
|
||||||
buffer[counter] = data[i];
|
buffer[counter] = data[i];
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
if (buffer[0]=='\0') {
|
if (buffer[0] == '\0') {
|
||||||
strncpy(buffer, "name", sizeof(buffer) - 1); // -1: compensate for '\0'
|
strncpy(buffer, "name", sizeof(buffer) - 1); // -1: compensate for '\0'
|
||||||
}
|
}
|
||||||
LOG_INFO(TAG, "new owner name:%s", buffer);
|
LOG_INFO(TAG, "new owner name:%s", buffer);
|
||||||
udp_broadcast_set_owner_details_name(buffer);
|
udp_broadcast_set_owner_details_name(buffer);
|
||||||
@@ -264,15 +260,15 @@ static uint8_t udp_broadcast_check_function(const char data[UDP_BROADCAST_MAX_DA
|
|||||||
buffer[counter] = data[i];
|
buffer[counter] = data[i];
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
if (buffer[0]=='\0') {
|
if (buffer[0] == '\0') {
|
||||||
strncpy(buffer, "default", sizeof(buffer) - 1); // -1: compensate for '\0'
|
strncpy(buffer, "default", sizeof(buffer) - 1); // -1: compensate for '\0'
|
||||||
}
|
}
|
||||||
LOG_INFO(TAG, "new owner surname:%s", buffer);
|
LOG_INFO(TAG, "new owner surname:%s", buffer);
|
||||||
udp_broadcast_set_owner_details_surname(buffer);
|
udp_broadcast_set_owner_details_surname(buffer);
|
||||||
udp_broadcast_format_reply();
|
udp_broadcast_format_reply();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
LOG_WARN(TAG,"%s: function didn't receive the right formatting", __func__);
|
LOG_WARN(TAG, "%s: function didn't receive the right formatting", __func__);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +307,7 @@ static void udp_receive_callback(void* arg,
|
|||||||
}
|
}
|
||||||
pc = (char*)p->payload;
|
pc = (char*)p->payload;
|
||||||
len = p->tot_len;
|
len = p->tot_len;
|
||||||
if (len >= UDP_BROADCAST_MAX_DATA_SIZE) { // >= : only if it's smaller to compensate for '\0'
|
if (len >= UDP_BROADCAST_MAX_DATA_SIZE) { // >= : only if it's smaller to compensate for '\0'
|
||||||
LOG_WARN(TAG, "%s: input buffer was bigger than or was max size %d", __func__, UDP_BROADCAST_MAX_DATA_SIZE);
|
LOG_WARN(TAG, "%s: input buffer was bigger than or was max size %d", __func__, UDP_BROADCAST_MAX_DATA_SIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -328,15 +324,14 @@ static void udp_receive_callback(void* arg,
|
|||||||
LOG_INFO(TAG, "%s: received data from %s at port: %d: %s", __func__, source_ip_str, port, data);
|
LOG_INFO(TAG, "%s: received data from %s at port: %d: %s", __func__, source_ip_str, port, data);
|
||||||
LOG_INFO(TAG, "%s: checking which function was called", __func__);
|
LOG_INFO(TAG, "%s: checking which function was called", __func__);
|
||||||
|
|
||||||
if(!udp_broadcast_check_function(data)){ // Should return 0 to reply
|
if (!udp_broadcast_check_function(data)) { // Should return 0 to reply
|
||||||
p_data->payload = udp_owner.reply;
|
p_data->payload = udp_owner.reply;
|
||||||
p_data->len = strlen(udp_owner.reply);
|
p_data->len = strlen(udp_owner.reply);
|
||||||
p_data->tot_len = strlen(udp_owner.reply);
|
p_data->tot_len = strlen(udp_owner.reply);
|
||||||
udp_sendto(connection, p_data, addr, 64000); // QT app listens on port 64000
|
udp_sendto(connection, p_data, addr, 64000); // QT app listens on port 64000
|
||||||
LOG_INFO(TAG, "%s: tried to reply to %s at port: %d: %s", __func__, source_ip_str, 64000, udp_owner.reply);
|
LOG_INFO(TAG, "%s: tried to reply to %s at port: %d: %s", __func__, source_ip_str, 64000, udp_owner.reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
defer:
|
defer:
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
pbuf_free(p_data);
|
pbuf_free(p_data);
|
||||||
@@ -375,8 +370,6 @@ err_t udp_broadcast_connection_init(void) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn err_t udp_broadcast_init()
|
* @fn err_t udp_broadcast_init()
|
||||||
* @brief udp_broadcast_init() initializes the owner's variables and calls upon @see udp_broadcast_connection_init()
|
* @brief udp_broadcast_init() initializes the owner's variables and calls upon @see udp_broadcast_connection_init()
|
||||||
@@ -391,7 +384,7 @@ err_t udp_broadcast_connection_init(void) {
|
|||||||
err_t udp_broadcast_init(uint32_t x_pos, uint32_t y_pos) {
|
err_t udp_broadcast_init(uint32_t x_pos, uint32_t y_pos) {
|
||||||
owner_name_x_pos = x_pos;
|
owner_name_x_pos = x_pos;
|
||||||
owner_name_y_pos = y_pos;
|
owner_name_y_pos = y_pos;
|
||||||
if(udp_broadcast_set_owner_details("name", "default") != ERR_OK){
|
if (udp_broadcast_set_owner_details("name", "default") != ERR_OK) {
|
||||||
LOG_WARN(TAG, "%s: don't give NULL pointers as arguments for the owner's details", __func__);
|
LOG_WARN(TAG, "%s: don't give NULL pointers as arguments for the owner's details", __func__);
|
||||||
return ERR_ARG;
|
return ERR_ARG;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "lcd_api.h"
|
#include "lcd_api.h"
|
||||||
|
|
||||||
|
|
||||||
static const char* TAG = "lcd_api";
|
static const char* TAG = "lcd_api";
|
||||||
|
|
||||||
static DMA2D_HandleTypeDef hDma2dHandler2;
|
static DMA2D_HandleTypeDef hDma2dHandler2;
|
||||||
@@ -85,7 +84,12 @@ void lcd_task(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font) {
|
void lcd_display_text(const char* text,
|
||||||
|
uint32_t x_pos,
|
||||||
|
uint32_t y_pos,
|
||||||
|
uint32_t color,
|
||||||
|
uint32_t bg_color,
|
||||||
|
sFONT* font) {
|
||||||
BSP_LCD_SelectLayer(1);
|
BSP_LCD_SelectLayer(1);
|
||||||
LOG_INFO(TAG, "Display text: %s @x=%d,y=%d", text, x_pos, y_pos);
|
LOG_INFO(TAG, "Display text: %s @x=%d,y=%d", text, x_pos, y_pos);
|
||||||
|
|
||||||
@@ -118,7 +122,12 @@ void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t
|
|||||||
BSP_LCD_DisplayStringAt(x_pos, y_pos, (uint8_t*)text, LEFT_MODE);
|
BSP_LCD_DisplayStringAt(x_pos, y_pos, (uint8_t*)text, LEFT_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_draw_raw_img(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode) {
|
void lcd_draw_raw_img(const void* p_src,
|
||||||
|
uint32_t x_pos,
|
||||||
|
uint32_t y_pos,
|
||||||
|
uint32_t x_size,
|
||||||
|
uint32_t y_size,
|
||||||
|
uint32_t color_mode) {
|
||||||
LOG_INFO(TAG, "Displaying raw image: @x=%lu, @y=%lu, width=%lu, height=%lu", x_pos, y_pos, x_size, y_size);
|
LOG_INFO(TAG, "Displaying raw image: @x=%lu, @y=%lu, width=%lu, height=%lu", x_pos, y_pos, x_size, y_size);
|
||||||
BSP_LCD_SelectLayer(0);
|
BSP_LCD_SelectLayer(0);
|
||||||
uint32_t address = hLtdcHandler.LayerCfg[1].FBStartAdress + (((BSP_LCD_GetXSize() * y_pos) + x_pos) * (4));
|
uint32_t address = hLtdcHandler.LayerCfg[1].FBStartAdress + (((BSP_LCD_GetXSize() * y_pos) + x_pos) * (4));
|
||||||
@@ -197,7 +206,7 @@ void lcd_clear_images(void) {
|
|||||||
BSP_LCD_Clear(0);
|
BSP_LCD_Clear(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_set_bg_color_layer0(uint32_t color){
|
void lcd_set_bg_color_layer0(uint32_t color) {
|
||||||
BSP_LCD_SelectLayer(0);
|
BSP_LCD_SelectLayer(0);
|
||||||
BSP_LCD_Clear(color);
|
BSP_LCD_Clear(color);
|
||||||
}
|
}
|
||||||
@@ -316,9 +325,9 @@ static inline void free_gif_slot(lcd_gif_t* gif) {
|
|||||||
static void gif_draw_cb(GIFDRAW* pDraw) {
|
static void gif_draw_cb(GIFDRAW* pDraw) {
|
||||||
BSP_LCD_SelectLayer(0);
|
BSP_LCD_SelectLayer(0);
|
||||||
lcd_gif_t* gif = (lcd_gif_t*)pDraw->pUser;
|
lcd_gif_t* gif = (lcd_gif_t*)pDraw->pUser;
|
||||||
uint8_t* palette = pDraw->pPalette24; // The RGB888 color palette
|
uint8_t* palette = pDraw->pPalette24; // The RGB888 color palette
|
||||||
uint8_t* p_src = pDraw->pPixels; // Source pixel pointer
|
uint8_t* p_src = pDraw->pPixels; // Source pixel pointer
|
||||||
int y = pDraw->iY + pDraw->y; // Current line being drawn
|
int y = pDraw->iY + pDraw->y; // Current line being drawn
|
||||||
|
|
||||||
// Calculate the destination address of the first pixel in the line
|
// Calculate the destination address of the first pixel in the line
|
||||||
uint32_t address = hLtdcHandler.LayerCfg[0].FBStartAdress + (((BSP_LCD_GetXSize() * gif->y_pos) + gif->x_pos) * 4)
|
uint32_t address = hLtdcHandler.LayerCfg[0].FBStartAdress + (((BSP_LCD_GetXSize() * gif->y_pos) + gif->x_pos) * 4)
|
||||||
@@ -344,10 +353,10 @@ static void gif_draw_cb(GIFDRAW* pDraw) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the color from the palette and convert it to ARGB8888
|
// Get the color from the palette and convert it to ARGB8888
|
||||||
uint8_t *p = palette + (pixel * 3);
|
uint8_t* p = palette + (pixel * 3);
|
||||||
uint32_t color = (0xFF << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
|
uint32_t color = (0xFF << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
|
||||||
|
|
||||||
// Draw the pixel
|
// Draw the pixel
|
||||||
((uint32_t *)address)[x] = color;
|
((uint32_t*)address)[x] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define LOGGER_LEVEL_WARN
|
#define LOGGER_LEVEL_WARN
|
||||||
#include "log.h"
|
|
||||||
#include "llfs.h"
|
#include "llfs.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The maximum number of files that can be opened concurrently using the POSIX API
|
* @brief The maximum number of files that can be opened concurrently using the POSIX API
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
extern struct llfs_data_file* llfs_root;
|
extern struct llfs_data_file* llfs_root;
|
||||||
static const char* TAG = "llfs";
|
static const char* TAG = "llfs";
|
||||||
static size_t file_count = 0; // Cache for the number of files in the filesystem
|
static size_t file_count = 0; // Cache for the number of files in the filesystem
|
||||||
static FILE* file_table[POSIX_MAX_FILES];
|
static FILE* file_table[POSIX_MAX_FILES];
|
||||||
|
|
||||||
#ifndef TESTING
|
#ifndef TESTING
|
||||||
@@ -331,7 +331,7 @@ off_t _lseek(int file, int ptr, int dir) {
|
|||||||
*/
|
*/
|
||||||
int _fstat(int file, struct stat* st) {
|
int _fstat(int file, struct stat* st) {
|
||||||
FILE* stream;
|
FILE* stream;
|
||||||
llfs_file_t *llfs_file;
|
llfs_file_t* llfs_file;
|
||||||
|
|
||||||
// Check if the file is stdin, stdout or stderr
|
// Check if the file is stdin, stdout or stderr
|
||||||
if (file == STDIN_FILENO || file == STDOUT_FILENO || file == STDERR_FILENO) {
|
if (file == STDIN_FILENO || file == STDOUT_FILENO || file == STDERR_FILENO) {
|
||||||
@@ -353,7 +353,7 @@ int _fstat(int file, struct stat* st) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
st->st_mode = S_IFREG; // Regular file
|
st->st_mode = S_IFREG; // Regular file
|
||||||
st->st_size = (off_t)llfs_file->len;
|
st->st_size = (off_t)llfs_file->len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -442,4 +442,3 @@ static uint8_t file_ext_cmp(const char* const filename, const char* const ext) {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
295717
project/Core/Src/llfs_data.c
@@ -7,8 +7,8 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "stm32f7xx_hal.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "stm32f7xx_hal.h"
|
||||||
|
|
||||||
extern UART_HandleTypeDef huart1;
|
extern UART_HandleTypeDef huart1;
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ extern UART_HandleTypeDef huart1;
|
|||||||
* @return The current timestamp in milliseconds since boot
|
* @return The current timestamp in milliseconds since boot
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int _write(int file, char *data, int len) {
|
int _write(int file, char* data, int len) {
|
||||||
HAL_StatusTypeDef status;
|
HAL_StatusTypeDef status;
|
||||||
|
|
||||||
switch (file) {
|
switch (file) {
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
/* USER CODE BEGIN Header */
|
/* USER CODE BEGIN Header */
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @file : main.c
|
* @file : main.c
|
||||||
* @brief : Main program body
|
* @brief : Main program body
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @attention
|
* @attention
|
||||||
*
|
*
|
||||||
* Copyright (c) 2023 STMicroelectronics.
|
* Copyright (c) 2023 STMicroelectronics.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This software is licensed under terms that can be found in the LICENSE file
|
* This software is licensed under terms that can be found in the LICENSE file
|
||||||
* in the root directory of this software component.
|
* in the root directory of this software component.
|
||||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||||
*
|
*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
/* USER CODE END Header */
|
/* USER CODE END Header */
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "modbus_tcp.h"
|
#include "modbus_tcp.h"
|
||||||
#include "UDP_broadcast.h"
|
#include "UDP_broadcast.h"
|
||||||
#include "tcp_cmd.h"
|
#include "tcp_cmd.h"
|
||||||
|
#include "website_backend.h"
|
||||||
|
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@
|
|||||||
|
|
||||||
/* Private define ------------------------------------------------------------*/
|
/* Private define ------------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN PD */
|
/* USER CODE BEGIN PD */
|
||||||
static const char *TAG = "main";
|
static const char* TAG = "main";
|
||||||
/* USER CODE END PD */
|
/* USER CODE END PD */
|
||||||
|
|
||||||
/* Private macro -------------------------------------------------------------*/
|
/* Private macro -------------------------------------------------------------*/
|
||||||
@@ -85,453 +86,433 @@ static void MX_QUADSPI_Init(void);
|
|||||||
/* USER CODE END 0 */
|
/* USER CODE END 0 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The application entry point.
|
* @brief The application entry point.
|
||||||
* @retval int
|
* @retval int
|
||||||
*/
|
*/
|
||||||
int main(void)
|
int main(void) {
|
||||||
{
|
/* USER CODE BEGIN 1 */
|
||||||
/* USER CODE BEGIN 1 */
|
|
||||||
|
|
||||||
/* USER CODE END 1 */
|
/* USER CODE END 1 */
|
||||||
|
|
||||||
/* MCU Configuration--------------------------------------------------------*/
|
/* MCU Configuration--------------------------------------------------------*/
|
||||||
|
|
||||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||||||
HAL_Init();
|
HAL_Init();
|
||||||
|
|
||||||
/* USER CODE BEGIN Init */
|
/* USER CODE BEGIN Init */
|
||||||
|
|
||||||
/* USER CODE END Init */
|
/* USER CODE END Init */
|
||||||
|
|
||||||
/* Configure the system clock */
|
/* Configure the system clock */
|
||||||
SystemClock_Config();
|
SystemClock_Config();
|
||||||
|
|
||||||
/* USER CODE BEGIN SysInit */
|
/* USER CODE BEGIN SysInit */
|
||||||
|
|
||||||
/* USER CODE END SysInit */
|
/* USER CODE END SysInit */
|
||||||
|
|
||||||
/* Initialize all configured peripherals */
|
/* Initialize all configured peripherals */
|
||||||
MX_GPIO_Init();
|
MX_GPIO_Init();
|
||||||
MX_LTDC_Init();
|
MX_LTDC_Init();
|
||||||
MX_USART1_UART_Init();
|
MX_USART1_UART_Init();
|
||||||
MX_DMA2D_Init();
|
MX_DMA2D_Init();
|
||||||
MX_FMC_Init();
|
MX_FMC_Init();
|
||||||
MX_LWIP_Init();
|
MX_LWIP_Init();
|
||||||
MX_QUADSPI_Init();
|
MX_QUADSPI_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
|
|
||||||
/* Initialize QSPI */
|
|
||||||
BSP_QSPI_Init();
|
|
||||||
BSP_QSPI_MemoryMappedMode();
|
|
||||||
WRITE_REG(QUADSPI->LPTR, 0xFFF);
|
|
||||||
|
|
||||||
/* Clear terminal */
|
|
||||||
printf(CLEAR_SCREEN);
|
|
||||||
|
|
||||||
/* Initialize the LCD */
|
|
||||||
lcd_init(true);
|
|
||||||
|
|
||||||
/* Initialize the filesystem */
|
|
||||||
llfs_init();
|
|
||||||
|
|
||||||
/* Initialize the tftp server */
|
|
||||||
tftp_server_init();
|
|
||||||
|
|
||||||
/* Initialize tcp command interface*/
|
|
||||||
tcp_cmd_init();
|
|
||||||
|
|
||||||
/* Initialize Modbus*/
|
|
||||||
modbus_init();
|
|
||||||
|
|
||||||
/* Initialize the MQTT application */
|
|
||||||
mqtt_application_init();
|
|
||||||
|
|
||||||
// Initialize the UDP broadcast service
|
|
||||||
|
|
||||||
if (udp_broadcast_init(10,255) != ERR_OK){
|
|
||||||
LOG_WARN(TAG,"error initializing udp connection, check warnings from udp_broadcast_init() or udp_broadcast_connection_init()");
|
|
||||||
}
|
|
||||||
if (udp_broadcast_set_owner_details("Joran", "Van Nieuwenhoven") != ERR_OK){
|
|
||||||
LOG_WARN(TAG,"error setting owner's details");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Infinite loop */
|
/* Clear terminal */
|
||||||
/* USER CODE BEGIN WHILE */
|
printf(CLEAR_SCREEN);
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
/* USER CODE END WHILE */
|
|
||||||
|
|
||||||
/* USER CODE BEGIN 3 */
|
/* Initialize the LCD */
|
||||||
MX_LWIP_Process();
|
lcd_init(true);
|
||||||
lcd_task();
|
|
||||||
}
|
/* Initialize the filesystem */
|
||||||
/* USER CODE END 3 */
|
llfs_init();
|
||||||
|
tcp_cmd_init();
|
||||||
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
|
/* Initialize the tftp server */
|
||||||
|
tftp_server_init();
|
||||||
|
|
||||||
|
/* Initialize tcp command interface*/
|
||||||
|
tcp_cmd_init();
|
||||||
|
|
||||||
|
/* Initialize Modbus*/
|
||||||
|
modbus_init();
|
||||||
|
|
||||||
|
/* Initialize the MQTT application */
|
||||||
|
mqtt_application_init();
|
||||||
|
|
||||||
|
// Initialize the UDP broadcast service
|
||||||
|
|
||||||
|
if (udp_broadcast_init(10, 255) != ERR_OK) {
|
||||||
|
LOG_WARN(TAG, "error initializing udp connection, check warnings from udp_broadcast_init() or "
|
||||||
|
"udp_broadcast_connection_init()");
|
||||||
|
}
|
||||||
|
if (udp_broadcast_set_owner_details("Joran", "Van Nieuwenhoven") != ERR_OK) {
|
||||||
|
LOG_WARN(TAG, "error setting owner's details");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize website backend */
|
||||||
|
wbe_init();
|
||||||
|
|
||||||
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
|
/* Infinite loop */
|
||||||
|
/* USER CODE BEGIN WHILE */
|
||||||
|
while (1) {
|
||||||
|
/* USER CODE END WHILE */
|
||||||
|
|
||||||
|
/* USER CODE BEGIN 3 */
|
||||||
|
MX_LWIP_Process();
|
||||||
|
lcd_task();
|
||||||
|
}
|
||||||
|
/* USER CODE END 3 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief System Clock Configuration
|
* @brief System Clock Configuration
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void SystemClock_Config(void)
|
void SystemClock_Config(void) {
|
||||||
{
|
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
||||||
|
|
||||||
/** Configure LSE Drive Capability
|
/** Configure LSE Drive Capability
|
||||||
*/
|
*/
|
||||||
HAL_PWR_EnableBkUpAccess();
|
HAL_PWR_EnableBkUpAccess();
|
||||||
|
|
||||||
/** Configure the main internal regulator output voltage
|
/** Configure the main internal regulator output voltage
|
||||||
*/
|
*/
|
||||||
__HAL_RCC_PWR_CLK_ENABLE();
|
__HAL_RCC_PWR_CLK_ENABLE();
|
||||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||||
|
|
||||||
/** Initializes the RCC Oscillators according to the specified parameters
|
/** Initializes the RCC Oscillators according to the specified parameters
|
||||||
* in the RCC_OscInitTypeDef structure.
|
* in the RCC_OscInitTypeDef structure.
|
||||||
*/
|
*/
|
||||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||||
RCC_OscInitStruct.PLL.PLLM = 25;
|
RCC_OscInitStruct.PLL.PLLM = 25;
|
||||||
RCC_OscInitStruct.PLL.PLLN = 400;
|
RCC_OscInitStruct.PLL.PLLN = 400;
|
||||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||||
RCC_OscInitStruct.PLL.PLLQ = 2;
|
RCC_OscInitStruct.PLL.PLLQ = 2;
|
||||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Activate the Over-Drive mode
|
/** Activate the Over-Drive mode
|
||||||
*/
|
*/
|
||||||
if (HAL_PWREx_EnableOverDrive() != HAL_OK)
|
if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Initializes the CPU, AHB and APB buses clocks
|
/** Initializes the CPU, AHB and APB buses clocks
|
||||||
*/
|
*/
|
||||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|
||||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
|
||||||
|
|
||||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK)
|
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief DMA2D Initialization Function
|
* @brief DMA2D Initialization Function
|
||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_DMA2D_Init(void)
|
static void MX_DMA2D_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN DMA2D_Init 0 */
|
/* USER CODE BEGIN DMA2D_Init 0 */
|
||||||
|
|
||||||
/* USER CODE END DMA2D_Init 0 */
|
/* USER CODE END DMA2D_Init 0 */
|
||||||
|
|
||||||
/* USER CODE BEGIN DMA2D_Init 1 */
|
/* USER CODE BEGIN DMA2D_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END DMA2D_Init 1 */
|
/* USER CODE END DMA2D_Init 1 */
|
||||||
hdma2d.Instance = DMA2D;
|
hdma2d.Instance = DMA2D;
|
||||||
hdma2d.Init.Mode = DMA2D_M2M;
|
hdma2d.Init.Mode = DMA2D_M2M;
|
||||||
hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||||
hdma2d.Init.OutputOffset = 0;
|
hdma2d.Init.OutputOffset = 0;
|
||||||
hdma2d.LayerCfg[1].InputOffset = 0;
|
hdma2d.LayerCfg[1].InputOffset = 0;
|
||||||
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
|
||||||
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
||||||
hdma2d.LayerCfg[1].InputAlpha = 0;
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
||||||
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
|
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) {
|
||||||
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK)
|
Error_Handler();
|
||||||
{
|
}
|
||||||
Error_Handler();
|
/* USER CODE BEGIN DMA2D_Init 2 */
|
||||||
}
|
|
||||||
/* USER CODE BEGIN DMA2D_Init 2 */
|
|
||||||
|
|
||||||
/* USER CODE END DMA2D_Init 2 */
|
/* USER CODE END DMA2D_Init 2 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief LTDC Initialization Function
|
* @brief LTDC Initialization Function
|
||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_LTDC_Init(void)
|
static void MX_LTDC_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN LTDC_Init 0 */
|
/* USER CODE BEGIN LTDC_Init 0 */
|
||||||
|
|
||||||
/* USER CODE END LTDC_Init 0 */
|
/* USER CODE END LTDC_Init 0 */
|
||||||
|
|
||||||
LTDC_LayerCfgTypeDef pLayerCfg = {0};
|
LTDC_LayerCfgTypeDef pLayerCfg = {0};
|
||||||
LTDC_LayerCfgTypeDef pLayerCfg1 = {0};
|
LTDC_LayerCfgTypeDef pLayerCfg1 = {0};
|
||||||
|
|
||||||
/* USER CODE BEGIN LTDC_Init 1 */
|
/* USER CODE BEGIN LTDC_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END LTDC_Init 1 */
|
/* USER CODE END LTDC_Init 1 */
|
||||||
hltdc.Instance = LTDC;
|
hltdc.Instance = LTDC;
|
||||||
hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
|
hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
|
||||||
hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
|
hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
|
||||||
hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
|
hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
|
||||||
hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
|
hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
|
||||||
hltdc.Init.HorizontalSync = 40;
|
hltdc.Init.HorizontalSync = 40;
|
||||||
hltdc.Init.VerticalSync = 9;
|
hltdc.Init.VerticalSync = 9;
|
||||||
hltdc.Init.AccumulatedHBP = 53;
|
hltdc.Init.AccumulatedHBP = 53;
|
||||||
hltdc.Init.AccumulatedVBP = 11;
|
hltdc.Init.AccumulatedVBP = 11;
|
||||||
hltdc.Init.AccumulatedActiveW = 533;
|
hltdc.Init.AccumulatedActiveW = 533;
|
||||||
hltdc.Init.AccumulatedActiveH = 283;
|
hltdc.Init.AccumulatedActiveH = 283;
|
||||||
hltdc.Init.TotalWidth = 565;
|
hltdc.Init.TotalWidth = 565;
|
||||||
hltdc.Init.TotalHeigh = 285;
|
hltdc.Init.TotalHeigh = 285;
|
||||||
hltdc.Init.Backcolor.Blue = 0;
|
hltdc.Init.Backcolor.Blue = 0;
|
||||||
hltdc.Init.Backcolor.Green = 255;
|
hltdc.Init.Backcolor.Green = 255;
|
||||||
hltdc.Init.Backcolor.Red = 0;
|
hltdc.Init.Backcolor.Red = 0;
|
||||||
if (HAL_LTDC_Init(&hltdc) != HAL_OK)
|
if (HAL_LTDC_Init(&hltdc) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
pLayerCfg.WindowX0 = 0;
|
||||||
pLayerCfg.WindowX0 = 0;
|
pLayerCfg.WindowX1 = 480;
|
||||||
pLayerCfg.WindowX1 = 480;
|
pLayerCfg.WindowY0 = 0;
|
||||||
pLayerCfg.WindowY0 = 0;
|
pLayerCfg.WindowY1 = 272;
|
||||||
pLayerCfg.WindowY1 = 272;
|
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB1555;
|
||||||
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB1555;
|
pLayerCfg.Alpha = 255;
|
||||||
pLayerCfg.Alpha = 255;
|
pLayerCfg.Alpha0 = 0;
|
||||||
pLayerCfg.Alpha0 = 0;
|
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
|
||||||
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
|
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
|
||||||
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
|
pLayerCfg.FBStartAdress = 0;
|
||||||
pLayerCfg.FBStartAdress = 0;
|
pLayerCfg.ImageWidth = 480;
|
||||||
pLayerCfg.ImageWidth = 480;
|
pLayerCfg.ImageHeight = 272;
|
||||||
pLayerCfg.ImageHeight = 272;
|
pLayerCfg.Backcolor.Blue = 0;
|
||||||
pLayerCfg.Backcolor.Blue = 0;
|
pLayerCfg.Backcolor.Green = 0;
|
||||||
pLayerCfg.Backcolor.Green = 0;
|
pLayerCfg.Backcolor.Red = 0;
|
||||||
pLayerCfg.Backcolor.Red = 0;
|
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) {
|
||||||
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
|
Error_Handler();
|
||||||
{
|
}
|
||||||
Error_Handler();
|
pLayerCfg1.WindowX0 = 0;
|
||||||
}
|
pLayerCfg1.WindowX1 = 480;
|
||||||
pLayerCfg1.WindowX0 = 0;
|
pLayerCfg1.WindowY0 = 0;
|
||||||
pLayerCfg1.WindowX1 = 480;
|
pLayerCfg1.WindowY1 = 272;
|
||||||
pLayerCfg1.WindowY0 = 0;
|
pLayerCfg1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB1555;
|
||||||
pLayerCfg1.WindowY1 = 272;
|
pLayerCfg1.Alpha = 255;
|
||||||
pLayerCfg1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB1555;
|
pLayerCfg1.Alpha0 = 0;
|
||||||
pLayerCfg1.Alpha = 255;
|
pLayerCfg1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
|
||||||
pLayerCfg1.Alpha0 = 0;
|
pLayerCfg1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
|
||||||
pLayerCfg1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
|
pLayerCfg1.FBStartAdress = 0;
|
||||||
pLayerCfg1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
|
pLayerCfg1.ImageWidth = 480;
|
||||||
pLayerCfg1.FBStartAdress = 0;
|
pLayerCfg1.ImageHeight = 272;
|
||||||
pLayerCfg1.ImageWidth = 480;
|
pLayerCfg1.Backcolor.Blue = 0;
|
||||||
pLayerCfg1.ImageHeight = 272;
|
pLayerCfg1.Backcolor.Green = 0;
|
||||||
pLayerCfg1.Backcolor.Blue = 0;
|
pLayerCfg1.Backcolor.Red = 0;
|
||||||
pLayerCfg1.Backcolor.Green = 0;
|
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg1, 1) != HAL_OK) {
|
||||||
pLayerCfg1.Backcolor.Red = 0;
|
Error_Handler();
|
||||||
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg1, 1) != HAL_OK)
|
}
|
||||||
{
|
/* USER CODE BEGIN LTDC_Init 2 */
|
||||||
Error_Handler();
|
|
||||||
}
|
|
||||||
/* USER CODE BEGIN LTDC_Init 2 */
|
|
||||||
|
|
||||||
/* USER CODE END LTDC_Init 2 */
|
/* USER CODE END LTDC_Init 2 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief QUADSPI Initialization Function
|
* @brief QUADSPI Initialization Function
|
||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_QUADSPI_Init(void)
|
static void MX_QUADSPI_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN QUADSPI_Init 0 */
|
/* USER CODE BEGIN QUADSPI_Init 0 */
|
||||||
|
|
||||||
/* USER CODE END QUADSPI_Init 0 */
|
/* USER CODE END QUADSPI_Init 0 */
|
||||||
|
|
||||||
/* USER CODE BEGIN QUADSPI_Init 1 */
|
/* USER CODE BEGIN QUADSPI_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END QUADSPI_Init 1 */
|
/* USER CODE END QUADSPI_Init 1 */
|
||||||
/* QUADSPI parameter configuration*/
|
/* QUADSPI parameter configuration*/
|
||||||
hqspi.Instance = QUADSPI;
|
hqspi.Instance = QUADSPI;
|
||||||
hqspi.Init.ClockPrescaler = 1;
|
hqspi.Init.ClockPrescaler = 1;
|
||||||
hqspi.Init.FifoThreshold = 4;
|
hqspi.Init.FifoThreshold = 4;
|
||||||
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
|
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
|
||||||
hqspi.Init.FlashSize = 16;
|
hqspi.Init.FlashSize = 16;
|
||||||
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
|
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
|
||||||
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
|
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
|
||||||
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
|
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
|
||||||
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
|
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
|
||||||
if (HAL_QSPI_Init(&hqspi) != HAL_OK)
|
if (HAL_QSPI_Init(&hqspi) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
/* USER CODE BEGIN QUADSPI_Init 2 */
|
||||||
/* USER CODE BEGIN QUADSPI_Init 2 */
|
|
||||||
|
|
||||||
/* USER CODE END QUADSPI_Init 2 */
|
/* USER CODE END QUADSPI_Init 2 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USART1 Initialization Function
|
* @brief USART1 Initialization Function
|
||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_USART1_UART_Init(void)
|
static void MX_USART1_UART_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN USART1_Init 0 */
|
/* USER CODE BEGIN USART1_Init 0 */
|
||||||
|
|
||||||
/* USER CODE END USART1_Init 0 */
|
/* USER CODE END USART1_Init 0 */
|
||||||
|
|
||||||
/* USER CODE BEGIN USART1_Init 1 */
|
/* USER CODE BEGIN USART1_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END USART1_Init 1 */
|
/* USER CODE END USART1_Init 1 */
|
||||||
huart1.Instance = USART1;
|
huart1.Instance = USART1;
|
||||||
huart1.Init.BaudRate = 115200;
|
huart1.Init.BaudRate = 115200;
|
||||||
huart1.Init.WordLength = UART_WORDLENGTH_8B;
|
huart1.Init.WordLength = UART_WORDLENGTH_8B;
|
||||||
huart1.Init.StopBits = UART_STOPBITS_1;
|
huart1.Init.StopBits = UART_STOPBITS_1;
|
||||||
huart1.Init.Parity = UART_PARITY_NONE;
|
huart1.Init.Parity = UART_PARITY_NONE;
|
||||||
huart1.Init.Mode = UART_MODE_TX_RX;
|
huart1.Init.Mode = UART_MODE_TX_RX;
|
||||||
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||||
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
|
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||||
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
|
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
|
||||||
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
|
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
|
||||||
if (HAL_UART_Init(&huart1) != HAL_OK)
|
if (HAL_UART_Init(&huart1) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler();
|
}
|
||||||
}
|
/* USER CODE BEGIN USART1_Init 2 */
|
||||||
/* USER CODE BEGIN USART1_Init 2 */
|
|
||||||
|
|
||||||
/* USER CODE END USART1_Init 2 */
|
/* USER CODE END USART1_Init 2 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FMC initialization function */
|
/* FMC initialization function */
|
||||||
static void MX_FMC_Init(void)
|
static void MX_FMC_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN FMC_Init 0 */
|
/* USER CODE BEGIN FMC_Init 0 */
|
||||||
|
|
||||||
/* USER CODE END FMC_Init 0 */
|
/* USER CODE END FMC_Init 0 */
|
||||||
|
|
||||||
FMC_SDRAM_TimingTypeDef SdramTiming = {0};
|
FMC_SDRAM_TimingTypeDef SdramTiming = {0};
|
||||||
|
|
||||||
/* USER CODE BEGIN FMC_Init 1 */
|
/* USER CODE BEGIN FMC_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END FMC_Init 1 */
|
/* USER CODE END FMC_Init 1 */
|
||||||
|
|
||||||
/** Perform the SDRAM1 memory initialization sequence
|
/** Perform the SDRAM1 memory initialization sequence
|
||||||
*/
|
*/
|
||||||
hsdram1.Instance = FMC_SDRAM_DEVICE;
|
hsdram1.Instance = FMC_SDRAM_DEVICE;
|
||||||
/* hsdram1.Init */
|
/* hsdram1.Init */
|
||||||
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
|
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
|
||||||
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
|
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
|
||||||
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
|
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
|
||||||
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
|
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
|
||||||
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
|
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
|
||||||
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_1;
|
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_1;
|
||||||
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
|
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
|
||||||
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_DISABLE;
|
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_DISABLE;
|
||||||
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
|
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
|
||||||
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
|
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
|
||||||
/* SdramTiming */
|
/* SdramTiming */
|
||||||
SdramTiming.LoadToActiveDelay = 16;
|
SdramTiming.LoadToActiveDelay = 16;
|
||||||
SdramTiming.ExitSelfRefreshDelay = 16;
|
SdramTiming.ExitSelfRefreshDelay = 16;
|
||||||
SdramTiming.SelfRefreshTime = 16;
|
SdramTiming.SelfRefreshTime = 16;
|
||||||
SdramTiming.RowCycleDelay = 16;
|
SdramTiming.RowCycleDelay = 16;
|
||||||
SdramTiming.WriteRecoveryTime = 16;
|
SdramTiming.WriteRecoveryTime = 16;
|
||||||
SdramTiming.RPDelay = 16;
|
SdramTiming.RPDelay = 16;
|
||||||
SdramTiming.RCDDelay = 16;
|
SdramTiming.RCDDelay = 16;
|
||||||
|
|
||||||
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
|
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK) {
|
||||||
{
|
Error_Handler();
|
||||||
Error_Handler( );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* USER CODE BEGIN FMC_Init 2 */
|
/* USER CODE BEGIN FMC_Init 2 */
|
||||||
|
|
||||||
/* USER CODE END FMC_Init 2 */
|
/* USER CODE END FMC_Init 2 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief GPIO Initialization Function
|
* @brief GPIO Initialization Function
|
||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_GPIO_Init(void)
|
static void MX_GPIO_Init(void) {
|
||||||
{
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
/* USER CODE END MX_GPIO_Init_1 */
|
||||||
/* USER CODE END MX_GPIO_Init_1 */
|
|
||||||
|
|
||||||
/* GPIO Ports Clock Enable */
|
/* GPIO Ports Clock Enable */
|
||||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOJ_CLK_ENABLE();
|
__HAL_RCC_GPIOJ_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOK_CLK_ENABLE();
|
__HAL_RCC_GPIOK_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOI_CLK_ENABLE();
|
__HAL_RCC_GPIOI_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||||
|
|
||||||
/*Configure GPIO pin Output Level */
|
/*Configure GPIO pin Output Level */
|
||||||
HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_Port, LCD_BL_CTRL_Pin, GPIO_PIN_RESET);
|
HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_Port, LCD_BL_CTRL_Pin, GPIO_PIN_RESET);
|
||||||
|
|
||||||
/*Configure GPIO pin Output Level */
|
/*Configure GPIO pin Output Level */
|
||||||
HAL_GPIO_WritePin(GPIOI, LED_Pin|LCD_DISP_Pin, GPIO_PIN_RESET);
|
HAL_GPIO_WritePin(GPIOI, LED_Pin | LCD_DISP_Pin, GPIO_PIN_RESET);
|
||||||
|
|
||||||
/*Configure GPIO pin : LCD_BL_CTRL_Pin */
|
/*Configure GPIO pin : LCD_BL_CTRL_Pin */
|
||||||
GPIO_InitStruct.Pin = LCD_BL_CTRL_Pin;
|
GPIO_InitStruct.Pin = LCD_BL_CTRL_Pin;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
HAL_GPIO_Init(LCD_BL_CTRL_GPIO_Port, &GPIO_InitStruct);
|
HAL_GPIO_Init(LCD_BL_CTRL_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pins : LED_Pin LCD_DISP_Pin */
|
/*Configure GPIO pins : LED_Pin LCD_DISP_Pin */
|
||||||
GPIO_InitStruct.Pin = LED_Pin|LCD_DISP_Pin;
|
GPIO_InitStruct.Pin = LED_Pin | LCD_DISP_Pin;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pin : BUTTON_Pin */
|
/*Configure GPIO pin : BUTTON_Pin */
|
||||||
GPIO_InitStruct.Pin = BUTTON_Pin;
|
GPIO_InitStruct.Pin = BUTTON_Pin;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
HAL_GPIO_Init(BUTTON_GPIO_Port, &GPIO_InitStruct);
|
HAL_GPIO_Init(BUTTON_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
||||||
/* USER CODE END MX_GPIO_Init_2 */
|
/* USER CODE END MX_GPIO_Init_2 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE BEGIN 4 */
|
/* USER CODE BEGIN 4 */
|
||||||
/* USER CODE END 4 */
|
/* USER CODE END 4 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function is executed in case of error occurrence.
|
* @brief This function is executed in case of error occurrence.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void Error_Handler(void)
|
void Error_Handler(void) {
|
||||||
{
|
/* USER CODE BEGIN Error_Handler_Debug */
|
||||||
/* USER CODE BEGIN Error_Handler_Debug */
|
/* User can add his own implementation to report the HAL error return state */
|
||||||
/* User can add his own implementation to report the HAL error return state */
|
__disable_irq();
|
||||||
__disable_irq();
|
while (1) {
|
||||||
while (1)
|
}
|
||||||
{
|
/* USER CODE END Error_Handler_Debug */
|
||||||
}
|
|
||||||
/* USER CODE END Error_Handler_Debug */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_FULL_ASSERT
|
#ifdef USE_FULL_ASSERT
|
||||||
|
|||||||
@@ -17,24 +17,18 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#define ATTEMPT_RECONNECT_AMOUNT 50
|
#define ATTEMPT_RECONNECT_AMOUNT 50
|
||||||
#define PUBLISH_QOS 2
|
#define PUBLISH_QOS 2
|
||||||
#define PUBLISH_RETAIN 1
|
#define PUBLISH_RETAIN 1
|
||||||
#define PRINT_XPOS 50
|
#define PRINT_XPOS 50
|
||||||
#define PRINT_YPOS 50
|
#define PRINT_YPOS 50
|
||||||
#define MAX_FILES 20
|
#define MAX_FILES 20
|
||||||
#define SERVER_IP4_A 192
|
#define SERVER_IP4_A 192
|
||||||
#define SERVER_IP4_B 168
|
#define SERVER_IP4_B 168
|
||||||
#define SERVER_IP4_C 69
|
#define SERVER_IP4_C 69
|
||||||
#define SERVER_IP4_D 11
|
#define SERVER_IP4_D 11
|
||||||
#define SERVER_PORT 1883
|
#define SERVER_PORT 1883
|
||||||
|
|
||||||
typedef enum input_topic {
|
typedef enum input_topic { set_text, set_text_color, set_color, set_image, other_topic } input_topic_t;
|
||||||
set_text,
|
|
||||||
set_text_color,
|
|
||||||
set_color,
|
|
||||||
set_image,
|
|
||||||
other_topic
|
|
||||||
} input_topic_t;
|
|
||||||
|
|
||||||
// Function prototypes
|
// Function prototypes
|
||||||
static void mqtt_pub_request_cb(void*, err_t);
|
static void mqtt_pub_request_cb(void*, err_t);
|
||||||
@@ -47,7 +41,8 @@ static void mosquitto_connect(mqtt_client_t*);
|
|||||||
static uint32_t color_picker(char*);
|
static uint32_t color_picker(char*);
|
||||||
static void create_publish_string(char*, char*, size_t);
|
static void create_publish_string(char*, char*, size_t);
|
||||||
|
|
||||||
// Global variables used in mqtt_incoming_publish_cb and mqtt_incoming_data_cb to give an easy to use ID to the subscribed topics
|
// Global variables used in mqtt_incoming_publish_cb and mqtt_incoming_data_cb to give an easy to use ID to the
|
||||||
|
// subscribed topics
|
||||||
static sFONT* font;
|
static sFONT* font;
|
||||||
static uint16_t xpos;
|
static uint16_t xpos;
|
||||||
static uint16_t ypos;
|
static uint16_t ypos;
|
||||||
@@ -80,9 +75,10 @@ static void publish_data(mqtt_client_t* client, void* arg) {
|
|||||||
|
|
||||||
LOG_DEBUG(TAG, "Entering publish");
|
LOG_DEBUG(TAG, "Entering publish");
|
||||||
|
|
||||||
create_publish_string("*.bmp", pub_payload,sizeof(pub_payload));
|
create_publish_string("*.bmp", pub_payload, sizeof(pub_payload));
|
||||||
|
|
||||||
err = mqtt_publish(client, "getImageList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN, mqtt_pub_request_cb, arg);
|
err = mqtt_publish(client, "getImageList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN,
|
||||||
|
mqtt_pub_request_cb, arg);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
LOG_DEBUG(TAG, "Publish err: %d", err);
|
LOG_DEBUG(TAG, "Publish err: %d", err);
|
||||||
}
|
}
|
||||||
@@ -90,7 +86,8 @@ static void publish_data(mqtt_client_t* client, void* arg) {
|
|||||||
pub_payload[0] = '\0';
|
pub_payload[0] = '\0';
|
||||||
create_publish_string("*.gif", pub_payload, sizeof(pub_payload));
|
create_publish_string("*.gif", pub_payload, sizeof(pub_payload));
|
||||||
|
|
||||||
err = mqtt_publish(client, "getGifList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN, mqtt_pub_request_cb, arg);
|
err = mqtt_publish(client, "getGifList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN,
|
||||||
|
mqtt_pub_request_cb, arg);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
LOG_DEBUG(TAG, "Publish err: %d", err);
|
LOG_DEBUG(TAG, "Publish err: %d", err);
|
||||||
}
|
}
|
||||||
@@ -142,8 +139,8 @@ static void mqtt_incoming_data_cb(void* arg, const uint8_t* data, uint16_t len,
|
|||||||
|
|
||||||
LOG_INFO(TAG, "Incoming publish payload with length %d, flags %d", len, flags);
|
LOG_INFO(TAG, "Incoming publish payload with length %d, flags %d", len, flags);
|
||||||
if (!(flags & MQTT_DATA_FLAG_LAST)) {
|
if (!(flags & MQTT_DATA_FLAG_LAST)) {
|
||||||
LOG_WARN(TAG, "incoming data too big to fit in buffer.");
|
LOG_WARN(TAG, "incoming data too big to fit in buffer.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(data_buffer, data, len);
|
memcpy(data_buffer, data, len);
|
||||||
data_buffer[len] = '\0';
|
data_buffer[len] = '\0';
|
||||||
|
|||||||
@@ -1,182 +1,592 @@
|
|||||||
/**
|
/**
|
||||||
* @file tcp_cmd.c
|
* @file tcp_cmd.c
|
||||||
* @brief TCP CMD interface
|
* @brief This file contains the implementation of the tcp command interface
|
||||||
* @author Gert R.
|
* @author Sander S.
|
||||||
*/
|
*/
|
||||||
#include "tcp_cmd.h"
|
#include "tcp_cmd.h"
|
||||||
|
|
||||||
static uint32_t result_txt = 0xff000000; // Store text color
|
#define MAX_TOKENS 10
|
||||||
static uint32_t result_bg = 0xff000000; // Store background color
|
#define MAX_CMD_LEN 50
|
||||||
|
|
||||||
static void tcp_cmd_close(struct tcp_pcb* pcb) {
|
#define NCAT
|
||||||
tcp_arg(pcb, NULL);
|
|
||||||
tcp_sent(pcb, NULL);
|
static const char* TAG = "tcp_cmd";
|
||||||
tcp_recv(pcb, NULL);
|
static uint32_t color_txt = 0xffffffff; // Store text color
|
||||||
tcp_close(pcb);
|
static uint32_t color_bg = 0xff000000; // Store background color
|
||||||
|
|
||||||
|
static void tcp_cmd_write(struct tcp_pcb* pcb, const char* str);
|
||||||
|
static void tcp_cmd_print_header(struct tcp_pcb* pcb);
|
||||||
|
static void tcp_cmd_print_help(struct tcp_pcb* pcb);
|
||||||
|
static void tcp_cmd_clear(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_text(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_bg_color(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_color(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_list_files(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_set_image(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_set_gif(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_exit(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static void tcp_cmd_unknown_cmd(struct tcp_pcb* pcb, char* cmd);
|
||||||
|
static bool tcp_cmd_parser(struct tcp_pcb* pcb, int argc, char** argv);
|
||||||
|
static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err);
|
||||||
|
static void tcp_cmd_close(struct tcp_pcb* pcb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function shifts the arguments in argv and argc
|
||||||
|
* @param[in,out] argc The argc pointer
|
||||||
|
* @param[in,out] argv The argv pointer
|
||||||
|
* @return The shifted argument
|
||||||
|
*/
|
||||||
|
static char* shift_args(int* argc, char*** argv) {
|
||||||
|
if (*argc == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
char* arg = (*argv)[0];
|
||||||
|
(*argv)++;
|
||||||
|
(*argc)--;
|
||||||
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) {
|
/**
|
||||||
size_t len;
|
* @brief This function converts a string to a color
|
||||||
size_t number_of_files;
|
* @param[in] argc The number of arguments
|
||||||
uint8_t file_in_fs;
|
* @param[in] argv The arguments
|
||||||
uint8_t check = 0;
|
* @param[out] color The color to write to
|
||||||
|
* @return true The conversion failed
|
||||||
|
* @return false The conversion succeeded
|
||||||
|
*/
|
||||||
|
static bool str_to_color(int argc, char** argv, uint32_t* color) {
|
||||||
|
if (argc == 1) {
|
||||||
|
*color = (uint32_t)strtoul(argv[0], NULL, 16);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (argc == 3) {
|
||||||
|
*color = 0xff000000;
|
||||||
|
*color |= (uint32_t)strtoul(argv[0], NULL, 10) << 16;
|
||||||
|
*color |= (uint32_t)strtoul(argv[1], NULL, 10) << 8;
|
||||||
|
*color |= (uint32_t)strtoul(argv[2], NULL, 10);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (argc == 4) {
|
||||||
|
*color = (uint32_t)strtoul(argv[0], NULL, 10) << 24;
|
||||||
|
*color |= (uint32_t)strtoul(argv[1], NULL, 10) << 16;
|
||||||
|
*color |= (uint32_t)strtoul(argv[2], NULL, 10) << 8;
|
||||||
|
*color |= (uint32_t)strtoul(argv[3], NULL, 10);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char* pc;
|
return true;
|
||||||
char tcp_buffer[1024];
|
}
|
||||||
char text[256];
|
|
||||||
char color_r[3];
|
|
||||||
char color_g[3];
|
|
||||||
char color_b[3];
|
|
||||||
|
|
||||||
char text_color_r[3];
|
/**
|
||||||
char text_color_g[3];
|
* @brief This function removes the newline from a string the string can contain multiple lines
|
||||||
char text_color_b[3];
|
* @param[in,out] str The string to remove the newline from
|
||||||
|
*/
|
||||||
char extension[4];
|
void tcp_cmd_remove_newline(char* str, size_t len) {
|
||||||
|
size_t i = 0;
|
||||||
char* endptr;
|
size_t j = 0;
|
||||||
|
while (str[i] != '\0' && j < len) {
|
||||||
|
if (str[j] != '\n' && str[j] != '\r') {
|
||||||
if (err == ERR_OK && p != NULL) {
|
str[i] = str[j];
|
||||||
tcp_recved(pcb, p->tot_len);
|
i++;
|
||||||
pc = (char*)p->payload;
|
|
||||||
len = p->tot_len;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
tcp_buffer[i] = pc[i];
|
|
||||||
}
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
str[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
if (!strncmp(tcp_buffer, "help", 4)) {
|
/**
|
||||||
check = 1;
|
* @brief This function 'removes' the leading spaces from a string
|
||||||
tcp_write(pcb, "help : laat lijst zien met alle commando's\r\n"
|
* @param[in] str The string to remove the leading spaces from
|
||||||
"text : geeft tekst mee die op LCD komt (uw_text)\r\n"
|
* @param[in] len The length of the string
|
||||||
"color : kleur achtergrond van scherm (255 255 255)\r\n"
|
* @return char* A pointer to the first non-space character
|
||||||
"textColor : kleur van tekst (255 255 255)\r\n"
|
*/
|
||||||
"listImages: laat een lijst zien van de mogelijke afbeeldingen\r\n"
|
char* tcp_cmd_remove_leading_space(char* str, size_t len) {
|
||||||
"setImage : veranderd te afbeelding (naam_afbeelding)\r\n"
|
size_t i = 0;
|
||||||
"exit : sluit de verbinding\r\n", 354, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
if (str == NULL || str[0] == '\0' || len == 0) {
|
||||||
} else if (!strncmp(tcp_buffer, "text ", 5)) {
|
return NULL;
|
||||||
size_t i;
|
}
|
||||||
for (i = 0; i < len - 4; i++) {
|
while (str[i] != '\0' && i < len) {
|
||||||
text[i] = tcp_buffer[i + 5];
|
if (isspace((int)str[i]) == 0) {
|
||||||
}
|
return &str[i];
|
||||||
text[i - 1] = '\0';
|
|
||||||
lcd_clear_text();
|
|
||||||
lcd_display_text(text, 10, 10, result_txt, result_bg, LCD_FONT24);
|
|
||||||
|
|
||||||
|
|
||||||
check = 1;
|
|
||||||
} else if (!strncmp(tcp_buffer, "color", 5)) {
|
|
||||||
for (size_t i = 0; i < 3; i++) {
|
|
||||||
color_r[i] = tcp_buffer[i + 6];
|
|
||||||
color_g[i] = tcp_buffer[i + 10];
|
|
||||||
color_b[i] = tcp_buffer[i + 14];
|
|
||||||
}
|
|
||||||
result_bg |= strtoul(color_r, &endptr, 10) << 16;
|
|
||||||
result_bg |= strtoul(color_g, &endptr, 10) << 8;
|
|
||||||
result_bg |= strtoul(color_b, &endptr, 10);
|
|
||||||
|
|
||||||
check = 1;
|
|
||||||
} else if (!strncmp(tcp_buffer, "textColor", 9)) {
|
|
||||||
for (size_t i = 0; i < 3; i++) {
|
|
||||||
text_color_r[i] = tcp_buffer[i + 10];
|
|
||||||
text_color_g[i] = tcp_buffer[i + 14];
|
|
||||||
text_color_b[i] = tcp_buffer[i + 18];
|
|
||||||
}
|
|
||||||
result_txt |= strtoul(text_color_r, &endptr, 10) << 16;
|
|
||||||
result_txt |= strtoul(text_color_g, &endptr, 10) << 8;
|
|
||||||
result_txt |= strtoul(text_color_b, &endptr, 10);
|
|
||||||
|
|
||||||
check = 1;
|
|
||||||
} else if (!strncmp(tcp_buffer, "listImages", 10)) {
|
|
||||||
number_of_files = llfs_file_count();
|
|
||||||
|
|
||||||
if (number_of_files > 0) {
|
|
||||||
llfs_file_t file_list[number_of_files];
|
|
||||||
number_of_files = llfs_file_list(file_list, number_of_files, NULL);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < number_of_files; i++) {
|
|
||||||
tcp_write(pcb, file_list[i].name, strlen(file_list[i].name), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
tcp_write(pcb, "\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tcp_write(pcb, "NO files in filesystem\r\n", 24, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
check = 1;
|
|
||||||
} else if (!strncmp(tcp_buffer, "setImage", 8)) {
|
|
||||||
char filename[len - 8];
|
|
||||||
for (size_t i = 0; i < len - 9; i++) {
|
|
||||||
filename[i] = tcp_buffer[i + 9];
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < 3; i++) {
|
|
||||||
extension[i] = tcp_buffer[i + len - 3];
|
|
||||||
}
|
|
||||||
filename[sizeof(filename) - 1] = '\0';
|
|
||||||
extension[3] = '\0';
|
|
||||||
|
|
||||||
number_of_files = llfs_file_count();
|
|
||||||
|
|
||||||
if(number_of_files > 0) {
|
|
||||||
llfs_file_t file_list[number_of_files];
|
|
||||||
|
|
||||||
number_of_files = llfs_file_list(file_list, number_of_files, NULL);
|
|
||||||
|
|
||||||
file_in_fs = 0;
|
|
||||||
for (size_t i = 0; i < number_of_files; i++) {
|
|
||||||
if (!strcmp(filename, file_list[i].name)) {
|
|
||||||
file_in_fs = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check which file extension is used and call right function
|
|
||||||
if (!strncmp(extension, "bmp", 3) && file_in_fs) {
|
|
||||||
lcd_clear_images();
|
|
||||||
lcd_draw_img_from_fs(filename, 10, 10);
|
|
||||||
} else if (!strncmp(extension, "gif", 3) && file_in_fs) {
|
|
||||||
lcd_clear_images();
|
|
||||||
lcd_draw_gif_from_fs(filename, 10, 10);
|
|
||||||
} else if (!file_in_fs) {
|
|
||||||
tcp_write(pcb, "File NOT in filesystem\n\r", 24, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
} else {
|
|
||||||
tcp_write(pcb, "Extension NOT supported\n\r", 25, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tcp_write(pcb, "NO files in filesystem\r\n", 24, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
check = 1;
|
|
||||||
} else if (!strncmp(tcp_buffer, "exit", 4)) {
|
|
||||||
lcd_clear_images();
|
|
||||||
lcd_clear_text();
|
|
||||||
tcp_cmd_close(pcb);
|
|
||||||
check = 1;
|
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!check && (strncmp(tcp_buffer, "\r\n", 2) != 0)) {
|
/**
|
||||||
tcp_write(pcb, "Onbestaand commando: help voor lijst van commando's\r\n", 53, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
* @brief This function converts a string to lowercase
|
||||||
|
* @param[in,out] str The string to convert
|
||||||
|
*/
|
||||||
|
void tcp_cmd_str_tolower(char* str) {
|
||||||
|
int i = 0;
|
||||||
|
while (str[i] != '\0') {
|
||||||
|
str[i] = (char)tolower((int)str[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function finds the next token in the input string
|
||||||
|
* If the token is between quotes, return the whole string between quotes
|
||||||
|
* @param[in] input The input string
|
||||||
|
* @param[in] delimiter The delimiters to use
|
||||||
|
* @param[in,out] next The next token
|
||||||
|
* @return char* The next token
|
||||||
|
*/
|
||||||
|
char* tcp_cmd_get_next_token(char* input, const char* delimiters, char** next) {
|
||||||
|
if (input == NULL && *next == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (input == NULL) {
|
||||||
|
input = *next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip leading delimiters
|
||||||
|
input += strspn(input, delimiters);
|
||||||
|
if (*input == '\0') {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the token is between quotes, return the whole string between quotes
|
||||||
|
if (*input == '"') {
|
||||||
|
char* end = strchr(++input, '"');
|
||||||
|
if (end == NULL) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
*end = '\0';
|
||||||
|
*next = end + 1;
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
pbuf_free(p);
|
// Find the end of the token
|
||||||
|
char* end = input + strcspn(input, delimiters);
|
||||||
if (len > tcp_sndbuf(pcb)) {
|
if (*end == '\0') {
|
||||||
len = tcp_sndbuf(pcb);
|
*next = end;
|
||||||
}
|
|
||||||
tcp_sent(pcb, NULL);
|
|
||||||
} else {
|
} else {
|
||||||
pbuf_free(p);
|
*end = '\0';
|
||||||
|
*next = end + 1;
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function is a wrapper for tcp_write and tcp_output
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] str The string to write
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_write(struct tcp_pcb* pcb, const char* str) {
|
||||||
|
tcp_write(pcb, str, strlen(str), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
||||||
|
tcp_output(pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function prints the header of the tcp command interface
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_print_header(struct tcp_pcb* pcb) {
|
||||||
|
tcp_cmd_write(pcb, " Welcome to the TCP CMD interface\n"
|
||||||
|
"(Type help for a list of the commands! exit to close)\n"
|
||||||
|
"============================================================\n"
|
||||||
|
"$>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function prints the help text
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_print_help(struct tcp_pcb* pcb) {
|
||||||
|
LOG_INFO(TAG, "Printing help");
|
||||||
|
tcp_cmd_write(pcb, "help : shows a list of commands\n"
|
||||||
|
"clear text/images : clears the text or images on the lcd\n"
|
||||||
|
"text \"<text>\" : puts text on the lcd\n"
|
||||||
|
"bgColor (<a>) <r> <g> <b> : set the background color of the lcd\n"
|
||||||
|
"color (<a>) <r> <g> <b> : set the color of the text\n"
|
||||||
|
"listFiles : shows a list with images in the filesystem\n"
|
||||||
|
"setImage <image_name> : put an image on the screen\n"
|
||||||
|
"setGif <image_name> : put a gif on the screen\n"
|
||||||
|
"exit : closes the connection\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the clear command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_clear(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
if (argc == 0) {
|
||||||
|
LOG_INFO(TAG, "Clearing screen");
|
||||||
|
lcd_clear_text();
|
||||||
|
lcd_clear_images();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (argc == 1) {
|
||||||
|
if (strcmp(argv[0], "text") == 0) {
|
||||||
|
LOG_INFO(TAG, "Clearing text");
|
||||||
|
lcd_clear_text();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp(argv[0], "images") == 0) {
|
||||||
|
LOG_INFO(TAG, "Clearing images");
|
||||||
|
lcd_clear_images();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_WARN(TAG, "Bad usage of clear");
|
||||||
|
tcp_cmd_write(pcb, "Usage: clear\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: clear text\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: clear images\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the text command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_text(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
if (argc == 1) {
|
||||||
|
LOG_INFO(TAG, "Setting text %s @ 10, 10", argv[0]);
|
||||||
|
lcd_display_text((const char*)argv[0], 10, 10, color_txt, color_bg, LCD_FONT24);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (argc == 3) {
|
||||||
|
LOG_INFO(TAG, "Setting text %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10),
|
||||||
|
(uint32_t)strtoul(argv[2], NULL, 10));
|
||||||
|
lcd_display_text((const char*)argv[0], (uint32_t)strtoul(argv[1], NULL, 10),
|
||||||
|
(uint32_t)strtoul(argv[2], NULL, 10), color_txt, color_bg, LCD_FONT24);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_WARN(TAG, "Bad usage of text");
|
||||||
|
tcp_cmd_write(pcb, "Usage: text \"<text>\"\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: text <word>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: text \"<text>\" <x> <y>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the bgcolor command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_bg_color(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
if (!str_to_color(argc, argv, &color_bg)) {
|
||||||
|
LOG_INFO(TAG, "Setting background color to %08lX", color_bg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_WARN(TAG, "Bad usage of bgcolor");
|
||||||
|
tcp_cmd_write(pcb, "Usage: bgcolor 0x<rrggbb>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: bgcolor 0x<aarrggbb>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: bgcolor <r> <g> <b>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: bgcolor <a> <r> <g> <b>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the color command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_color(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
if (!str_to_color(argc, argv, &color_txt)) {
|
||||||
|
LOG_INFO(TAG, "Setting color to %08lX", color_txt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_WARN(TAG, "Bad usage of color");
|
||||||
|
tcp_cmd_write(pcb, "Usage: color 0x<rrggbb>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: color 0x<aarrggbb>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: color <r> <g> <b>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: color <a> <r> <g> <b>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the listfiles command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_list_files(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
UNUSED(argv);
|
||||||
|
if (argc == 0) {
|
||||||
|
LOG_INFO(TAG, "Listing files");
|
||||||
|
void* mem = NULL; // Pointer for internal use by the llfs library
|
||||||
|
llfs_file_t* file;
|
||||||
|
while ((file = llfs_next_file(&mem, NULL)) != NULL) {
|
||||||
|
tcp_cmd_write(pcb, file->name);
|
||||||
|
tcp_cmd_write(pcb, "\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_WARN(TAG, "Bad usage of listfiles");
|
||||||
|
tcp_cmd_write(pcb, "Usage: listfiles\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: ls\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the setimage command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_set_image(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
const char* ext = NULL;
|
||||||
|
if (argc >= 1) {
|
||||||
|
ext = llfs_get_filename_ext(argv[0]);
|
||||||
|
if (strcmp(ext, "bmp") != 0) {
|
||||||
|
LOG_WARN(TAG, "setimage: File is not a bmp");
|
||||||
|
tcp_cmd_write(pcb, "File is not a bmp\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc == 1) {
|
||||||
|
LOG_INFO(TAG, "Setting image %s @ 0, 0", argv[0]);
|
||||||
|
lcd_draw_img_from_fs(argv[0], 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (argc == 3) {
|
||||||
|
LOG_INFO(TAG, "Setting image %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10),
|
||||||
|
(uint32_t)strtoul(argv[2], NULL, 10));
|
||||||
|
lcd_draw_img_from_fs(argv[0], (uint32_t)strtoul(argv[1], NULL, 10), (uint32_t)strtoul(argv[2], NULL, 10));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_WARN(TAG, "Bad usage of setimage");
|
||||||
|
tcp_cmd_write(pcb, "Usage: setimage <filename>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: setimage <filename> <x> <y>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the setgif command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_set_gif(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
const char* ext = NULL;
|
||||||
|
if (argc >= 1) {
|
||||||
|
ext = llfs_get_filename_ext(argv[0]);
|
||||||
|
if (strcmp(ext, "gif") != 0) {
|
||||||
|
LOG_WARN(TAG, "setgif: File is not a gif");
|
||||||
|
tcp_cmd_write(pcb, "File is not a gif\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc == 1) {
|
||||||
|
LOG_INFO(TAG, "Setting gif %s @ 0, 0", argv[0]);
|
||||||
|
lcd_draw_gif_from_fs(argv[0], 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (argc == 3) {
|
||||||
|
LOG_INFO(TAG, "Setting gif %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10),
|
||||||
|
(uint32_t)strtoul(argv[2], NULL, 10));
|
||||||
|
lcd_draw_gif_from_fs(argv[0], (uint32_t)strtoul(argv[1], NULL, 10), (uint32_t)strtoul(argv[2], NULL, 10));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == ERR_OK && p == NULL) {
|
LOG_WARN(TAG, "Bad usage of setgif");
|
||||||
|
tcp_cmd_write(pcb, "Usage: setgif <filename>\n");
|
||||||
|
tcp_cmd_write(pcb, "Usage: setgif <filename> <x> <y>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles the exit command
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] argc The number of arguments
|
||||||
|
* @param[in] argv The arguments
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_exit(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
UNUSED(argv);
|
||||||
|
if (argc == 0) {
|
||||||
|
LOG_INFO(TAG, "Closing connection");
|
||||||
|
tcp_cmd_write(pcb, "Exiting...\n");
|
||||||
|
lcd_clear_images();
|
||||||
|
lcd_clear_text();
|
||||||
|
tcp_close(pcb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARN(TAG, "Bad usage of exit");
|
||||||
|
tcp_cmd_write(pcb, "Usage: exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles unknown commands
|
||||||
|
*
|
||||||
|
* @param[in] pcb The tcp_pcb struct to write to
|
||||||
|
* @param[in] cmd The command
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_unknown_cmd(struct tcp_pcb* pcb, char* cmd) {
|
||||||
|
LOG_WARN(TAG, "Unknown command: %s", cmd);
|
||||||
|
tcp_cmd_write(pcb, "Unknown command: ");
|
||||||
|
tcp_cmd_write(pcb, cmd);
|
||||||
|
tcp_cmd_write(pcb, "\n");
|
||||||
|
tcp_cmd_write(pcb, "Type help for list of commands\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function parses the command and calls the appropriate function
|
||||||
|
*
|
||||||
|
* @param[in] pcb Pointer to the tcp_pcb struct to write to
|
||||||
|
* @param[in] argc Count of arguments
|
||||||
|
* @param[in] argv Array of arguments
|
||||||
|
* @return true Connection should be closed
|
||||||
|
* @return false Connection should be kept open
|
||||||
|
*/
|
||||||
|
static bool tcp_cmd_parser(struct tcp_pcb* pcb, int argc, char** argv) {
|
||||||
|
if (argc == 0) {
|
||||||
|
LOG_WARN(TAG, "No command given");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char* cmd = shift_args(&argc, &argv);
|
||||||
|
tcp_cmd_str_tolower(cmd);
|
||||||
|
if (strcmp(cmd, "help") == 0) {
|
||||||
|
tcp_cmd_print_help(pcb);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "clear") == 0) {
|
||||||
|
tcp_cmd_clear(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "text") == 0) {
|
||||||
|
tcp_cmd_text(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "bgcolor") == 0) {
|
||||||
|
tcp_cmd_bg_color(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "color") == 0) {
|
||||||
|
tcp_cmd_color(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "listfiles") == 0) {
|
||||||
|
tcp_cmd_list_files(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "ls") == 0) {
|
||||||
|
tcp_cmd_list_files(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "setimage") == 0) {
|
||||||
|
tcp_cmd_set_image(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "setgif") == 0) {
|
||||||
|
tcp_cmd_set_gif(pcb, argc, argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd, "exit") == 0) {
|
||||||
|
tcp_cmd_exit(pcb, argc, argv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tcp_cmd_unknown_cmd(pcb, cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function is called when the tcp connection receives data
|
||||||
|
* @param[in] arg The argument ptr
|
||||||
|
* @param[in] pcb The tcp_pcb struct
|
||||||
|
* @param[in] p The pbuf struct
|
||||||
|
* @param[in] err The error code from the tcp stack
|
||||||
|
* @return err_t ERR_OK if successful
|
||||||
|
*/
|
||||||
|
err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) {
|
||||||
|
int argc = 0;
|
||||||
|
char cmd[MAX_CMD_LEN] = {0};
|
||||||
|
char* cmd_ptr = NULL;
|
||||||
|
char* argv[MAX_TOKENS] = {0};
|
||||||
|
bool close_conn = false;
|
||||||
|
char* next = NULL;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
// Connection closed?
|
||||||
|
if (p == NULL && err == ERR_OK) {
|
||||||
|
LOG_INFO(TAG, "Remote closed connection");
|
||||||
|
return tcp_close(pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
LOG_WARN(TAG, "TCP data received with error(%d): %s", err, lwip_strerr(err));
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->tot_len >= MAX_CMD_LEN) {
|
||||||
|
LOG_WARN(TAG, "Command too long");
|
||||||
|
tcp_cmd_write(pcb, "Command too long");
|
||||||
|
}
|
||||||
|
uint16_t len = p->tot_len >= MAX_CMD_LEN ? MAX_CMD_LEN : p->tot_len;
|
||||||
|
// Make sure the string is null terminated
|
||||||
|
pbuf_copy_partial(p, cmd, len, 0);
|
||||||
|
cmd[len] = '\0';
|
||||||
|
|
||||||
|
// Tell the tcp stack that we have taken the data
|
||||||
|
tcp_recved(pcb, p->tot_len);
|
||||||
|
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
if (cmd[0] != '\0') {
|
||||||
|
LOG_INFO(TAG, "cmd: %s", cmd);
|
||||||
|
}
|
||||||
|
// Split string into tokens by delimiter (space)
|
||||||
|
cmd_ptr = tcp_cmd_remove_leading_space(cmd, strlen(cmd));
|
||||||
|
argv[0] = tcp_cmd_get_next_token(cmd_ptr, " ", &next);
|
||||||
|
if (argv[0] != NULL) {
|
||||||
|
argc = 1;
|
||||||
|
}
|
||||||
|
while (argv[argc - 1] != NULL && argc < MAX_TOKENS) {
|
||||||
|
// Check if the next token is 0 (end of string) strlen doesn't work here
|
||||||
|
if (*next == 0) {
|
||||||
|
argv[argc] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next = tcp_cmd_remove_leading_space(next, strlen(next));
|
||||||
|
argv[argc] = tcp_cmd_get_next_token(NULL, " ", &next);
|
||||||
|
if (argv[argc] == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
close_conn = tcp_cmd_parser(pcb, argc, argv);
|
||||||
|
|
||||||
|
if (close_conn) {
|
||||||
|
LOG_INFO(TAG, "Closing connection");
|
||||||
tcp_cmd_close(pcb);
|
tcp_cmd_close(pcb);
|
||||||
|
#ifdef NCAT
|
||||||
|
} else {
|
||||||
|
tcp_cmd_write(pcb, "$>");
|
||||||
}
|
}
|
||||||
if (strncmp(tcp_buffer, "\r\n", 2) != 0) {
|
#else
|
||||||
tcp_write(pcb, "User: ", 6, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
} else if (argc > 0) {
|
||||||
|
tcp_cmd_write(pcb, "$>");
|
||||||
|
} else {
|
||||||
|
tcp_cmd_write(pcb, "");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
defer:
|
||||||
|
pbuf_free(p);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function is called when a new tcp connection is accepted
|
||||||
|
* @param[in] arg The argument
|
||||||
|
* @param[in] pcb The tcp_pcb struct
|
||||||
|
* @param[in] err The error
|
||||||
|
* @return err_t ERR_OK
|
||||||
|
*/
|
||||||
static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err) {
|
static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err) {
|
||||||
LWIP_UNUSED_ARG(arg);
|
LWIP_UNUSED_ARG(arg);
|
||||||
LWIP_UNUSED_ARG(err);
|
LWIP_UNUSED_ARG(err);
|
||||||
@@ -184,20 +594,46 @@ static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err) {
|
|||||||
tcp_recv(pcb, tcp_cmd_recv);
|
tcp_recv(pcb, tcp_cmd_recv);
|
||||||
tcp_err(pcb, NULL);
|
tcp_err(pcb, NULL);
|
||||||
tcp_poll(pcb, NULL, 4);
|
tcp_poll(pcb, NULL, 4);
|
||||||
tcp_write(pcb, " Welcom bij de TCP CMD Interface\r\n"
|
|
||||||
"(Typ help voor een lijst van de commando's! X om te sluiten)\r\n"
|
LOG_INFO(TAG, "New connection accepted");
|
||||||
"============================================================\r\n"
|
tcp_cmd_print_header(pcb);
|
||||||
"User: ", 168, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
|
|
||||||
tcp_sent(pcb, NULL);
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @brief This function closes the tcp connection
|
||||||
|
* @param[in] pcb The tcp_pcb struct to close
|
||||||
|
*/
|
||||||
|
static void tcp_cmd_close(struct tcp_pcb* pcb) {
|
||||||
|
tcp_arg(pcb, NULL);
|
||||||
|
tcp_sent(pcb, NULL);
|
||||||
|
tcp_recv(pcb, NULL);
|
||||||
|
tcp_close(pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function initializes the tcp command interface
|
||||||
|
*/
|
||||||
void tcp_cmd_init(void) {
|
void tcp_cmd_init(void) {
|
||||||
struct tcp_pcb* tcp_pcb;
|
struct tcp_pcb* tcp_pcb;
|
||||||
tcp_pcb = tcp_new();
|
tcp_pcb = tcp_new();
|
||||||
tcp_bind(tcp_pcb, IP_ADDR_ANY, 23);
|
|
||||||
|
if (tcp_pcb == NULL) {
|
||||||
|
LOG_CRIT(TAG, "Failed to allocate pcb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcp_bind(tcp_pcb, IP_ADDR_ANY, 23) != ERR_OK) {
|
||||||
|
LOG_CRIT(TAG, "Failed to bind pcb");
|
||||||
|
free(tcp_pcb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tcp_pcb = tcp_listen(tcp_pcb);
|
tcp_pcb = tcp_listen(tcp_pcb);
|
||||||
|
if (tcp_pcb == NULL) {
|
||||||
|
LOG_CRIT(TAG, "Failed to listen");
|
||||||
|
free(tcp_pcb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tcp_accept(tcp_pcb, tcp_cmd_accept);
|
tcp_accept(tcp_pcb, tcp_cmd_accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ static void* tftp_open(const char* fname, const char* mode, uint8_t write);
|
|||||||
static void tftp_close(void* handle);
|
static void tftp_close(void* handle);
|
||||||
static int tftp_read(void* handle, void* buf, int bytes);
|
static int tftp_read(void* handle, void* buf, int bytes);
|
||||||
static int tftp_write(void* handle, struct pbuf* p);
|
static int tftp_write(void* handle, struct pbuf* p);
|
||||||
static struct tftp_context tftpContext_s = {.open = tftp_open, .close = tftp_close, .read = tftp_read, .write = tftp_write};
|
static struct tftp_context tftpContext_s = {.open = tftp_open,
|
||||||
|
.close = tftp_close,
|
||||||
|
.read = tftp_read,
|
||||||
|
.write = tftp_write};
|
||||||
/**
|
/**
|
||||||
* @brief tftp custom file functions to set the offset and read the data
|
* @brief tftp custom file functions to set the offset and read the data
|
||||||
* @param[in,out] handle Custom file handles
|
* @param[in,out] handle Custom file handles
|
||||||
@@ -237,7 +240,7 @@ void init_index(void) {
|
|||||||
for (int i = 0; i < MAX_VIRT_FILES; i++) {
|
for (int i = 0; i < MAX_VIRT_FILES; i++) {
|
||||||
len += strlen(virt_file[i].name) + 1;
|
len += strlen(virt_file[i].name) + 1;
|
||||||
}
|
}
|
||||||
void* mem = NULL; // Pointer for internal use by the llfs library
|
void* mem = NULL; // Pointer for internal use by the llfs library
|
||||||
llfs_file_t* file;
|
llfs_file_t* file;
|
||||||
while ((file = llfs_next_file(&mem, NULL)) != NULL) {
|
while ((file = llfs_next_file(&mem, NULL)) != NULL) {
|
||||||
len += strlen(file->name) + 1;
|
len += strlen(file->name) + 1;
|
||||||
|
|||||||
301
project/Core/Src/website_backend.c
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
/**
|
||||||
|
* @file website_backend.h
|
||||||
|
* @brief Backend for the website to operate
|
||||||
|
* @author Toon B.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Includes
|
||||||
|
#include "website_backend.h"
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static size_t wbe_get_images(char* images_string, size_t file_count_fs);
|
||||||
|
static inline void wbe_build_infostring(const llfs_file_t* file_list, char* info_string, const size_t cnt);
|
||||||
|
static void wbe_decoding_url(const char* encoded, char* decoded);
|
||||||
|
static uint32_t wbe_color_value(const char* rgb);
|
||||||
|
|
||||||
|
void wbe_init(void) {
|
||||||
|
httpd_init();
|
||||||
|
LOG_DEBUG("WBE", "Initialize webserver");
|
||||||
|
|
||||||
|
// Set starting LCD screen
|
||||||
|
wbe_display("Please Edit Me !", LCD_GREEN, LCD_BLACK, SD_IMG);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_open_custom(struct fs_file* file, const char* name) {
|
||||||
|
// Variables
|
||||||
|
llfs_file_t* wanted_file = llfs_file_open(name + 1);
|
||||||
|
size_t buffer_len = 0;
|
||||||
|
static char image_stringbuffer[STR_MAX] = "";
|
||||||
|
|
||||||
|
// The wanted file was found in the filesystem
|
||||||
|
if (wanted_file != NULL) {
|
||||||
|
// Debug info
|
||||||
|
LOG_DEBUG("WBE", "The file : %s was found", wanted_file->name);
|
||||||
|
|
||||||
|
// Give the information about the file to the client
|
||||||
|
file->data = (const char*)wanted_file->data;
|
||||||
|
file->len = (int)wanted_file->len;
|
||||||
|
file->index = (int)wanted_file->len;
|
||||||
|
file->is_custom_file = 1;
|
||||||
|
file->pextension = NULL;
|
||||||
|
file->flags = FS_FILE_FLAGS_HEADER_INCLUDED;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The endpoint '/images.info' is called when the client wants to call for the
|
||||||
|
* information string that contains the names of the available images.
|
||||||
|
*/
|
||||||
|
if (strncmp(name, "/images.info", strlen("/images.info")) == 0) {
|
||||||
|
// Create the information string for the images in the filesystem
|
||||||
|
buffer_len = wbe_get_images(image_stringbuffer, llfs_file_count());
|
||||||
|
|
||||||
|
// Give the string back to the client
|
||||||
|
file->data = image_stringbuffer;
|
||||||
|
file->len = (int)buffer_len;
|
||||||
|
file->index = (int)buffer_len;
|
||||||
|
file->is_custom_file = 1;
|
||||||
|
file->pextension = NULL;
|
||||||
|
file->flags = FS_FILE_FLAGS_HEADER_INCLUDED;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoint when client wants to send information to the backend
|
||||||
|
if (strncmp(name, "/cgi", 3) == 0) {
|
||||||
|
// Give the original index.html back to the client
|
||||||
|
wanted_file = llfs_file_open("index.html");
|
||||||
|
|
||||||
|
if (wanted_file != NULL) {
|
||||||
|
file->data = (const char*)wanted_file->data;
|
||||||
|
file->len = (int)wanted_file->len;
|
||||||
|
file->index = (int)wanted_file->len;
|
||||||
|
file->is_custom_file = 1;
|
||||||
|
file->pextension = NULL;
|
||||||
|
file->flags = FS_FILE_FLAGS_HEADER_INCLUDED;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_close_custom(struct fs_file* file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void wbe_get_images(char*, size_t)
|
||||||
|
* @brief Function searches filesystem for files with extention ".bmp" and ".gif" and put them
|
||||||
|
* combined in a string that needs to be send to the frontend.
|
||||||
|
*
|
||||||
|
* @param[in] images_string, string that will contain the image names
|
||||||
|
* @param[in] file_count_fs, the number of files in the filesystem
|
||||||
|
*/
|
||||||
|
static size_t wbe_get_images(char* images_string, size_t file_count_fs) {
|
||||||
|
// Allocate space for the files
|
||||||
|
llfs_file_t file_list[file_count_fs];
|
||||||
|
|
||||||
|
size_t file_count_bmp = 0;
|
||||||
|
size_t file_count_gif = 0;
|
||||||
|
|
||||||
|
// Reset string
|
||||||
|
strcpy(images_string, "");
|
||||||
|
|
||||||
|
// Get all the ".bmp" and ".gif" files
|
||||||
|
file_count_bmp = llfs_file_list(file_list, file_count_fs, ".bmp");
|
||||||
|
file_count_gif = llfs_file_list(file_list + file_count_bmp, file_count_fs, ".gif");
|
||||||
|
|
||||||
|
// Create the info string
|
||||||
|
wbe_build_infostring(file_list, images_string, file_count_gif + file_count_bmp);
|
||||||
|
|
||||||
|
// Debug info
|
||||||
|
LOG_DEBUG("WBE", "Images string : %s ", images_string);
|
||||||
|
|
||||||
|
// Return the length of the string
|
||||||
|
return strlen(images_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void wbe_build_infostring(const llfs_file_t*, char*, const size_t)
|
||||||
|
* @brief Function adds the names of the files in "file_list" and adds them in "infoStr".
|
||||||
|
* The names are seperated by '|' characters.
|
||||||
|
*
|
||||||
|
* @param[in] file_list, list with files
|
||||||
|
* @param[in] info_string, string that will contain the filenames
|
||||||
|
* @param[in] cnt, the number of files
|
||||||
|
*/
|
||||||
|
static inline void wbe_build_infostring(const llfs_file_t* file_list, char* info_string, const size_t cnt) {
|
||||||
|
// Add the filenames to the info string
|
||||||
|
for (size_t i = 0; i < cnt; ++i) {
|
||||||
|
strncat(info_string, file_list[i].name, strlen(file_list[i].name));
|
||||||
|
strncat(info_string, "|", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove last seperator '|'
|
||||||
|
info_string[strlen(info_string) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void httpd_cgi_handler(struct fs_file* file, const char* uri, int num_parm, char** pc_param, char** pc_value) {
|
||||||
|
// Variables
|
||||||
|
uint32_t vktxt = LCD_GREEN;
|
||||||
|
uint32_t vka = LCD_BLACK;
|
||||||
|
|
||||||
|
// Allocate space for parameters
|
||||||
|
char vtxt[STR_MAX]; // The sentence that we want to print on the LCD.
|
||||||
|
char vfo[STR_MAX]; // Name of the selected image on the website.
|
||||||
|
char s_vktxt[CLR_MAX]; // The color of the sentence. (in #RGB)
|
||||||
|
char s_vka[CLR_MAX]; // Color of the background. (also in #RGB)
|
||||||
|
|
||||||
|
if (strcmp("/cgi", uri) == 0) {
|
||||||
|
for (size_t i = 0; i < num_parm; ++i) {
|
||||||
|
// The given sentence
|
||||||
|
if (strcmp("vtxt", pc_param[i]) == 0) {
|
||||||
|
wbe_decoding_url(pc_value[i], vtxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The color of the sentence
|
||||||
|
if (strcmp("vktxt", pc_param[i]) == 0) {
|
||||||
|
wbe_decoding_url(pc_value[i], s_vktxt);
|
||||||
|
|
||||||
|
// Convert to hex value
|
||||||
|
if (s_vktxt != NULL) {
|
||||||
|
vktxt = wbe_color_value(s_vktxt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color of the background
|
||||||
|
if (strcmp("vka", pc_param[i]) == 0) {
|
||||||
|
wbe_decoding_url(pc_value[i], s_vka);
|
||||||
|
|
||||||
|
// convert to hex value
|
||||||
|
if (s_vka != NULL) {
|
||||||
|
vka = wbe_color_value(s_vka);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name of the image
|
||||||
|
if (strcmp("vfo", pc_param[i]) == 0) {
|
||||||
|
wbe_decoding_url(pc_value[i], vfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug info
|
||||||
|
LOG_DEBUG("WBE", "CGI DATA : %s , %x , %x , %s", vtxt, vktxt, vka, vfo);
|
||||||
|
|
||||||
|
// Display on LCD
|
||||||
|
wbe_display(vtxt, vktxt, vka, vfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void wbe_decoding_url(const char*, char*)
|
||||||
|
* @brief The given information from the CGI parameters are URL encoded.
|
||||||
|
* This function translates this encoded string in a readable
|
||||||
|
* decoded string. The lengthe of "char* decoded" is at least the
|
||||||
|
* length of "char* encoded" + 1.
|
||||||
|
*
|
||||||
|
* @param[in] encoded, the encoded URL string that needs to be decoded
|
||||||
|
* @param[in] decoded, string that will contain the decoded URL.
|
||||||
|
*/
|
||||||
|
static void wbe_decoding_url(const char* encoded, char* decoded) {
|
||||||
|
// Variables
|
||||||
|
char* endptr;
|
||||||
|
size_t decoded_index = 0;
|
||||||
|
size_t encoded_length = strlen(encoded);
|
||||||
|
uint32_t hex_val;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < encoded_length; ++i) {
|
||||||
|
// If we encounter a %xx, decode it to ascii
|
||||||
|
if ((encoded[i] == '%') && (i + 2 < encoded_length)) {
|
||||||
|
// Decode %xx
|
||||||
|
hex_val = (uint32_t)strtoul(&encoded[i + 1], &endptr, 16);
|
||||||
|
|
||||||
|
// Check for conversion errors
|
||||||
|
if (endptr == &encoded[i + 1] || *endptr != '\0') {
|
||||||
|
LOG_DEBUG("WBE", "URL text conversion error");
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded[decoded_index++] = (char)hex_val;
|
||||||
|
|
||||||
|
// Skip 2 characters
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
// If we encounter a +, add a space character
|
||||||
|
} else if (encoded[i] == '+') {
|
||||||
|
decoded[decoded_index++] = ' ';
|
||||||
|
|
||||||
|
// If no % or +, just put what stands in 'encoded'
|
||||||
|
} else {
|
||||||
|
decoded[decoded_index++] = encoded[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish the string
|
||||||
|
decoded[decoded_index] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t wbe_color_value(const char* rgb) {
|
||||||
|
// Variables
|
||||||
|
char* endptr;
|
||||||
|
uint32_t color = LCD_BLACK;
|
||||||
|
char argb[11] = "0xff";
|
||||||
|
|
||||||
|
// Create argb string (also, skip the '#' char)
|
||||||
|
strncat(argb, rgb + 1, strlen(rgb + 1));
|
||||||
|
|
||||||
|
// Get argb value
|
||||||
|
color = (uint32_t)strtoul(argb, &endptr, 16);
|
||||||
|
|
||||||
|
// Check for conversion errors
|
||||||
|
if (*endptr != '\0') {
|
||||||
|
color = LCD_BLACK;
|
||||||
|
LOG_DEBUG("WBE", "URL color conversion error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wbe_display(const char* txt, const uint32_t txt_color, const uint32_t bg_color, const char* image) {
|
||||||
|
// Variables
|
||||||
|
lcd_gif_t* gif;
|
||||||
|
const char* extension;
|
||||||
|
|
||||||
|
// clear the screen
|
||||||
|
lcd_clear_text();
|
||||||
|
lcd_clear_images();
|
||||||
|
|
||||||
|
// Display the text and the background
|
||||||
|
lcd_set_bg_color_layer0(bg_color);
|
||||||
|
lcd_display_text(txt, 10, 10, txt_color, bg_color, LCD_FONT16);
|
||||||
|
|
||||||
|
// Get the extension of the file
|
||||||
|
extension = llfs_get_filename_ext(image);
|
||||||
|
|
||||||
|
// Check extension
|
||||||
|
if (extension != NULL) {
|
||||||
|
// Draw bmp
|
||||||
|
if (strcmp(extension, "bmp") == 0) {
|
||||||
|
lcd_draw_img_from_fs(image, IMG_X, IMG_Y);
|
||||||
|
|
||||||
|
// Draw gif
|
||||||
|
} else if (strcmp(extension, "gif") == 0) {
|
||||||
|
gif = lcd_draw_gif_from_fs(image, IMG_X, IMG_Y);
|
||||||
|
|
||||||
|
if (gif == NULL) {
|
||||||
|
LOG_DEBUG("WBE", "GIF could not be drawn");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing, then draw the standard image
|
||||||
|
} else {
|
||||||
|
lcd_draw_img_from_fs(SD_IMG, IMG_X, IMG_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing, then draw the standard image
|
||||||
|
} else {
|
||||||
|
lcd_draw_img_from_fs(SD_IMG, IMG_X, IMG_Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,14 +12,17 @@ add_executable(tests)
|
|||||||
target_compile_definitions(tests
|
target_compile_definitions(tests
|
||||||
PRIVATE
|
PRIVATE
|
||||||
"TESTING"
|
"TESTING"
|
||||||
|
"DEBUG"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(tests
|
target_sources(tests
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${TEST_SOURCES}
|
${TEST_SOURCES}
|
||||||
../project/Core/Src/tftp.c
|
${CMAKE_SOURCE_DIR}
|
||||||
../project/Core/Src/llfs_data.c
|
${CMAKE_SOURCE_DIR}/project/Core/Src/llfs_data.c
|
||||||
../project/Core/Src/llfs.c
|
${CMAKE_SOURCE_DIR}/project/Core/Src/llfs.c
|
||||||
|
${CMAKE_SOURCE_DIR}/project/Core/Src/tftp.c
|
||||||
|
${CMAKE_SOURCE_DIR}/project/Core/Src/tcp_cmd.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(tests PRIVATE $<$<CONFIG:Debug>:
|
target_compile_options(tests PRIVATE $<$<CONFIG:Debug>:
|
||||||
@@ -35,7 +38,7 @@ target_include_directories(tests
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
${PROJECT_BINARY_DIR}
|
${PROJECT_BINARY_DIR}
|
||||||
../project/Core/Inc/
|
${CMAKE_SOURCE_DIR}/project/Core/Inc/
|
||||||
)
|
)
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
|||||||
91
tests/mocs.c
@@ -1,44 +1,68 @@
|
|||||||
#include "mocs.h"
|
#include "mocs.h"
|
||||||
#include "tftp.h"
|
#include "tftp.h"
|
||||||
|
#include "mocs.h"
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define dprint(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define dprint(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
void tftp_cleanup(void) {
|
void tftp_cleanup(void) {
|
||||||
|
dprint("tftp_cleanup\n");
|
||||||
}
|
}
|
||||||
uint32_t logger_get_timestamp(void) {
|
uint32_t logger_get_timestamp(void) {
|
||||||
|
dprint("logger_get_timestamp\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tftp_init(struct tftp_context* context) {
|
int tftp_init(struct tftp_context* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
|
|
||||||
|
dprint("tftp_init\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_display_text(const char* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font) {
|
void lcd_display_text(const char* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font) {
|
||||||
|
UNUSED(text);
|
||||||
|
UNUSED(x_pos);
|
||||||
|
UNUSED(y_pos);
|
||||||
UNUSED(color);
|
UNUSED(color);
|
||||||
UNUSED(bg_color);
|
UNUSED(bg_color);
|
||||||
UNUSED(font);
|
UNUSED(font);
|
||||||
|
|
||||||
printf("lcd_display_text @ %d %d with color 0x%08X bg color 0x%08X\n%s\n", x_pos, y_pos, color, bg_color, text);
|
dprint("lcd_display_text @ %d %d with color 0x%08X bg color 0x%08X\n%s\n", x_pos, y_pos, color, bg_color, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_draw_img_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos) {
|
void lcd_draw_img_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos) {
|
||||||
printf("lcd_draw_img_from_fs\n%s @%d %d\n", filename, x_pos, y_pos);
|
UNUSED(filename);
|
||||||
|
UNUSED(x_pos);
|
||||||
|
UNUSED(y_pos);
|
||||||
|
|
||||||
|
dprint("lcd_draw_img_from_fs\n%s @%d %d\n", filename, x_pos, y_pos);
|
||||||
}
|
}
|
||||||
void lcd_draw_gif_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos) {
|
void lcd_draw_gif_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos) {
|
||||||
printf("lcd_draw_gif_from_fs\n%s @%d %d\n", filename, x_pos, y_pos);
|
UNUSED(filename);
|
||||||
|
UNUSED(x_pos);
|
||||||
|
UNUSED(y_pos);
|
||||||
|
|
||||||
|
dprint("lcd_draw_gif_from_fs\n%s @%d %d\n", filename, x_pos, y_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_clear_images(void) {
|
void lcd_clear_images(void) {
|
||||||
printf("lcd_clear_images\n");
|
dprint("lcd_clear_images\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_clear_text(void) {
|
void lcd_clear_text(void) {
|
||||||
printf("lcd_clear_text\n");
|
dprint("lcd_clear_text\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_draw_bmp_img(uint8_t* bmp_buff, uint32_t x_pos, uint32_t y_pos) {
|
void lcd_draw_bmp_img(uint8_t* bmp_buff, uint32_t x_pos, uint32_t y_pos) {
|
||||||
UNUSED(bmp_buff);
|
UNUSED(bmp_buff);
|
||||||
|
UNUSED(x_pos);
|
||||||
|
UNUSED(y_pos);
|
||||||
|
|
||||||
printf("lcd_draw_bmp_img @ %d %d\n", x_pos, y_pos);
|
dprint("lcd_draw_bmp_img @ %d %d\n", x_pos, y_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_draw_gif(uint8_t* gif_buff, size_t len, uint32_t x_pos, uint32_t y_pos) {
|
void lcd_draw_gif(uint8_t* gif_buff, size_t len, uint32_t x_pos, uint32_t y_pos) {
|
||||||
@@ -47,59 +71,81 @@ void lcd_draw_gif(uint8_t* gif_buff, size_t len, uint32_t x_pos, uint32_t y_pos)
|
|||||||
UNUSED(x_pos);
|
UNUSED(x_pos);
|
||||||
UNUSED(y_pos);
|
UNUSED(y_pos);
|
||||||
|
|
||||||
printf("lcd_draw_gif @ %d %d\n", x_pos, y_pos);
|
dprint("lcd_draw_gif @ %d %d\n", x_pos, y_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tcp_pcb* tcp_new(void) {
|
struct tcp_pcb* tcp_new(void) {
|
||||||
|
dprint("tcp_new\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_t tcp_bind(void *pcb, void *ipaddr, uint16_t port) {
|
err_t tcp_bind(void* pcb, void* ipaddr, uint16_t port) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(ipaddr);
|
UNUSED(ipaddr);
|
||||||
UNUSED(port);
|
UNUSED(port);
|
||||||
|
|
||||||
|
dprint("tcp_bind @ %d\n", port);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tcp_pcb* tcp_listen(void *pcb) {
|
struct tcp_pcb* tcp_listen(void* pcb) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
|
|
||||||
|
dprint("tcp_listen\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_accept(void *pcb, tcp_accept_fn arg) {
|
void tcp_accept(void* pcb, tcp_accept_fn arg) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(arg);
|
UNUSED(arg);
|
||||||
|
|
||||||
|
dprint("tcp_accept\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_arg(void* pcb, void* arg) {
|
void tcp_arg(void* pcb, void* arg) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(arg);
|
UNUSED(arg);
|
||||||
|
|
||||||
|
dprint("tcp_arg\n");
|
||||||
}
|
}
|
||||||
void tcp_sent(void* pcb, void* arg) {
|
void tcp_sent(void* pcb, void* arg) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(arg);
|
UNUSED(arg);
|
||||||
|
|
||||||
|
dprint("tcp_sent\n");
|
||||||
}
|
}
|
||||||
void tcp_recv(void* pcb, tcp_recv_fn arg) {
|
void tcp_recv(void* pcb, tcp_recv_fn arg) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(arg);
|
UNUSED(arg);
|
||||||
|
|
||||||
|
dprint("tcp_recv\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_setprio(void* pcb, uint8_t prio) {
|
void tcp_setprio(void* pcb, uint8_t prio) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(prio);
|
UNUSED(prio);
|
||||||
|
|
||||||
|
dprint("tcp_setprio\n");
|
||||||
}
|
}
|
||||||
void tcp_err(void* pcb, void* err) {
|
void tcp_err(void* pcb, void* err) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(err);
|
UNUSED(err);
|
||||||
|
|
||||||
|
dprint("tcp_err\n");
|
||||||
}
|
}
|
||||||
void tcp_poll(void* pcb, void* poll, uint8_t interval) {
|
void tcp_poll(void* pcb, void* poll, uint8_t interval) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(poll);
|
UNUSED(poll);
|
||||||
UNUSED(interval);
|
UNUSED(interval);
|
||||||
|
|
||||||
|
dprint("tcp_poll\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_close(void* pcb) {
|
err_t tcp_close(void* pcb) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
|
|
||||||
|
dprint("tcp_close\n");
|
||||||
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_write(void* pcb, const char* data, size_t len, uint8_t apiflags) {
|
void tcp_write(void* pcb, const char* data, size_t len, uint8_t apiflags) {
|
||||||
@@ -107,23 +153,44 @@ void tcp_write(void* pcb, const char* data, size_t len, uint8_t apiflags) {
|
|||||||
UNUSED(apiflags);
|
UNUSED(apiflags);
|
||||||
UNUSED(len);
|
UNUSED(len);
|
||||||
|
|
||||||
printf("tcp_write:\n%s\n", data);
|
dprint("tcp_write:\n");
|
||||||
|
printf("%s\n", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_output(void* pcb) {
|
void tcp_output(void* pcb) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
|
|
||||||
|
dprint("tcp_output\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_recved(void* pcb, uint16_t len) {
|
void tcp_recved(void* pcb, uint16_t len) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
UNUSED(len);
|
UNUSED(len);
|
||||||
|
|
||||||
|
dprint("tcp_recved\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tcp_sndbuf(void* pcb) {
|
size_t tcp_sndbuf(void* pcb) {
|
||||||
UNUSED(pcb);
|
UNUSED(pcb);
|
||||||
|
|
||||||
|
dprint("tcp_sndbuf\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbuf_free(struct pbuf* p) {
|
void pbuf_free(struct pbuf* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|
||||||
|
dprint("pbuf_free\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t pbuf_copy_partial(const struct pbuf* buf, void* dataptr, uint16_t len, uint16_t offset) {
|
||||||
|
memcpy(dataptr, ((uint8_t*)(buf->payload)) + offset, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* lwip_strerr(err_t err) {
|
||||||
|
UNUSED(err);
|
||||||
|
|
||||||
|
dprint("lwip_sterr\n");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
140
tests/mocs.h
@@ -4,8 +4,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef UNUSED
|
#ifndef UNUSED
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
@@ -13,56 +13,65 @@ extern "C" {
|
|||||||
|
|
||||||
#define LWIP_UNUSED_ARG(x) UNUSED(x)
|
#define LWIP_UNUSED_ARG(x) UNUSED(x)
|
||||||
|
|
||||||
|
typedef void sFONT;
|
||||||
|
|
||||||
|
#define LCD_COLOR_BLACK 0
|
||||||
|
#define LCD_COLOR_WHITE 1
|
||||||
|
#define LCD_TRANSPARENT 2
|
||||||
|
|
||||||
|
#define LCD_FONT16 0
|
||||||
|
#define LCD_FONT24 (void*)1
|
||||||
|
|
||||||
typedef int8_t err_t;
|
typedef int8_t err_t;
|
||||||
/** Definitions for error constants. */
|
/** Definitions for error constants. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/** No error, everything OK. */
|
/** No error, everything OK. */
|
||||||
ERR_OK = 0,
|
ERR_OK = 0,
|
||||||
/** Out of memory error. */
|
/** Out of memory error. */
|
||||||
ERR_MEM = -1,
|
ERR_MEM = -1,
|
||||||
/** Buffer error. */
|
/** Buffer error. */
|
||||||
ERR_BUF = -2,
|
ERR_BUF = -2,
|
||||||
/** Timeout. */
|
/** Timeout. */
|
||||||
ERR_TIMEOUT = -3,
|
ERR_TIMEOUT = -3,
|
||||||
/** Routing problem. */
|
/** Routing problem. */
|
||||||
ERR_RTE = -4,
|
ERR_RTE = -4,
|
||||||
/** Operation in progress */
|
/** Operation in progress */
|
||||||
ERR_INPROGRESS = -5,
|
ERR_INPROGRESS = -5,
|
||||||
/** Illegal value. */
|
/** Illegal value. */
|
||||||
ERR_VAL = -6,
|
ERR_VAL = -6,
|
||||||
/** Operation would block. */
|
/** Operation would block. */
|
||||||
ERR_WOULDBLOCK = -7,
|
ERR_WOULDBLOCK = -7,
|
||||||
/** Address in use. */
|
/** Address in use. */
|
||||||
ERR_USE = -8,
|
ERR_USE = -8,
|
||||||
/** Already connecting. */
|
/** Already connecting. */
|
||||||
ERR_ALREADY = -9,
|
ERR_ALREADY = -9,
|
||||||
/** Conn already established.*/
|
/** Conn already established.*/
|
||||||
ERR_ISCONN = -10,
|
ERR_ISCONN = -10,
|
||||||
/** Not connected. */
|
/** Not connected. */
|
||||||
ERR_CONN = -11,
|
ERR_CONN = -11,
|
||||||
/** Low-level netif error */
|
/** Low-level netif error */
|
||||||
ERR_IF = -12,
|
ERR_IF = -12,
|
||||||
|
|
||||||
/** Connection aborted. */
|
/** Connection aborted. */
|
||||||
ERR_ABRT = -13,
|
ERR_ABRT = -13,
|
||||||
/** Connection reset. */
|
/** Connection reset. */
|
||||||
ERR_RST = -14,
|
ERR_RST = -14,
|
||||||
/** Connection closed. */
|
/** Connection closed. */
|
||||||
ERR_CLSD = -15,
|
ERR_CLSD = -15,
|
||||||
/** Illegal argument. */
|
/** Illegal argument. */
|
||||||
ERR_ARG = -16
|
ERR_ARG = -16
|
||||||
} err_enum_t;
|
} err_enum_t;
|
||||||
|
|
||||||
struct pbuf {
|
struct pbuf {
|
||||||
struct pbuf *next;
|
struct pbuf* next;
|
||||||
void *payload;
|
void* payload;
|
||||||
uint16_t tot_len;
|
uint16_t tot_len;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t type_internal;
|
uint8_t type_internal;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
//LWIP_PBUF_REF_T ref;
|
// LWIP_PBUF_REF_T ref;
|
||||||
|
|
||||||
uint8_t if_idx;
|
uint8_t if_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tcp_pcb {
|
struct tcp_pcb {
|
||||||
@@ -70,10 +79,10 @@ struct tcp_pcb {
|
|||||||
};
|
};
|
||||||
typedef void sFONT;
|
typedef void sFONT;
|
||||||
|
|
||||||
#define ERR_OK 0
|
#define ERR_OK 0
|
||||||
#define LCD_COLOR_BLACK 0
|
#define LCD_COLOR_BLACK 0
|
||||||
#define LCD_COLOR_WHITE 1
|
#define LCD_COLOR_WHITE 1
|
||||||
#define LCD_TRANSPARENT 2
|
#define LCD_TRANSPARENT 2
|
||||||
|
|
||||||
#define LCD_FONT16 0
|
#define LCD_FONT16 0
|
||||||
#define LCD_FONT24 (void*)1
|
#define LCD_FONT24 (void*)1
|
||||||
@@ -86,14 +95,13 @@ typedef void sFONT;
|
|||||||
#define TCP_PRIO_MAX 127
|
#define TCP_PRIO_MAX 127
|
||||||
#define IP_ADDR_ANY 0
|
#define IP_ADDR_ANY 0
|
||||||
|
|
||||||
typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
|
typedef err_t (*tcp_recv_fn)(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err);
|
||||||
struct pbuf *p, err_t err);
|
|
||||||
|
typedef err_t (*tcp_accept_fn)(void* arg, struct tcp_pcb* newpcb, err_t err);
|
||||||
typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
|
||||||
|
|
||||||
uint32_t logger_get_timestamp(void);
|
uint32_t logger_get_timestamp(void);
|
||||||
|
|
||||||
void lcd_display_text(const char* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT *font);
|
void lcd_display_text(const char* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font);
|
||||||
void lcd_draw_img_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos);
|
void lcd_draw_img_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos);
|
||||||
void lcd_draw_gif_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos);
|
void lcd_draw_gif_from_fs(char* filename, uint32_t x_pos, uint32_t y_pos);
|
||||||
void lcd_draw_bmp_img(uint8_t* bmp_buff, uint32_t x_pos, uint32_t y_pos);
|
void lcd_draw_bmp_img(uint8_t* bmp_buff, uint32_t x_pos, uint32_t y_pos);
|
||||||
@@ -103,23 +111,27 @@ void lcd_clear_images(void);
|
|||||||
void lcd_clear_text(void);
|
void lcd_clear_text(void);
|
||||||
|
|
||||||
struct tcp_pcb* tcp_new(void);
|
struct tcp_pcb* tcp_new(void);
|
||||||
err_t tcp_bind(void *pcb, void *ipaddr, uint16_t port);
|
err_t tcp_bind(void* pcb, void* ipaddr, uint16_t port);
|
||||||
struct tcp_pcb* tcp_listen(void *pcb);
|
struct tcp_pcb* tcp_listen(void* pcb);
|
||||||
void tcp_accept(void *pcb, tcp_accept_fn arg);
|
void tcp_accept(void* pcb, tcp_accept_fn arg);
|
||||||
void tcp_arg(void *pcb, void *arg);
|
void tcp_arg(void* pcb, void* arg);
|
||||||
void tcp_sent(void *pcb, void *arg);
|
void tcp_sent(void* pcb, void* arg);
|
||||||
void tcp_recv(void *pcb, tcp_recv_fn arg);
|
void tcp_recv(void* pcb, tcp_recv_fn arg);
|
||||||
void tcp_setprio(void *pcb, uint8_t prio);
|
void tcp_setprio(void* pcb, uint8_t prio);
|
||||||
void tcp_err(void *pcb, void* err);
|
void tcp_err(void* pcb, void* err);
|
||||||
void tcp_poll(void *pcb, void* poll, uint8_t interval);
|
void tcp_poll(void* pcb, void* poll, uint8_t interval);
|
||||||
void tcp_close(void *pcb);
|
err_t tcp_close(void* pcb);
|
||||||
|
|
||||||
void tcp_write(void *pcb, const char *data, size_t len, uint8_t apiflags);
|
void tcp_write(void* pcb, const char* data, size_t len, uint8_t apiflags);
|
||||||
void tcp_output(void *pcb);
|
void tcp_output(void* pcb);
|
||||||
void tcp_recved(void *pcb, uint16_t len);
|
void tcp_recved(void* pcb, uint16_t len);
|
||||||
void pbuf_free(struct pbuf* p);
|
void pbuf_free(struct pbuf* p);
|
||||||
|
|
||||||
size_t tcp_sndbuf(void *pcb);
|
size_t tcp_sndbuf(void* pcb);
|
||||||
|
|
||||||
|
uint16_t pbuf_copy_partial(const struct pbuf* buf, void* dataptr, uint16_t len, uint16_t offset);
|
||||||
|
|
||||||
|
const char* lwip_strerr(err_t err);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
0
tests/tcp.h
Normal file
252
tests/tcp_cmd.cpp
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "mocs.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "tcp_cmd.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TCP_CMD, tcp_cmd_remove_newline) {
|
||||||
|
char* cmd = (char*)calloc(50, 1);
|
||||||
|
strcpy(cmd, "help\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "help");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "help\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\nhelp\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n\n\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n\n\n\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhelp\n\n\n\n\n\n\n\n\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
strcpy(cmd, "\n\nhel\np\n");
|
||||||
|
tcp_cmd_remove_newline(cmd, strlen(cmd));
|
||||||
|
EXPECT_STREQ(cmd, "help");
|
||||||
|
|
||||||
|
free(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TCP_CMD, tcp_cmd_remove_leading_space) {
|
||||||
|
char* cmd = (char*)calloc(50, 1);
|
||||||
|
strcpy(cmd, "help");
|
||||||
|
EXPECT_STREQ(tcp_cmd_remove_leading_space(cmd, strlen(cmd)), "help");
|
||||||
|
strcpy(cmd, " help");
|
||||||
|
EXPECT_STREQ(tcp_cmd_remove_leading_space(cmd, strlen(cmd)), "help");
|
||||||
|
strcpy(cmd, " help");
|
||||||
|
EXPECT_STREQ(tcp_cmd_remove_leading_space(cmd, strlen(cmd)), "help");
|
||||||
|
strcpy(cmd, " help");
|
||||||
|
EXPECT_STREQ(tcp_cmd_remove_leading_space(cmd, strlen(cmd)), "help");
|
||||||
|
strcpy(cmd, " help");
|
||||||
|
EXPECT_STREQ(tcp_cmd_remove_leading_space(cmd, strlen(cmd)), "help");
|
||||||
|
strcpy(cmd, "\n\t\r\n help");
|
||||||
|
EXPECT_STREQ(tcp_cmd_remove_leading_space(cmd, strlen(cmd)), "help");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TCP_CMD, tcp_data_cb) {
|
||||||
|
char* cmd = (char*)calloc(50, 1);
|
||||||
|
std::string output;
|
||||||
|
pbuf p = {.next = NULL, .payload = (void*)cmd, .tot_len = 4, .len = 0, .type_internal = 0, .flags = 0, .if_idx = 0};
|
||||||
|
strcpy(cmd, "help");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "help : shows a list of commands\n"
|
||||||
|
"clear text/images : clears the text or images on the lcd\n"
|
||||||
|
"text \"<text>\" : puts text on the lcd\n"
|
||||||
|
"bgColor (<a>) <r> <g> <b> : set the background color of the lcd\n"
|
||||||
|
"color (<a>) <r> <g> <b> : set the color of the text\n"
|
||||||
|
"listFiles : shows a list with images in the filesystem\n"
|
||||||
|
"setImage <image_name> : put an image on the screen\n"
|
||||||
|
"setGif <image_name> : put a gif on the screen\n"
|
||||||
|
"exit : closes the connection\n\n$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\ntcp_write:\n"
|
||||||
|
"help : shows a list of commands\n"
|
||||||
|
"clear text/images : clears the text or images on the lcd\n"
|
||||||
|
"text \"<text>\" : puts text on the lcd\n"
|
||||||
|
"bgColor (<a>) <r> <g> <b> : set the background color of the lcd\n"
|
||||||
|
"color (<a>) <r> <g> <b> : set the color of the text\n"
|
||||||
|
"listFiles : shows a list with images in the filesystem\n"
|
||||||
|
"setImage <image_name> : put an image on the screen\n"
|
||||||
|
"setGif <image_name> : put a gif on the screen\n"
|
||||||
|
"exit : closes the connection\n"
|
||||||
|
"\ntcp_output\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "text \"This is printed on the display\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlcd_display_text @ 10 10 with color 0xFFFFFFFF bg color 0xFF000000\nThis is printed on the display\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "color 0x555555");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "bgcolor 0xAAAAAA");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "text \"This is printed on the display\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlcd_display_text @ 10 10 with color 0x00555555 bg color 0x00AAAAAA\nThis is printed on the display\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "color 255 255 255");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "bgcolor 255 255 255");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "text \"This is printed on the display\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlcd_display_text @ 10 10 with color 0xFFFFFFFF bg color 0xFFFFFFFF\nThis is printed on the display\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "setImage \"test.bmp\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlcd_draw_img_from_fs\ntest.bmp @0 0\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "setImage \"test.gif\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "[Warning] ( 0) [tcp_cmd]: setimage: File is not a bmp\r\nFile is not a bmp\n\n$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlogger_get_timestamp\n[Warning] ( 0) [tcp_cmd]: setimage: File is not a bmp\r\ntcp_write:\nFile is not a bmp\n\ntcp_output\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "setGif \"test.gif\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlcd_draw_gif_from_fs\ntest.gif @0 0\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "setGif \"test.bmp\"");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "[Warning] ( 0) [tcp_cmd]: setgif: File is not a gif\r\nFile is not a gif\n\n$>\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\nlogger_get_timestamp\n[Warning] ( 0) [tcp_cmd]: setgif: File is not a gif\r\ntcp_write:\nFile is not a gif\n\ntcp_output\ntcp_write:\n$>\ntcp_output\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(cmd, "exit");
|
||||||
|
p.tot_len = (uint16_t)strlen(cmd);
|
||||||
|
|
||||||
|
testing::internal::CaptureStdout();
|
||||||
|
tcp_cmd_recv(NULL, NULL, &p, ERR_OK);
|
||||||
|
output = testing::internal::GetCapturedStdout();
|
||||||
|
#ifndef DEBUG
|
||||||
|
EXPECT_EQ(output, "Exiting...\n\n");
|
||||||
|
#else
|
||||||
|
EXPECT_EQ(output, "tcp_recved\ntcp_write:\nExiting...\n\ntcp_output\nlcd_clear_images\nlcd_clear_text\ntcp_close\ntcp_arg\ntcp_sent\ntcp_recv\ntcp_close\npbuf_free\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(cmd);
|
||||||
|
}
|
||||||
@@ -1,47 +1,35 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "mocs.h"
|
#include "mocs.h"
|
||||||
#include "tftp.h"
|
#include "tftp.h"
|
||||||
|
|
||||||
tftp_custom_file_t file = {
|
tftp_custom_file_t file = {.data = (char*)"1234567890", .len = 11, .name = (char*)"test.txt", .offset = 0};
|
||||||
.data = (char*)"1234567890",
|
tftp_custom_file_t write_file = {.data = NULL, .len = 0, .name = (char*)"test.txt", .offset = 0};
|
||||||
.len = 11,
|
|
||||||
.name = (char*)"test.txt",
|
|
||||||
.offset = 0
|
|
||||||
};
|
|
||||||
tftp_custom_file_t write_file = {
|
|
||||||
.data = NULL,
|
|
||||||
.len = 0,
|
|
||||||
.name = (char*)"test.txt",
|
|
||||||
.offset = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(TFTP, custom_fseek)
|
TEST(TFTP, custom_fseek) {
|
||||||
{
|
|
||||||
tftp_custom_fseek(&file, 5, SEEK_SET);
|
tftp_custom_fseek(&file, 5, SEEK_SET);
|
||||||
EXPECT_EQ(file.offset, 5);
|
EXPECT_EQ(file.offset, 5);
|
||||||
tftp_custom_fseek(&file, 5, SEEK_CUR);
|
tftp_custom_fseek(&file, 5, SEEK_CUR);
|
||||||
EXPECT_EQ(file.offset, 10);
|
EXPECT_EQ(file.offset, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TFTP, custom_fread)
|
TEST(TFTP, custom_fread) {
|
||||||
{
|
|
||||||
char buf[11];
|
char buf[11];
|
||||||
tftp_custom_fseek(&file, 0, SEEK_SET);
|
tftp_custom_fseek(&file, 0, SEEK_SET);
|
||||||
size_t bytes = tftp_custom_fread(buf, 11, &file);
|
size_t bytes = tftp_custom_fread(buf, 11, &file);
|
||||||
EXPECT_EQ(bytes, 10);
|
EXPECT_EQ(bytes, 11);
|
||||||
EXPECT_EQ(file.offset, 10);
|
EXPECT_EQ(file.offset, 11);
|
||||||
EXPECT_EQ(memcmp(buf, "1234567890", 10), 0);
|
EXPECT_EQ(memcmp(buf, "1234567890", 10), 0);
|
||||||
|
|
||||||
memset(buf, 0, 11);
|
memset(buf, 0, 11);
|
||||||
|
|
||||||
tftp_custom_fseek(&file, 0, SEEK_SET);
|
tftp_custom_fseek(&file, 0, SEEK_SET);
|
||||||
bytes = tftp_custom_fread(buf, 11, &file);
|
bytes = tftp_custom_fread(buf, 11, &file);
|
||||||
EXPECT_EQ(bytes, 10);
|
EXPECT_EQ(bytes, 11);
|
||||||
EXPECT_EQ(memcmp(buf, "1234567890", 10), 0);
|
EXPECT_EQ(memcmp(buf, "1234567890", 10), 0);
|
||||||
|
|
||||||
memset(buf, 0, 11);
|
memset(buf, 0, 11);
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "mocs.h"
|
#include "mocs.h"
|
||||||
|
|
||||||
struct tftp_context {
|
struct tftp_context {
|
||||||
void* (*open)(const char* fname, const char* mode, uint8_t write);
|
void* (*open)(const char* fname, const char* mode, uint8_t write);
|
||||||
void (*close)(void* handle);
|
void (*close)(void* handle);
|
||||||
int (*read)(void* handle, void* buf, int bytes);
|
int (*read)(void* handle, void* buf, int bytes);
|
||||||
int (*write)(void* handle, struct pbuf* p);
|
int (*write)(void* handle, struct pbuf* p);
|
||||||
};
|
};
|
||||||
|
|
||||||
void tftp_cleanup(void);
|
void tftp_cleanup(void);
|
||||||
|
|||||||