使用SWUpdate 软件进行程序升级

SWUpdate 官方说明文档:

https://zqb-all.github.io/swupdate/swupdate.html

//main.cpp

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#include "MainWindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

//common_def.h

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#ifndef COMMON_DEF_H
#define COMMON_DEF_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdbool.h>
#include "network_ipc.h"

#include <QDebug>

static char buf[256];
static int fd = STDIN_FILENO;
static int verbose = 1;
static bool dry_run = false;
static bool run_postupdate = false;
static int end_status = EXIT_SUCCESS;

static pthread_mutex_t mymutex;

/*
 * this is the callback to get a new chunk of the
 * image.
 * It is called by a thread generated by the library and
 * can block.
 */
static int readimage(char **p, int *size) {
    int ret;

    ret = read(fd, buf, sizeof(buf));

    *p = buf;

    *size = ret;

    return ret;
}

/*
 * This is called by the library to inform
 * about the current status of the upgrade
 */
static int printstatus(ipc_message *msg)
{
    if (verbose)
        fprintf(stdout, "Status: %d message: %s\n",
            msg->data.status.current,
            strlen(msg->data.status.desc) > 0 ? msg->data.status.desc : "");

    return 0;
}

/*
 * this is called at the end reporting the status
 * of the upgrade and running any post-update actions
 * if successful
 */
static int end(RECOVERY_STATUS status)
{
    end_status = (status == SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE;

    fprintf(stdout, "Swupdate %s\n",
        status == FAILURE ? "*failed* !" :
            "was successful !");

    if (status == SUCCESS && run_postupdate) {
        fprintf(stdout, "Executing post-update actions.\n");
        ipc_message msg;
        if (ipc_postupdate(&msg) != 0)
            fprintf(stderr, "Running post-update failed!\n");
    }

    pthread_mutex_unlock(&mymutex);

    return 0;
}

/*
 * Send file to main swupdate process
 */
static int send_file(const char* filename) {
    int rc;
    if (filename && (fd = open(filename, O_RDONLY)) < 0) {
        fprintf(stderr, "Unable to open %s\n", filename);
        return EXIT_FAILURE;
    }

    /* synchronize with a mutex */
    pthread_mutex_lock(&mymutex);


    /* May be set non-zero by end() function on failure */
    end_status = EXIT_SUCCESS;

    rc = swupdate_async_start(readimage, printstatus,
                end, dry_run);

    /* return if we've hit an error scenario */
    if (rc < 0) {
        fprintf(stderr, "swupdate_async_start returns %d\n", rc);
        pthread_mutex_unlock(&mymutex);
        close(fd);
        return EXIT_FAILURE;
    }

    /* Now block */
    pthread_mutex_lock(&mymutex);

    /* End called, unlock and exit */
    pthread_mutex_unlock(&mymutex);

    if (filename)
        close(fd);

    return end_status;
}



#endif // COMMON_DEF_H

//MainWindow.h

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "StartSwupdateThread.h"
#include "UpdateTextEditThread.h"
#include <QProcess>
#include <QSharedPointer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void StartSWUpdateSoftWare();
    void StartStartSh();

private slots:
    void on_btn_select_file_clicked();

    void on_btn_upgrade_clicked();

    void on_btn_cancel_clicked();

    void slot_update_textedit(QString text );

private:
    Ui::MainWindow *ui;

    StartSwupdateThread m_start_sw_thread;
    UpdateTextEditThread m_update_text_thread;

    QSharedPointer<QProcess> my_process{nullptr};

};
#endif // MAINWINDOW_H

 //network_ipc.h

/*
 * (C) Copyright 2008-2017
 * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
 * 	on behalf of ifm electronic GmbH
 *
 * SPDX-License-Identifier:     LGPL-2.1-or-later
 */

#ifndef _IPC_H
#define _IPC_H

#include <stdlib.h>
#include <stdbool.h>
#include "swupdate_status.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Be careful to include further headers here. This file is the interface
 * to external programs interfacing with SWUpdate as client, and further
 * headers are not exported.
 */

#define IPC_MAGIC		0x14052001

typedef enum {
	REQ_INSTALL,
	ACK,
	NACK,
	GET_STATUS,
	POST_UPDATE,
	SWUPDATE_SUBPROCESS,
	REQ_INSTALL_DRYRUN,
	SET_AES_KEY
} msgtype;

/*
 * Commands are used for IPC to subprocesses. The meaning is then interpreted
 * by the single subprocess
 */
enum {
	CMD_ACTIVATION,	/* this returns the answer if a SW can be activated */
	CMD_CONFIG,
	CMD_ENABLE	/* Enable or disable suricatta mode */
};

