sohaib qamar / SWUpdate_RPC

Fork of SWUpdate by David Smart

Committer:
WiredHome
Date:
Fri Nov 10 12:32:04 2017 +0000
Revision:
24:e400edb8d2ee
Parent:
23:cfe84db2b2cb
Child:
25:af99bdcca2b4
Add a method to translate an error code into text string

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 24:e400edb8d2ee 50 if (r >= 0 && 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 17:1d318666246c 169 SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action)
WiredHome 17:1d318666246c 170 {
WiredHome 0:e221363f7942 171 HTTPClient http;
WiredHome 17:1d318666246c 172 //http.setTimeout( 15000 );
WiredHome 9:73067ef14c30 173 char fqurl[SW_MAX_URL]; // fully qualified url
WiredHome 9:73067ef14c30 174 char verfn[SW_MAX_FQFN]; // local version file
WiredHome 9:73067ef14c30 175 char fwfn[SW_MAX_FQFN];
WiredHome 16:de99e872fc9d 176 char nameroot[7];
WiredHome 9:73067ef14c30 177 uint16_t result = SWUP_OK; // starting out quite optimistic, for all the things that can go wrong
WiredHome 9:73067ef14c30 178 char buf[50]; // long enough for 3 comma separated numbers...
WiredHome 17:1d318666246c 179
WiredHome 22:2a010efe00da 180 INFO("SoftwareUpdate(%s , %s)", url, name);
WiredHome 16:de99e872fc9d 181 strncpy(nameroot, name, 6);
WiredHome 16:de99e872fc9d 182 nameroot[6] = '\0';
WiredHome 16:de99e872fc9d 183 snprintf(verfn, SW_MAX_FQFN, "/local/%s.ver", nameroot);
WiredHome 0:e221363f7942 184
WiredHome 0:e221363f7942 185 /* Read installed version string */
WiredHome 0:e221363f7942 186 int inst_ver = -1;
WiredHome 0:e221363f7942 187 FILE *fv = fopen(verfn, "r");
WiredHome 0:e221363f7942 188 if (fv) {
WiredHome 0:e221363f7942 189 fscanf(fv, "%d", &inst_ver);
WiredHome 0:e221363f7942 190 fclose(fv);
WiredHome 0:e221363f7942 191 }
WiredHome 0:e221363f7942 192 INFO(" Installed version: %d", inst_ver);
WiredHome 17:1d318666246c 193
WiredHome 0:e221363f7942 194 /* Download latest version string */
WiredHome 21:253e7da56ff9 195 //HTTPText server_ver("test message");
WiredHome 9:73067ef14c30 196 snprintf(fqurl, SW_MAX_URL, "%s/%s.txt", url, name);
WiredHome 23:cfe84db2b2cb 197 INFO("Query %s", fqurl);
WiredHome 17:1d318666246c 198 HTTPErrorCode = http.get(fqurl, buf, sizeof(buf));
WiredHome 17:1d318666246c 199 if (HTTPErrorCode == HTTP_OK) {
WiredHome 0:e221363f7942 200 int latest_ver = -1;
WiredHome 3:c69fff55fc60 201 int cksum = 0;
WiredHome 3:c69fff55fc60 202 int fsize = 0;
WiredHome 3:c69fff55fc60 203 int parseCount;
WiredHome 3:c69fff55fc60 204 parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize);
WiredHome 3:c69fff55fc60 205 if (parseCount == 3) {
WiredHome 9:73067ef14c30 206 INFO(" web version: %d", latest_ver);
WiredHome 9:73067ef14c30 207 INFO(" checksum: %d", cksum);
WiredHome 9:73067ef14c30 208 INFO(" file size: %d", fsize);
WiredHome 3:c69fff55fc60 209 if (inst_ver != latest_ver) {
WiredHome 3:c69fff55fc60 210 INFO(" Downloading firmware ver %d ...", latest_ver);
WiredHome 22:2a010efe00da 211 snprintf(fwfn, SW_MAX_FQFN, "/local/%s%02d.BIN", nameroot, (latest_ver % 100));
WiredHome 22:2a010efe00da 212 snprintf(fqurl, SW_MAX_URL, "%s/%s.bin", url, name);
WiredHome 17:1d318666246c 213
WiredHome 3:c69fff55fc60 214 HTTPFile latest(fwfn);
WiredHome 23:cfe84db2b2cb 215 INFO("Fetch %s", fqurl);
WiredHome 17:1d318666246c 216 HTTPErrorCode = http.get(fqurl, &latest);
WiredHome 17:1d318666246c 217 if (HTTPErrorCode == HTTP_OK) {
WiredHome 19:169aab9047bd 218 Integrity_t t = PassesIntegrityCheck(fwfn, cksum, fsize);
WiredHome 19:169aab9047bd 219 if (t == no_file) {
WiredHome 19:169aab9047bd 220 ERR(" *** No space on file system. ***");
WiredHome 19:169aab9047bd 221 result |= SWUP_NO_SPACE;
WiredHome 19:169aab9047bd 222 } else if (t == ok) {
WiredHome 16:de99e872fc9d 223 if (!RemoveOtherBinFiles(nameroot, latest_ver)) {
WiredHome 9:73067ef14c30 224 ERR(" *** Failed to remove old version(s). ***");
WiredHome 9:73067ef14c30 225 result |= SWUP_OLD_STUCK;
WiredHome 3:c69fff55fc60 226 }
WiredHome 3:c69fff55fc60 227 INFO("Updating stored version number.");
WiredHome 3:c69fff55fc60 228 fv = fopen(verfn, "w");
WiredHome 3:c69fff55fc60 229 if (fv) {
WiredHome 3:c69fff55fc60 230 int fr = fputs(buf, fv);
WiredHome 3:c69fff55fc60 231 if (fr < 0) {
WiredHome 3:c69fff55fc60 232 ERR("Failed (%d) to update stored version number.", fr);
WiredHome 3:c69fff55fc60 233 fclose( fv );
WiredHome 9:73067ef14c30 234 result |= SWUP_VER_STUCK;
WiredHome 3:c69fff55fc60 235 } else {
WiredHome 3:c69fff55fc60 236 fclose( fv );
WiredHome 9:73067ef14c30 237 if (action == AUTO_REBOOT) {
WiredHome 3:c69fff55fc60 238 WARN("Resetting...\n");
WiredHome 3:c69fff55fc60 239 wait_ms(200);
WiredHome 3:c69fff55fc60 240 mbed_reset();
WiredHome 3:c69fff55fc60 241 }
WiredHome 3:c69fff55fc60 242 }
WiredHome 1:208de08b1a19 243 } else {
WiredHome 3:c69fff55fc60 244 WARN("Failed to update local version info in %s.", verfn);
WiredHome 9:73067ef14c30 245 result |= SWUP_VWRITE_FAILED;
WiredHome 1:208de08b1a19 246 }
WiredHome 19:169aab9047bd 247 } else /* t == bad_crc */ {
WiredHome 3:c69fff55fc60 248 WARN("New file {%s} did not pass integrity check.", fwfn);
WiredHome 9:73067ef14c30 249 result |= SWUP_INTEGRITY_FAILED;
WiredHome 0:e221363f7942 250 }
WiredHome 1:208de08b1a19 251 } else {
WiredHome 3:c69fff55fc60 252 WARN("Failed to download lastest firmware.");
WiredHome 17:1d318666246c 253 result |= SWUP_HTTP_BIN;
WiredHome 0:e221363f7942 254 }
WiredHome 0:e221363f7942 255 } else {
WiredHome 9:73067ef14c30 256 INFO("Online version is same as installed version.");
WiredHome 9:73067ef14c30 257 result |= SWUP_SAME_VER;
WiredHome 0:e221363f7942 258 }
WiredHome 0:e221363f7942 259 }
WiredHome 0:e221363f7942 260 } else {
WiredHome 22:2a010efe00da 261 WARN("Failed accessing {%s}. Extended Error Code = %d", fqurl, HTTPErrorCode);
WiredHome 17:1d318666246c 262 result |= SWUP_HTTP_VER;
WiredHome 0:e221363f7942 263 }
WiredHome 9:73067ef14c30 264 return (SWUpdate_T)result;
WiredHome 0:e221363f7942 265 }