sohaib qamar / SWUpdate_RPC

Fork of SWUpdate by David Smart

Committer:
WiredHome
Date:
Mon May 07 19:56:00 2018 +0000
Revision:
26:f2bb6061dcb3
Parent:
25:af99bdcca2b4
Added a method to get the current build number (SW version number).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:e221363f7942 1
WiredHome 17:1d318666246c 2 // Software Update via Ethernet from forum -
WiredHome 0:e221363f7942 3 // http://mbed.org/forum/mbed/topic/1183/
WiredHome 1:208de08b1a19 4 //
WiredHome 0:e221363f7942 5 #include "mbed.h"
WiredHome 0:e221363f7942 6 #include "SWUpdate.h"
WiredHome 0:e221363f7942 7 #include "HTTPFile.h"
WiredHome 0:e221363f7942 8 #include <stdio.h>
WiredHome 0:e221363f7942 9
WiredHome 0:e221363f7942 10 extern "C" void mbed_reset();
WiredHome 0:e221363f7942 11
WiredHome 15:49cc43dcbbf6 12 //#define DEBUG "SWup"
WiredHome 0:e221363f7942 13 #include <cstdio>
WiredHome 0:e221363f7942 14 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 0:e221363f7942 15 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 16 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 17 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 18 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:e221363f7942 19 #else
WiredHome 0:e221363f7942 20 #define DBG(x, ...)
WiredHome 0:e221363f7942 21 #define WARN(x, ...)
WiredHome 0:e221363f7942 22 #define ERR(x, ...)
WiredHome 0:e221363f7942 23 #define INFO(x, ...)
WiredHome 0:e221363f7942 24 #endif
WiredHome 0:e221363f7942 25
WiredHome 17:1d318666246c 26 static HTTPResult HTTPErrorCode;
WiredHome 17:1d318666246c 27
WiredHome 19:169aab9047bd 28 typedef enum {
WiredHome 19:169aab9047bd 29 ok,
WiredHome 19:169aab9047bd 30 no_file,
WiredHome 19:169aab9047bd 31 bad_crc
WiredHome 19:169aab9047bd 32 } Integrity_t;
WiredHome 19:169aab9047bd 33
WiredHome 24:e400edb8d2ee 34
WiredHome 24:e400edb8d2ee 35 const char * SWErrorMsg[] = {
WiredHome 24:e400edb8d2ee 36 "OK", // SWUP_OK = 0x00, ///< Software Update succeeded as planned.
WiredHome 24:e400edb8d2ee 37 "Same version", // SWUP_SAME_VER = 0x01, ///< Online version is the same as the installed version.
WiredHome 24:e400edb8d2ee 38 "Get bin error", // SWUP_HTTP_BIN = 0x02, ///< HTTP get returned an error while trying to fetch the bin file.
WiredHome 24:e400edb8d2ee 39 "Old file stuck", // SWUP_OLD_STUCK = 0x04, ///< Old file could not be removed.
WiredHome 24:e400edb8d2ee 40 "Old vers stuck", // SWUP_VER_STUCK = 0x08, ///< Old version number could not be updated.
WiredHome 24:e400edb8d2ee 41 "Ver write fail", // SWUP_VWRITE_FAILED = 0x10, ///< Can't open for write the version tracking file.
WiredHome 24:e400edb8d2ee 42 "Integrity fail", // SWUP_INTEGRITY_FAILED = 0x20, ///< Integrity check of downloaded file failed.
WiredHome 24:e400edb8d2ee 43 "Get ver fail", // SWUP_HTTP_VER = 0x40, ///< HTTP get returned an error while trying to fetch the version file.
WiredHome 24:e400edb8d2ee 44 "Filesys full", // SWUP_NO_SPACE = 0x80, ///< No space on file system for new version.
WiredHome 24:e400edb8d2ee 45 };
WiredHome 24:e400edb8d2ee 46
WiredHome 24:e400edb8d2ee 47 const char * SoftwareUpdateGetHTTPErrorMsg(HTTPResult r)
WiredHome 24:e400edb8d2ee 48 {
WiredHome 24:e400edb8d2ee 49 const char * p = "invalid result code";
WiredHome 25:af99bdcca2b4 50 if (r <= SWUP_NO_SPACE)
WiredHome 24:e400edb8d2ee 51 p = SWErrorMsg[r];
WiredHome 24:e400edb8d2ee 52 return p;
WiredHome 24:e400edb8d2ee 53 }
WiredHome 24:e400edb8d2ee 54
WiredHome 24:e400edb8d2ee 55 HTTPResult SoftwareUpdateGetHTTPErrorCode(void)
WiredHome 24:e400edb8d2ee 56 {
WiredHome 24:e400edb8d2ee 57 return HTTPErrorCode;
WiredHome 24:e400edb8d2ee 58 }
WiredHome 24:e400edb8d2ee 59
WiredHome 24:e400edb8d2ee 60
WiredHome 19:169aab9047bd 61 static Integrity_t PassesIntegrityCheck(const char * fname, int cksum, int fsize)
WiredHome 17:1d318666246c 62 {
WiredHome 19:169aab9047bd 63 Integrity_t res = bad_crc; // assume things go wrong...
WiredHome 3:c69fff55fc60 64 int newCksum = 0;
WiredHome 3:c69fff55fc60 65 int newFSize = 0;
WiredHome 3:c69fff55fc60 66 FILE *fh = fopen(fname, "rb");
WiredHome 17:1d318666246c 67
WiredHome 3:c69fff55fc60 68 INFO("IntegrityCheck(%s,%d,%d)", fname, cksum, fsize);
WiredHome 3:c69fff55fc60 69 if (fh) {
WiredHome 3:c69fff55fc60 70 char buf;
WiredHome 3:c69fff55fc60 71 while (fread(&buf, 1, 1, fh)) {
WiredHome 3:c69fff55fc60 72 newCksum = (newCksum + buf) & 0xFFFF;
WiredHome 3:c69fff55fc60 73 newFSize++;
WiredHome 3:c69fff55fc60 74 }
WiredHome 3:c69fff55fc60 75 fclose(fh);
WiredHome 3:c69fff55fc60 76 INFO(" Check(...,%d,%d)", newCksum, newFSize);
WiredHome 3:c69fff55fc60 77 if (newCksum == cksum && newFSize == fsize)
WiredHome 19:169aab9047bd 78 res = ok;
WiredHome 3:c69fff55fc60 79 } else {
WiredHome 3:c69fff55fc60 80 WARN("failed to open %s.", fname);
WiredHome 19:169aab9047bd 81 res = no_file;
WiredHome 3:c69fff55fc60 82 }
WiredHome 3:c69fff55fc60 83 return res;
WiredHome 1:208de08b1a19 84 }
WiredHome 1:208de08b1a19 85
WiredHome 9:73067ef14c30 86 /// mytolower exists because not all compiler libraries have this function
WiredHome 9:73067ef14c30 87 ///
WiredHome 9:73067ef14c30 88 /// This takes a character and if it is upper-case, it converts it to
WiredHome 9:73067ef14c30 89 /// lower-case and returns it.
WiredHome 9:73067ef14c30 90 ///
WiredHome 17:1d318666246c 91 /// @note this only works for characters in the range 'A' - 'Z'.
WiredHome 17:1d318666246c 92 ///
WiredHome 18:5f7667d63a27 93 /// a is the character to convert
WiredHome 18:5f7667d63a27 94 /// returns the lower case equivalent to the supplied character.
WiredHome 9:73067ef14c30 95 ///
WiredHome 17:1d318666246c 96 static char mytolower(char a)
WiredHome 17:1d318666246c 97 {
WiredHome 9:73067ef14c30 98 if (a >= 'A' && a <= 'Z')
WiredHome 9:73067ef14c30 99 return (a - 'A' + 'a');
WiredHome 9:73067ef14c30 100 else
WiredHome 9:73067ef14c30 101 return a;
WiredHome 9:73067ef14c30 102 }
WiredHome 9:73067ef14c30 103
WiredHome 9:73067ef14c30 104 /// mystrnicmp exists because not all compiler libraries have this function.
WiredHome 9:73067ef14c30 105 ///
WiredHome 9:73067ef14c30 106 /// Some have strnicmp, others _strnicmp, and others have C++ methods, which
WiredHome 9:73067ef14c30 107 /// is outside the scope of this C-portable set of functions.
WiredHome 9:73067ef14c30 108 ///
WiredHome 18:5f7667d63a27 109 /// l is a pointer to the string on the left
WiredHome 18:5f7667d63a27 110 /// r is a pointer to the string on the right
WiredHome 18:5f7667d63a27 111 /// n is the number of characters to compare
WiredHome 18:5f7667d63a27 112 /// returns -1 if l < r
WiredHome 18:5f7667d63a27 113 /// returns 0 if l == r
WiredHome 18:5f7667d63a27 114 /// returns +1 if l > r
WiredHome 9:73067ef14c30 115 ///
WiredHome 17:1d318666246c 116 static int mystrnicmp(const char *l, const char *r, size_t n)
WiredHome 17:1d318666246c 117 {
WiredHome 9:73067ef14c30 118 int result = 0;
WiredHome 9:73067ef14c30 119
WiredHome 9:73067ef14c30 120 if (n != 0) {
WiredHome 9:73067ef14c30 121 do {
WiredHome 9:73067ef14c30 122 result = mytolower(*l++) - mytolower(*r++);
WiredHome 9:73067ef14c30 123 } while ((result == 0) && (*l != '\0') && (--n > 0));
WiredHome 9:73067ef14c30 124 }
WiredHome 9:73067ef14c30 125 if (result < -1)
WiredHome 9:73067ef14c30 126 result = -1;
WiredHome 9:73067ef14c30 127 else if (result > 1)
WiredHome 9:73067ef14c30 128 result = 1;
WiredHome 9:73067ef14c30 129 return result;
WiredHome 9:73067ef14c30 130 }
WiredHome 9:73067ef14c30 131
WiredHome 9:73067ef14c30 132
WiredHome 17:1d318666246c 133 // Scan the local file system for any .bin files and
WiredHome 9:73067ef14c30 134 // if they don't match the current one, remove them.
WiredHome 9:73067ef14c30 135 //
WiredHome 9:73067ef14c30 136 static bool RemoveOtherBinFiles(const char * name, int ver)
WiredHome 9:73067ef14c30 137 {
WiredHome 9:73067ef14c30 138 char curbin[SW_MAX_FQFN];
WiredHome 9:73067ef14c30 139 DIR *d;
WiredHome 9:73067ef14c30 140 struct dirent *p;
WiredHome 9:73067ef14c30 141 bool noFailed = true;
WiredHome 17:1d318666246c 142
WiredHome 17:1d318666246c 143 snprintf(curbin, SW_MAX_FQFN, "%s%02d.bin", name, (ver % 100));
WiredHome 9:73067ef14c30 144 INFO("Remove bin files excluding {%s}", curbin);
WiredHome 9:73067ef14c30 145 d = opendir("/local/");
WiredHome 9:73067ef14c30 146 // Get a directory handle
WiredHome 9:73067ef14c30 147 if ( d != NULL ) {
WiredHome 9:73067ef14c30 148 // Walk the directory
WiredHome 9:73067ef14c30 149 while ( (p = readdir(d)) != NULL ) {
WiredHome 9:73067ef14c30 150 INFO(" check {%s}", p->d_name);
WiredHome 9:73067ef14c30 151 // if the file is .bin and not curbin
WiredHome 9:73067ef14c30 152 if (0 == mystrnicmp(p->d_name + strlen(p->d_name) - 4, ".bin", 4)
WiredHome 17:1d318666246c 153 && (0 != mystrnicmp(p->d_name, curbin, strlen(curbin)))) {
WiredHome 9:73067ef14c30 154 // remove the file
WiredHome 9:73067ef14c30 155 char toremove[SW_MAX_FQFN];
WiredHome 9:73067ef14c30 156 snprintf(toremove, SW_MAX_FQFN, "/local/%s", p->d_name);
WiredHome 9:73067ef14c30 157 INFO(" removing %s.", toremove);
WiredHome 9:73067ef14c30 158 if (remove(toremove)) {
WiredHome 9:73067ef14c30 159 // set flag if it could not be removed
WiredHome 9:73067ef14c30 160 noFailed = false;
WiredHome 9:73067ef14c30 161 }
WiredHome 9:73067ef14c30 162 }
WiredHome 9:73067ef14c30 163 }
WiredHome 9:73067ef14c30 164 closedir(d);
WiredHome 9:73067ef14c30 165 }
WiredHome 9:73067ef14c30 166 return noFailed;
WiredHome 9:73067ef14c30 167 }
WiredHome 9:73067ef14c30 168
WiredHome 26:f2bb6061dcb3 169
WiredHome 26:f2bb6061dcb3 170 int GetSoftwareVersionNumber(const char * name)
WiredHome 17:1d318666246c 171 {
WiredHome 26:f2bb6061dcb3 172 char nameroot[7];
WiredHome 9:73067ef14c30 173 char verfn[SW_MAX_FQFN]; // local version file
WiredHome 26:f2bb6061dcb3 174
WiredHome 16:de99e872fc9d 175 strncpy(nameroot, name, 6);
WiredHome 16:de99e872fc9d 176 nameroot[6] = '\0';
WiredHome 16:de99e872fc9d 177 snprintf(verfn, SW_MAX_FQFN, "/local/%s.ver", nameroot);
WiredHome 0:e221363f7942 178
WiredHome 0:e221363f7942 179 /* Read installed version string */
WiredHome 0:e221363f7942 180 int inst_ver = -1;
WiredHome 0:e221363f7942 181 FILE *fv = fopen(verfn, "r");
WiredHome 0:e221363f7942 182 if (fv) {
WiredHome 0:e221363f7942 183 fscanf(fv, "%d", &inst_ver);
WiredHome 0:e221363f7942 184 fclose(fv);
WiredHome 26:f2bb6061dcb3 185 } else {
WiredHome 26:f2bb6061dcb3 186 inst_ver = -1;
WiredHome 0:e221363f7942 187 }
WiredHome 0:e221363f7942 188 INFO(" Installed version: %d", inst_ver);
WiredHome 26:f2bb6061dcb3 189 return inst_ver;
WiredHome 26:f2bb6061dcb3 190 }
WiredHome 17:1d318666246c 191
WiredHome 26:f2bb6061dcb3 192 bool SetSoftwareVersionNumber(const char * name, int ver, int cksum, int filesize)
WiredHome 26:f2bb6061dcb3 193 {
WiredHome 26:f2bb6061dcb3 194 char nameroot[7];
WiredHome 26:f2bb6061dcb3 195 char verfn[SW_MAX_FQFN]; // local version file
WiredHome 26:f2bb6061dcb3 196 char buf[40];
WiredHome 26:f2bb6061dcb3 197
WiredHome 26:f2bb6061dcb3 198 strncpy(nameroot, name, 6);
WiredHome 26:f2bb6061dcb3 199 nameroot[6] = '\0';
WiredHome 26:f2bb6061dcb3 200 snprintf(verfn, SW_MAX_FQFN, "/local/%s.ver", nameroot);
WiredHome 26:f2bb6061dcb3 201 snprintf(buf, 40, "%d,%d,%d", ver, cksum, filesize);
WiredHome 26:f2bb6061dcb3 202 FILE *fv = fopen(verfn, "w");
WiredHome 26:f2bb6061dcb3 203 if (fv) {
WiredHome 26:f2bb6061dcb3 204 int fr = fputs(buf, fv);
WiredHome 26:f2bb6061dcb3 205 fclose( fv );
WiredHome 26:f2bb6061dcb3 206 if (fr >= 0) {
WiredHome 26:f2bb6061dcb3 207 return true;
WiredHome 26:f2bb6061dcb3 208 } else {
WiredHome 26:f2bb6061dcb3 209 ERR("Failed (%d) to update stored version number.", fr);
WiredHome 26:f2bb6061dcb3 210 }
WiredHome 26:f2bb6061dcb3 211 } else {
WiredHome 26:f2bb6061dcb3 212 WARN("Failed to update local version info in %s.", verfn);
WiredHome 26:f2bb6061dcb3 213 }
WiredHome 26:f2bb6061dcb3 214 return false;
WiredHome 26:f2bb6061dcb3 215 }
WiredHome 26:f2bb6061dcb3 216
WiredHome 26:f2bb6061dcb3 217 SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action)
WiredHome 26:f2bb6061dcb3 218 {
WiredHome 26:f2bb6061dcb3 219 HTTPClient http;
WiredHome 26:f2bb6061dcb3 220 //http.setTimeout( 15000 );
WiredHome 26:f2bb6061dcb3 221 char fqurl[SW_MAX_URL]; // fully qualified url
WiredHome 26:f2bb6061dcb3 222 char fwfn[SW_MAX_FQFN];
WiredHome 26:f2bb6061dcb3 223 char nameroot[7];
WiredHome 26:f2bb6061dcb3 224 uint16_t result = SWUP_OK; // starting out quite optimistic, for all the things that can go wrong
WiredHome 26:f2bb6061dcb3 225 char buf[50]; // long enough for 3 comma separated numbers...
WiredHome 26:f2bb6061dcb3 226
WiredHome 26:f2bb6061dcb3 227 INFO("SoftwareUpdate(%s , %s)", url, name);
WiredHome 26:f2bb6061dcb3 228 strncpy(nameroot, name, 6);
WiredHome 26:f2bb6061dcb3 229 nameroot[6] = '\0';
WiredHome 26:f2bb6061dcb3 230 int inst_ver = GetSoftwareVersionNumber(name);
WiredHome 0:e221363f7942 231 /* Download latest version string */
WiredHome 21:253e7da56ff9 232 //HTTPText server_ver("test message");
WiredHome 9:73067ef14c30 233 snprintf(fqurl, SW_MAX_URL, "%s/%s.txt", url, name);
WiredHome 23:cfe84db2b2cb 234 INFO("Query %s", fqurl);
WiredHome 17:1d318666246c 235 HTTPErrorCode = http.get(fqurl, buf, sizeof(buf));
WiredHome 17:1d318666246c 236 if (HTTPErrorCode == HTTP_OK) {
WiredHome 0:e221363f7942 237 int latest_ver = -1;
WiredHome 3:c69fff55fc60 238 int cksum = 0;
WiredHome 3:c69fff55fc60 239 int fsize = 0;
WiredHome 3:c69fff55fc60 240 int parseCount;
WiredHome 3:c69fff55fc60 241 parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize);
WiredHome 3:c69fff55fc60 242 if (parseCount == 3) {
WiredHome 9:73067ef14c30 243 INFO(" web version: %d", latest_ver);
WiredHome 9:73067ef14c30 244 INFO(" checksum: %d", cksum);
WiredHome 9:73067ef14c30 245 INFO(" file size: %d", fsize);
WiredHome 3:c69fff55fc60 246 if (inst_ver != latest_ver) {
WiredHome 3:c69fff55fc60 247 INFO(" Downloading firmware ver %d ...", latest_ver);
WiredHome 22:2a010efe00da 248 snprintf(fwfn, SW_MAX_FQFN, "/local/%s%02d.BIN", nameroot, (latest_ver % 100));
WiredHome 22:2a010efe00da 249 snprintf(fqurl, SW_MAX_URL, "%s/%s.bin", url, name);
WiredHome 17:1d318666246c 250
WiredHome 3:c69fff55fc60 251 HTTPFile latest(fwfn);
WiredHome 23:cfe84db2b2cb 252 INFO("Fetch %s", fqurl);
WiredHome 17:1d318666246c 253 HTTPErrorCode = http.get(fqurl, &latest);
WiredHome 17:1d318666246c 254 if (HTTPErrorCode == HTTP_OK) {
WiredHome 19:169aab9047bd 255 Integrity_t t = PassesIntegrityCheck(fwfn, cksum, fsize);
WiredHome 19:169aab9047bd 256 if (t == no_file) {
WiredHome 19:169aab9047bd 257 ERR(" *** No space on file system. ***");
WiredHome 19:169aab9047bd 258 result |= SWUP_NO_SPACE;
WiredHome 19:169aab9047bd 259 } else if (t == ok) {
WiredHome 16:de99e872fc9d 260 if (!RemoveOtherBinFiles(nameroot, latest_ver)) {
WiredHome 9:73067ef14c30 261 ERR(" *** Failed to remove old version(s). ***");
WiredHome 9:73067ef14c30 262 result |= SWUP_OLD_STUCK;
WiredHome 3:c69fff55fc60 263 }
WiredHome 3:c69fff55fc60 264 INFO("Updating stored version number.");
WiredHome 26:f2bb6061dcb3 265 if (SetSoftwareVersionNumber(name, latest_ver, cksum, fsize)) {
WiredHome 26:f2bb6061dcb3 266 // ok
WiredHome 26:f2bb6061dcb3 267 if (action == AUTO_REBOOT) {
WiredHome 26:f2bb6061dcb3 268 WARN("Resetting...\n");
WiredHome 26:f2bb6061dcb3 269 wait_ms(200);
WiredHome 26:f2bb6061dcb3 270 mbed_reset();
WiredHome 3:c69fff55fc60 271 }
WiredHome 1:208de08b1a19 272 } else {
WiredHome 26:f2bb6061dcb3 273 // failed
WiredHome 26:f2bb6061dcb3 274 ERR("Failed to update stored version number.");
WiredHome 9:73067ef14c30 275 result |= SWUP_VWRITE_FAILED;
WiredHome 1:208de08b1a19 276 }
WiredHome 19:169aab9047bd 277 } else /* t == bad_crc */ {
WiredHome 3:c69fff55fc60 278 WARN("New file {%s} did not pass integrity check.", fwfn);
WiredHome 9:73067ef14c30 279 result |= SWUP_INTEGRITY_FAILED;
WiredHome 0:e221363f7942 280 }
WiredHome 1:208de08b1a19 281 } else {
WiredHome 3:c69fff55fc60 282 WARN("Failed to download lastest firmware.");
WiredHome 17:1d318666246c 283 result |= SWUP_HTTP_BIN;
WiredHome 0:e221363f7942 284 }
WiredHome 0:e221363f7942 285 } else {
WiredHome 9:73067ef14c30 286 INFO("Online version is same as installed version.");
WiredHome 9:73067ef14c30 287 result |= SWUP_SAME_VER;
WiredHome 0:e221363f7942 288 }
WiredHome 0:e221363f7942 289 }
WiredHome 0:e221363f7942 290 } else {
WiredHome 22:2a010efe00da 291 WARN("Failed accessing {%s}. Extended Error Code = %d", fqurl, HTTPErrorCode);
WiredHome 17:1d318666246c 292 result |= SWUP_HTTP_VER;
WiredHome 0:e221363f7942 293 }
WiredHome 9:73067ef14c30 294 return (SWUpdate_T)result;
WiredHome 0:e221363f7942 295 }