typedef union {
	char msg[128];
	struct { 
		int current;
		int last_result;
		int error;
		char desc[2048];
	} status;
	struct {
		sourcetype source; /* Who triggered the update */
		int	cmd;	   /* Optional encoded command */
		int	timeout;     /* timeout in seconds if an aswer is expected */
		unsigned int len;    /* Len of data valid in buf */
		char	buf[2048];   /*
				      * Buffer that each source can fill
				      * with additional information
				      */
	} instmsg;
	struct {
		char key_ascii[65]; /* Key size in ASCII (256 bit, 32 bytes bin) + termination */
		char ivt_ascii[33]; /* Key size in ASCII (16 bytes bin) + termination */
	} aeskeymsg;
} msgdata;
	
typedef struct {
	int magic;	/* magic number */
	int type;
	msgdata data;
} ipc_message;

char *get_ctrl_socket(void);
int ipc_inst_start(void);
int ipc_inst_start_ext(sourcetype source, size_t len, const char *info, bool dry_run);
int ipc_send_data(int connfd, char *buf, int size);
void ipc_end(int connfd);
int ipc_get_status(ipc_message *msg);
int ipc_get_status_timeout(ipc_message *msg, unsigned int timeout_ms);
int ipc_postupdate(ipc_message *msg);
int ipc_send_cmd(ipc_message *msg);

typedef int (*writedata)(char **buf, int *size);
typedef int (*getstatus)(ipc_message *msg);
typedef int (*terminated)(RECOVERY_STATUS status);
int ipc_wait_for_complete(getstatus callback);
int swupdate_image_write(char *buf, int size);
int swupdate_async_start(writedata wr_func, getstatus status_func,
				terminated end_func, bool dry_run);

#ifdef __cplusplus
}   // extern "C"
#endif

#endif

//StartSwupdateThread.h

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#ifndef STARTSWUPDATETHREAD_H
#define STARTSWUPDATETHREAD_H

#include <QObject>
#include <QThread>
#include <QDebug>

class StartSwupdateThread :public  QThread
{
    Q_OBJECT

public:
    StartSwupdateThread();
    ~StartSwupdateThread() override ;

    void run() override;

signals:
    void signal_start_status(QString str );

public:
    bool m_start_status{false};

};

#endif // STARTSWUPDATETHREAD_H

//swupdate_status.h

/*
 * (C) Copyright 2015-2017
 * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
 *
 * SPDX-License-Identifier:     LGPL-2.1-or-later
 */

#ifndef _SWUPDATE_STATUS_H
#define _SWUPDATE_STATUS_H

#ifdef __cplusplus
extern "C" {
#endif

/*
 * This is used to send back the result of an update.
 * It is strictly forbidden to change the order of entries.
 * New values should be put at the end without altering the order.
 */

typedef enum {
	IDLE,
	START,
	RUN,
	SUCCESS,
	FAILURE,
	DOWNLOAD,
	DONE,
	SUBPROCESS,
	PROGRESS,
} RECOVERY_STATUS;

typedef enum {
	SOURCE_UNKNOWN,
	SOURCE_WEBSERVER,
	SOURCE_SURICATTA,
	SOURCE_DOWNLOADER,
	SOURCE_LOCAL
} sourcetype;

#ifdef __cplusplus
}   // extern "C"
#endif

#endif

//UpdateTextEditThread.h

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#ifndef UPDATETEXTEDITTHREAD_H
#define UPDATETEXTEDITTHREAD_H

#include <QObject>
#include <QThread>
#include "common_def.h"


class UpdateTextEditThread : public QThread
{
    Q_OBJECT

public:
    UpdateTextEditThread();
    ~UpdateTextEditThread();

    void run() override;

signals:
    void signal_update_text(QString text);

public:
    bool m_is_stop{false};

};

#endif // UPDATETEXTEDITTHREAD_H

//MainWindow.cpp

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QFileDialog>
#include <QProcess>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(&m_update_text_thread, &UpdateTextEditThread::signal_update_text, this, &MainWindow::slot_update_textedit);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::StartSWUpdateSoftWare()
{
    QString program = "/home/xsf/demo/sbabic/swupdate/swupdate";
    QStringList arguments;
    arguments << " -w " << "\"--document-root ./examples/www/v2  --port 8080\" " ;

    if(!my_process)
    my_process = QSharedPointer< QProcess>::create();

    my_process->start(program,arguments);
    my_process->waitForStarted();
    qDebug().noquote() << __FUNCTION__ << arguments<<my_process->arguments()  ;
    qDebug() << __FUNCTION__ << my_process->processId() << my_process->state()<< my_process->pid() ;

}

