SWUpdate library to be used with RPC.

Fork of SWUpdate by David Smart

SWUpdate.cpp

Committer:
WiredHome
Date:
2014-06-14
Revision:
3:c69fff55fc60
Parent:
1:208de08b1a19
Child:
7:a7efbae7e02e

File content as of revision 3:c69fff55fc60:


// Software Update via Ethernet from forum - 
// http://mbed.org/forum/mbed/topic/1183/
//
#include "mbed.h"
#include "SWUpdate.h"
#include "HTTPClient.h"
#include "HTTPText.h"
#include "HTTPFile.h"
#include <stdio.h>

extern "C" void mbed_reset();

#define DEBUG "SWup"
#include <cstdio>
#if (defined(DEBUG) && !defined(TARGET_LPC11U24))
#define DBG(x, ...)  std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
#define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
#else
#define DBG(x, ...)
#define WARN(x, ...)
#define ERR(x, ...)
#define INFO(x, ...)
#endif

static bool PassesIntegrityCheck(const char * fname, int cksum, int fsize) {
    int res = false;    // assume things go wrong...
    int newCksum = 0;
    int newFSize = 0;
    FILE *fh = fopen(fname, "rb");
    INFO("IntegrityCheck(%s,%d,%d)", fname, cksum, fsize);
    if (fh) {
        char buf;
        while (fread(&buf, 1, 1, fh)) {
            newCksum = (newCksum + buf) & 0xFFFF;
            newFSize++;
        }
        fclose(fh);
        INFO("      Check(...,%d,%d)", newCksum, newFSize);
        if (newCksum == cksum && newFSize == fsize)
            res = true;
    } else {
        WARN("failed to open %s.", fname);
    }
    return res;
}

bool SoftwareUpdate(const char *url, const char * name, Reboot_T reboot) {
    HTTPClient http;
    //http.setTimeout( 15000 ); 
    char fqurl[150];    // fully qualified url
    char verfn[32];     // local version file
    char fwfn[32];
    bool result = false;    // many things can go wrong, assume failure
    char buf[50];
        
    INFO("SoftwareUpdate(%s,%s)", url, name);
    snprintf(verfn, 32, "/local/%s.ver", name);

    /* Read installed version string */
    int inst_ver = -1;
    FILE *fv = fopen(verfn, "r");
    if (fv) {
        fscanf(fv, "%d", &inst_ver);
        fclose(fv);
    }
    INFO("  Installed version: %d", inst_ver);
    
    /* Download latest version string */
    HTTPText server_ver("test message");
    snprintf(fqurl, 150, "%s/%s.txt", url, name);
    HTTPResult r = http.get(fqurl, buf, sizeof(buf));
    if (r == HTTP_OK) {
        int latest_ver = -1;
        int cksum = 0;
        int fsize = 0;
        int parseCount;
        INFO("  read {%s}", buf);
        parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize);
        if (parseCount == 3) {
            INFO("  web version: %d", latest_ver);
            INFO("     checksum: %d", cksum);
            INFO("    file size: %d", fsize);
            if (inst_ver != latest_ver) {
                INFO("  Downloading firmware ver %d ...", latest_ver);
                sprintf(fwfn, "/local/%s%d.BIN", name, latest_ver);
                snprintf(fqurl, 150, "%s/%s.bin", url, name);
        
                HTTPFile latest(fwfn);
                r = http.get(fqurl, &latest);
                if (r == HTTP_OK) {
                    // Check the integrity of the freshly downloaded file,
                    // before swapping out the old version.
                    // ... to appear here ...
                    if (PassesIntegrityCheck(fwfn, cksum, fsize)) {
                        sprintf(fwfn, "/local/%s%d.BIN", name, inst_ver);
                        INFO("  Firmware downloaded, removing old version (%s).", fwfn);
                        if (remove(fwfn)) {
                            ERR("  *** Failed to remove old version. ***");
                        }
                        INFO("Updating stored version number.");
                        fv = fopen(verfn, "w");
                        if (fv) {
                            int fr = fputs(buf, fv);
                            if (fr < 0) {
                                ERR("Failed (%d) to update stored version number.", fr);
                                fclose( fv );
                            } else {
                                fclose( fv );
                                if (reboot == AUTO_REBOOT) {
                                    WARN("Resetting...\n");
                                    wait_ms(200);
                                    mbed_reset();
                                }
                                result = true;
                            }
                        } else {
                            WARN("Failed to update local version info in %s.", verfn);
                        }
                    } else {
                        WARN("New file {%s} did not pass integrity check.", fwfn);
                    }
                } else {
                    WARN("Failed to download lastest firmware.");
                }
            } else {
                WARN("Only %d parameters found in online version file.", parseCount);
            }
        }
    } else {
        WARN("Failed to download online firmware version number.");
    }
    return result;
}