SWUpdate library to be used with RPC.

Fork of SWUpdate by David Smart

Committer:
sohaibqamar
Date:
Fri Oct 05 07:15:29 2018 +0000
Revision:
27:c7b275023106
Parent:
19:169aab9047bd
Child:
21:253e7da56ff9
To be used the SWUpdate with RPC.

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