void MainWindow::StartStartSh()
{

    QString cmd = "/home/xsf/temp/QtProjects/Q5_9_C_Demo/UpgradeDemo/start_sw.sh" ;
//    system(cmd.toStdString().c_str());

        QString program = "./start_sw.h";

        if(!my_process)
        {
            my_process = QSharedPointer< QProcess>::create(this);
            my_process->setEnvironment(my_process->environment());
        }

        my_process->start("sh " + cmd/*program*/);
        my_process->waitForStarted();
        qDebug().noquote() << __FUNCTION__ <<my_process->arguments()  ;
        qDebug() << __FUNCTION__ << my_process->processId() << my_process->state()<< my_process->pid() ;


}


void MainWindow::on_btn_select_file_clicked()
{
    QString str =  QFileDialog::getOpenFileName(this,tr("select file"),"/home/xsf/demo/sbabic/swupdate/xsf_test");
    ui->swu_file_path->setText(str);
}

void MainWindow::on_btn_upgrade_clicked()
{
    if(ui->swu_file_path->text().isEmpty())
    {
        qDebug() << "ui->swu_file_path->text().isEmpty()";
        return;
    }

    ///solution 1
    //    StartSWUpdateSoftWare();

    ///solution 2
    //    if(!m_start_sw_thread.isRunning())
    //    {
    //        m_start_sw_thread.start();
    //    }
    //    m_start_sw_thread.wait();

    ///solution 3
      StartStartSh();

      usleep(5000000);

    //solution 4
        if(!m_update_text_thread.isRunning())
        {
            m_update_text_thread.start();
        }
        m_update_text_thread.wait();

        qDebug() << __FUNCTION__ << my_process->processId() << my_process->state()<< my_process->pid() ;
//        my_process->kill();
//        my_process->terminate();
        system("killall swupdate");
        usleep(1000000);

        qDebug() << __FUNCTION__ << my_process->processId() << my_process->state()<< my_process->pid() ;

}

void MainWindow::on_btn_cancel_clicked()
{
    close();
}

void MainWindow::slot_update_textedit(QString text)
{
  ui->textedit->append(text);
}

StartSwupdateThread.cpp

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#include "StartSwupdateThread.h"

StartSwupdateThread::StartSwupdateThread()
{

}

StartSwupdateThread::~StartSwupdateThread()
{

}

void StartSwupdateThread::run()
{
//    QString cmd  ;
//    cmd = "/home/xsf/demo/sbabic/swupdate/swupdate -w \"--document-root ./examples/www/v2  --port 8080\" " ;

//    qDebug() <<__FUNCTION__ ;
//    system(cmd.toStdString().c_str());

    QString cmd = "/home/xsf/temp/QtProjects/Q5_9_C_Demo/UpgradeDemo/start_sw.sh" ;
    system(cmd.toStdString().c_str());

    qDebug() <<__FUNCTION__ ;

}

UpdateTextEditThread.cpp

/***********************************
*@file
*@brief
*@author
*@e-mail:
*@company
*@date
************************************/
#include "UpdateTextEditThread.h"
#include <QDebug>

UpdateTextEditThread::UpdateTextEditThread()
{

}

UpdateTextEditThread::~UpdateTextEditThread()
{

}

void UpdateTextEditThread::run()
{
    if (!m_is_stop) {
        QString str = "Start Upgrade " ;
        qDebug() << __FUNCTION__ << str ;
        emit signal_update_text(str);

        pthread_mutex_init(&mymutex, NULL);

        QString swu_file = "/home/xsf/demo/sbabic/swupdate/xsf_test/my-software_1.0.swu";
        int ret =  send_file(swu_file.toStdString().c_str());
        qDebug() << __FUNCTION__ <<" send_file ret value :"<< ret ;
        str = ret ==0 ? "Upgrade success !" : "Upgrade fail!" ;
        emit signal_update_text(str);


        usleep(1000000);

        m_is_stop = true ;

    }
}

 start_sw.sh

cd /home/xsf/demo/sbabic/swupdate
echo "this is start_sw.sh file"
killall swupdate  
/home/xsf/demo/sbabic/swupdate/swupdate -w "--document-root ./examples/www/v2  --port 8080"

create .swu file

 

 

///MakeFile

CONTAINER_VER="1.0"
PRODUCT_NAME="my-software"
FILES="sw-description 1.txt 2.txt 3.txt   "
for i in $FILES;do
        echo $i;done | cpio -ov -H crc >  ${PRODUCT_NAME}_${CONTAINER_VER}.swu

///sw-description

software =
{
        version = "0.1.0";
        description = "Firmware update for XXXXX Project";

        hardware-compatibility: [ "1.0", "1.2", "1.3"];

        files: (
                {
                        filename = "1.txt";
                        path = "/home/xsf/test/1.txt";
                },

                {
                        filename = "2.txt";
                        path = "/home/xsf/test/2.txt";
                } ,   
  
               {
                        filename = "3.txt";
                        path = "/home/xsf/test/3.txt";
                }
        );


}
swupdate success status

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值