Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SWUpdate by
SWUpdate.cpp@14:0e012d53c6df, 2014-06-27 (annotated)
- Committer:
- WiredHome
- Date:
- Fri Jun 27 20:57:23 2014 +0000
- Revision:
- 14:0e012d53c6df
- Parent:
- 9:73067ef14c30
- Child:
- 15:49cc43dcbbf6
bin file must be 8-chars total, so revised the example to have a shorter filename, and sequence number to be 2 digit, not 3.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:e221363f7942 | 1 | |
WiredHome | 0:e221363f7942 | 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 "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 | 14:0e012d53c6df | 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 | 3:c69fff55fc60 | 28 | static bool PassesIntegrityCheck(const char * fname, int cksum, int fsize) { |
WiredHome | 3:c69fff55fc60 | 29 | int res = false; // assume things go wrong... |
WiredHome | 3:c69fff55fc60 | 30 | int newCksum = 0; |
WiredHome | 3:c69fff55fc60 | 31 | int newFSize = 0; |
WiredHome | 3:c69fff55fc60 | 32 | FILE *fh = fopen(fname, "rb"); |
WiredHome | 9:73067ef14c30 | 33 | |
WiredHome | 3:c69fff55fc60 | 34 | INFO("IntegrityCheck(%s,%d,%d)", fname, cksum, fsize); |
WiredHome | 3:c69fff55fc60 | 35 | if (fh) { |
WiredHome | 3:c69fff55fc60 | 36 | char buf; |
WiredHome | 3:c69fff55fc60 | 37 | while (fread(&buf, 1, 1, fh)) { |
WiredHome | 3:c69fff55fc60 | 38 | newCksum = (newCksum + buf) & 0xFFFF; |
WiredHome | 3:c69fff55fc60 | 39 | newFSize++; |
WiredHome | 3:c69fff55fc60 | 40 | } |
WiredHome | 3:c69fff55fc60 | 41 | fclose(fh); |
WiredHome | 3:c69fff55fc60 | 42 | INFO(" Check(...,%d,%d)", newCksum, newFSize); |
WiredHome | 3:c69fff55fc60 | 43 | if (newCksum == cksum && newFSize == fsize) |
WiredHome | 3:c69fff55fc60 | 44 | res = true; |
WiredHome | 3:c69fff55fc60 | 45 | } else { |
WiredHome | 3:c69fff55fc60 | 46 | WARN("failed to open %s.", fname); |
WiredHome | 3:c69fff55fc60 | 47 | } |
WiredHome | 3:c69fff55fc60 | 48 | return res; |
WiredHome | 1:208de08b1a19 | 49 | } |
WiredHome | 1:208de08b1a19 | 50 | |
WiredHome | 9:73067ef14c30 | 51 | /// mytolower exists because not all compiler libraries have this function |
WiredHome | 9:73067ef14c30 | 52 | /// |
WiredHome | 9:73067ef14c30 | 53 | /// This takes a character and if it is upper-case, it converts it to |
WiredHome | 9:73067ef14c30 | 54 | /// lower-case and returns it. |
WiredHome | 9:73067ef14c30 | 55 | /// |
WiredHome | 9:73067ef14c30 | 56 | /// @param a is the character to convert |
WiredHome | 9:73067ef14c30 | 57 | /// @returns the lower case equivalent to a |
WiredHome | 9:73067ef14c30 | 58 | /// |
WiredHome | 9:73067ef14c30 | 59 | static char mytolower(char a) { |
WiredHome | 9:73067ef14c30 | 60 | if (a >= 'A' && a <= 'Z') |
WiredHome | 9:73067ef14c30 | 61 | return (a - 'A' + 'a'); |
WiredHome | 9:73067ef14c30 | 62 | else |
WiredHome | 9:73067ef14c30 | 63 | return a; |
WiredHome | 9:73067ef14c30 | 64 | } |
WiredHome | 9:73067ef14c30 | 65 | |
WiredHome | 9:73067ef14c30 | 66 | /// mystrnicmp exists because not all compiler libraries have this function. |
WiredHome | 9:73067ef14c30 | 67 | /// |
WiredHome | 9:73067ef14c30 | 68 | /// Some have strnicmp, others _strnicmp, and others have C++ methods, which |
WiredHome | 9:73067ef14c30 | 69 | /// is outside the scope of this C-portable set of functions. |
WiredHome | 9:73067ef14c30 | 70 | /// |
WiredHome | 9:73067ef14c30 | 71 | /// @param l is a pointer to the string on the left |
WiredHome | 9:73067ef14c30 | 72 | /// @param r is a pointer to the string on the right |
WiredHome | 9:73067ef14c30 | 73 | /// @param n is the number of characters to compare |
WiredHome | 9:73067ef14c30 | 74 | /// @returns -1 if l < r |
WiredHome | 9:73067ef14c30 | 75 | /// @returns 0 if l == r |
WiredHome | 9:73067ef14c30 | 76 | /// @returns +1 if l > r |
WiredHome | 9:73067ef14c30 | 77 | /// |
WiredHome | 9:73067ef14c30 | 78 | static int mystrnicmp(const char *l, const char *r, size_t n) { |
WiredHome | 9:73067ef14c30 | 79 | int result = 0; |
WiredHome | 9:73067ef14c30 | 80 | |
WiredHome | 9:73067ef14c30 | 81 | if (n != 0) { |
WiredHome | 9:73067ef14c30 | 82 | do { |
WiredHome | 9:73067ef14c30 | 83 | result = mytolower(*l++) - mytolower(*r++); |
WiredHome | 9:73067ef14c30 | 84 | } while ((result == 0) && (*l != '\0') && (--n > 0)); |
WiredHome | 9:73067ef14c30 | 85 | } |
WiredHome | 9:73067ef14c30 | 86 | if (result < -1) |
WiredHome | 9:73067ef14c30 | 87 | result = -1; |
WiredHome | 9:73067ef14c30 | 88 | else if (result > 1) |
WiredHome | 9:73067ef14c30 | 89 | result = 1; |
WiredHome | 9:73067ef14c30 | 90 | return result; |
WiredHome | 9:73067ef14c30 | 91 | } |
WiredHome | 9:73067ef14c30 | 92 | |
WiredHome | 9:73067ef14c30 | 93 | |
WiredHome | 9:73067ef14c30 | 94 | // Scan the local file system for any .bin files and |
WiredHome | 9:73067ef14c30 | 95 | // if they don't match the current one, remove them. |
WiredHome | 9:73067ef14c30 | 96 | // |
WiredHome | 9:73067ef14c30 | 97 | static bool RemoveOtherBinFiles(const char * name, int ver) |
WiredHome | 9:73067ef14c30 | 98 | { |
WiredHome | 9:73067ef14c30 | 99 | char curbin[SW_MAX_FQFN]; |
WiredHome | 9:73067ef14c30 | 100 | DIR *d; |
WiredHome | 9:73067ef14c30 | 101 | struct dirent *p; |
WiredHome | 9:73067ef14c30 | 102 | bool noFailed = true; |
WiredHome | 9:73067ef14c30 | 103 | |
WiredHome | 14:0e012d53c6df | 104 | snprintf(curbin, SW_MAX_FQFN, "%s%02d.bin", name, ver); |
WiredHome | 9:73067ef14c30 | 105 | INFO("Remove bin files excluding {%s}", curbin); |
WiredHome | 9:73067ef14c30 | 106 | d = opendir("/local/"); |
WiredHome | 9:73067ef14c30 | 107 | // Get a directory handle |
WiredHome | 9:73067ef14c30 | 108 | if ( d != NULL ) { |
WiredHome | 9:73067ef14c30 | 109 | // Walk the directory |
WiredHome | 9:73067ef14c30 | 110 | while ( (p = readdir(d)) != NULL ) { |
WiredHome | 9:73067ef14c30 | 111 | INFO(" check {%s}", p->d_name); |
WiredHome | 9:73067ef14c30 | 112 | // if the file is .bin and not curbin |
WiredHome | 9:73067ef14c30 | 113 | if (0 == mystrnicmp(p->d_name + strlen(p->d_name) - 4, ".bin", 4) |
WiredHome | 9:73067ef14c30 | 114 | && (0 != mystrnicmp(p->d_name, curbin, strlen(curbin)))) { |
WiredHome | 9:73067ef14c30 | 115 | // remove the file |
WiredHome | 9:73067ef14c30 | 116 | char toremove[SW_MAX_FQFN]; |
WiredHome | 9:73067ef14c30 | 117 | snprintf(toremove, SW_MAX_FQFN, "/local/%s", p->d_name); |
WiredHome | 9:73067ef14c30 | 118 | INFO(" removing %s.", toremove); |
WiredHome | 9:73067ef14c30 | 119 | if (remove(toremove)) { |
WiredHome | 9:73067ef14c30 | 120 | // set flag if it could not be removed |
WiredHome | 9:73067ef14c30 | 121 | noFailed = false; |
WiredHome | 9:73067ef14c30 | 122 | } |
WiredHome | 9:73067ef14c30 | 123 | } |
WiredHome | 9:73067ef14c30 | 124 | } |
WiredHome | 9:73067ef14c30 | 125 | closedir(d); |
WiredHome | 9:73067ef14c30 | 126 | } |
WiredHome | 9:73067ef14c30 | 127 | return noFailed; |
WiredHome | 9:73067ef14c30 | 128 | } |
WiredHome | 9:73067ef14c30 | 129 | |
WiredHome | 9:73067ef14c30 | 130 | SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action) { |
WiredHome | 0:e221363f7942 | 131 | HTTPClient http; |
WiredHome | 0:e221363f7942 | 132 | //http.setTimeout( 15000 ); |
WiredHome | 9:73067ef14c30 | 133 | char fqurl[SW_MAX_URL]; // fully qualified url |
WiredHome | 9:73067ef14c30 | 134 | char verfn[SW_MAX_FQFN]; // local version file |
WiredHome | 9:73067ef14c30 | 135 | char fwfn[SW_MAX_FQFN]; |
WiredHome | 9:73067ef14c30 | 136 | uint16_t result = SWUP_OK; // starting out quite optimistic, for all the things that can go wrong |
WiredHome | 9:73067ef14c30 | 137 | char buf[50]; // long enough for 3 comma separated numbers... |
WiredHome | 0:e221363f7942 | 138 | |
WiredHome | 0:e221363f7942 | 139 | INFO("SoftwareUpdate(%s,%s)", url, name); |
WiredHome | 9:73067ef14c30 | 140 | snprintf(verfn, SW_MAX_FQFN, "/local/%s.ver", name); |
WiredHome | 0:e221363f7942 | 141 | |
WiredHome | 0:e221363f7942 | 142 | /* Read installed version string */ |
WiredHome | 0:e221363f7942 | 143 | int inst_ver = -1; |
WiredHome | 0:e221363f7942 | 144 | FILE *fv = fopen(verfn, "r"); |
WiredHome | 0:e221363f7942 | 145 | if (fv) { |
WiredHome | 0:e221363f7942 | 146 | fscanf(fv, "%d", &inst_ver); |
WiredHome | 0:e221363f7942 | 147 | fclose(fv); |
WiredHome | 0:e221363f7942 | 148 | } |
WiredHome | 0:e221363f7942 | 149 | INFO(" Installed version: %d", inst_ver); |
WiredHome | 0:e221363f7942 | 150 | |
WiredHome | 0:e221363f7942 | 151 | /* Download latest version string */ |
WiredHome | 0:e221363f7942 | 152 | HTTPText server_ver("test message"); |
WiredHome | 9:73067ef14c30 | 153 | snprintf(fqurl, SW_MAX_URL, "%s/%s.txt", url, name); |
WiredHome | 0:e221363f7942 | 154 | HTTPResult r = http.get(fqurl, buf, sizeof(buf)); |
WiredHome | 0:e221363f7942 | 155 | if (r == HTTP_OK) { |
WiredHome | 0:e221363f7942 | 156 | int latest_ver = -1; |
WiredHome | 3:c69fff55fc60 | 157 | int cksum = 0; |
WiredHome | 3:c69fff55fc60 | 158 | int fsize = 0; |
WiredHome | 3:c69fff55fc60 | 159 | int parseCount; |
WiredHome | 3:c69fff55fc60 | 160 | parseCount = sscanf(buf, "%d,%d,%d", &latest_ver, &cksum, &fsize); |
WiredHome | 3:c69fff55fc60 | 161 | if (parseCount == 3) { |
WiredHome | 9:73067ef14c30 | 162 | INFO(" web version: %d", latest_ver); |
WiredHome | 9:73067ef14c30 | 163 | INFO(" checksum: %d", cksum); |
WiredHome | 9:73067ef14c30 | 164 | INFO(" file size: %d", fsize); |
WiredHome | 3:c69fff55fc60 | 165 | if (inst_ver != latest_ver) { |
WiredHome | 3:c69fff55fc60 | 166 | INFO(" Downloading firmware ver %d ...", latest_ver); |
WiredHome | 14:0e012d53c6df | 167 | sprintf(fwfn, "/local/%s%02d.BIN", name, latest_ver); |
WiredHome | 3:c69fff55fc60 | 168 | snprintf(fqurl, 150, "%s/%s.bin", url, name); |
WiredHome | 3:c69fff55fc60 | 169 | |
WiredHome | 3:c69fff55fc60 | 170 | HTTPFile latest(fwfn); |
WiredHome | 3:c69fff55fc60 | 171 | r = http.get(fqurl, &latest); |
WiredHome | 3:c69fff55fc60 | 172 | if (r == HTTP_OK) { |
WiredHome | 3:c69fff55fc60 | 173 | if (PassesIntegrityCheck(fwfn, cksum, fsize)) { |
WiredHome | 9:73067ef14c30 | 174 | if (!RemoveOtherBinFiles(name, latest_ver)) { |
WiredHome | 9:73067ef14c30 | 175 | ERR(" *** Failed to remove old version(s). ***"); |
WiredHome | 9:73067ef14c30 | 176 | result |= SWUP_OLD_STUCK; |
WiredHome | 3:c69fff55fc60 | 177 | } |
WiredHome | 3:c69fff55fc60 | 178 | INFO("Updating stored version number."); |
WiredHome | 3:c69fff55fc60 | 179 | fv = fopen(verfn, "w"); |
WiredHome | 3:c69fff55fc60 | 180 | if (fv) { |
WiredHome | 3:c69fff55fc60 | 181 | int fr = fputs(buf, fv); |
WiredHome | 3:c69fff55fc60 | 182 | if (fr < 0) { |
WiredHome | 3:c69fff55fc60 | 183 | ERR("Failed (%d) to update stored version number.", fr); |
WiredHome | 3:c69fff55fc60 | 184 | fclose( fv ); |
WiredHome | 9:73067ef14c30 | 185 | result |= SWUP_VER_STUCK; |
WiredHome | 3:c69fff55fc60 | 186 | } else { |
WiredHome | 3:c69fff55fc60 | 187 | fclose( fv ); |
WiredHome | 9:73067ef14c30 | 188 | if (action == AUTO_REBOOT) { |
WiredHome | 3:c69fff55fc60 | 189 | WARN("Resetting...\n"); |
WiredHome | 3:c69fff55fc60 | 190 | wait_ms(200); |
WiredHome | 3:c69fff55fc60 | 191 | mbed_reset(); |
WiredHome | 3:c69fff55fc60 | 192 | } |
WiredHome | 3:c69fff55fc60 | 193 | } |
WiredHome | 1:208de08b1a19 | 194 | } else { |
WiredHome | 3:c69fff55fc60 | 195 | WARN("Failed to update local version info in %s.", verfn); |
WiredHome | 9:73067ef14c30 | 196 | result |= SWUP_VWRITE_FAILED; |
WiredHome | 1:208de08b1a19 | 197 | } |
WiredHome | 0:e221363f7942 | 198 | } else { |
WiredHome | 3:c69fff55fc60 | 199 | WARN("New file {%s} did not pass integrity check.", fwfn); |
WiredHome | 9:73067ef14c30 | 200 | result |= SWUP_INTEGRITY_FAILED; |
WiredHome | 0:e221363f7942 | 201 | } |
WiredHome | 1:208de08b1a19 | 202 | } else { |
WiredHome | 3:c69fff55fc60 | 203 | WARN("Failed to download lastest firmware."); |
WiredHome | 9:73067ef14c30 | 204 | result |= SWUP_BAD_URL; |
WiredHome | 0:e221363f7942 | 205 | } |
WiredHome | 0:e221363f7942 | 206 | } else { |
WiredHome | 9:73067ef14c30 | 207 | INFO("Online version is same as installed version."); |
WiredHome | 9:73067ef14c30 | 208 | result |= SWUP_SAME_VER; |
WiredHome | 0:e221363f7942 | 209 | } |
WiredHome | 0:e221363f7942 | 210 | } |
WiredHome | 0:e221363f7942 | 211 | } else { |
WiredHome | 1:208de08b1a19 | 212 | WARN("Failed to download online firmware version number."); |
WiredHome | 9:73067ef14c30 | 213 | result |= SWUP_HTTP_ERR; |
WiredHome | 0:e221363f7942 | 214 | } |
WiredHome | 9:73067ef14c30 | 215 | return (SWUpdate_T)result; |
WiredHome | 0:e221363f7942 | 216 | } |