The FirmwareUpdater is a mbed firmware update library with HTTP server on cloud.

Dependents:   FirmwareUpdater_TestProgram geigercounter04 firm LPC1768_up_frim

Committer:
shintamainjp
Date:
Wed Nov 03 12:57:51 2010 +0000
Revision:
0:f9bdb06ab672
Child:
1:0305a8120f06
Initial version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shintamainjp 0:f9bdb06ab672 1 /**
shintamainjp 0:f9bdb06ab672 2 * =============================================================================
shintamainjp 0:f9bdb06ab672 3 * Firmware updater (Version 0.0.1)
shintamainjp 0:f9bdb06ab672 4 * =============================================================================
shintamainjp 0:f9bdb06ab672 5 * Copyright (c) 2010 Shinichiro Nakamura (CuBeatSystems)
shintamainjp 0:f9bdb06ab672 6 *
shintamainjp 0:f9bdb06ab672 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
shintamainjp 0:f9bdb06ab672 8 * of this software and associated documentation files (the "Software"), to deal
shintamainjp 0:f9bdb06ab672 9 * in the Software without restriction, including without limitation the rights
shintamainjp 0:f9bdb06ab672 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
shintamainjp 0:f9bdb06ab672 11 * copies of the Software, and to permit persons to whom the Software is
shintamainjp 0:f9bdb06ab672 12 * furnished to do so, subject to the following conditions:
shintamainjp 0:f9bdb06ab672 13 *
shintamainjp 0:f9bdb06ab672 14 * The above copyright notice and this permission notice shall be included in
shintamainjp 0:f9bdb06ab672 15 * all copies or substantial portions of the Software.
shintamainjp 0:f9bdb06ab672 16 *
shintamainjp 0:f9bdb06ab672 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
shintamainjp 0:f9bdb06ab672 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
shintamainjp 0:f9bdb06ab672 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
shintamainjp 0:f9bdb06ab672 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
shintamainjp 0:f9bdb06ab672 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
shintamainjp 0:f9bdb06ab672 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
shintamainjp 0:f9bdb06ab672 23 * THE SOFTWARE.
shintamainjp 0:f9bdb06ab672 24 * =============================================================================
shintamainjp 0:f9bdb06ab672 25 */
shintamainjp 0:f9bdb06ab672 26
shintamainjp 0:f9bdb06ab672 27 #include "FirmwareUpdater.h"
shintamainjp 0:f9bdb06ab672 28
shintamainjp 0:f9bdb06ab672 29 #include <stdio.h>
shintamainjp 0:f9bdb06ab672 30 #include <stdarg.h>
shintamainjp 0:f9bdb06ab672 31
shintamainjp 0:f9bdb06ab672 32 extern "C" void mbed_reset();
shintamainjp 0:f9bdb06ab672 33
shintamainjp 0:f9bdb06ab672 34 const std::string FirmwareUpdater::EXT_BIN = ".bin";
shintamainjp 0:f9bdb06ab672 35 const std::string FirmwareUpdater::EXT_BINTMP = ".b__";
shintamainjp 0:f9bdb06ab672 36 const std::string FirmwareUpdater::EXT_TXT = ".txt";
shintamainjp 0:f9bdb06ab672 37 const std::string FirmwareUpdater::EXT_TXTTMP = ".t__";
shintamainjp 0:f9bdb06ab672 38
shintamainjp 0:f9bdb06ab672 39 /**
shintamainjp 0:f9bdb06ab672 40 * Create.
shintamainjp 0:f9bdb06ab672 41 *
shintamainjp 0:f9bdb06ab672 42 * @param url URL for firmware. Do not include a target file name.
shintamainjp 0:f9bdb06ab672 43 * @param name An application name. Do not include a extention.
shintamainjp 0:f9bdb06ab672 44 * @param log True if logging.
shintamainjp 0:f9bdb06ab672 45 */
shintamainjp 0:f9bdb06ab672 46 FirmwareUpdater::FirmwareUpdater(std::string url, std::string name, bool log)
shintamainjp 0:f9bdb06ab672 47 : url(url), name(name), log(log), local("local") {
shintamainjp 0:f9bdb06ab672 48 client.setTimeout(10000);
shintamainjp 0:f9bdb06ab672 49
shintamainjp 0:f9bdb06ab672 50 /*
shintamainjp 0:f9bdb06ab672 51 * A file name on the mbed local file system should keep '8 + 3' types of name.
shintamainjp 0:f9bdb06ab672 52 */
shintamainjp 0:f9bdb06ab672 53 if (name.length() > 8) {
shintamainjp 0:f9bdb06ab672 54 printf("Invalid firmware name '%s' found. The maximum length is 8.\n", name.c_str());
shintamainjp 0:f9bdb06ab672 55 LOG("Invalid firmware name '%s' found. The maximum length is 8.\n", name.c_str());
shintamainjp 0:f9bdb06ab672 56 }
shintamainjp 0:f9bdb06ab672 57 }
shintamainjp 0:f9bdb06ab672 58
shintamainjp 0:f9bdb06ab672 59 /**
shintamainjp 0:f9bdb06ab672 60 * Dispose.
shintamainjp 0:f9bdb06ab672 61 */
shintamainjp 0:f9bdb06ab672 62 FirmwareUpdater::~FirmwareUpdater() {
shintamainjp 0:f9bdb06ab672 63 }
shintamainjp 0:f9bdb06ab672 64
shintamainjp 0:f9bdb06ab672 65 /**
shintamainjp 0:f9bdb06ab672 66 * Get a URL.
shintamainjp 0:f9bdb06ab672 67 *
shintamainjp 0:f9bdb06ab672 68 * @return URL.
shintamainjp 0:f9bdb06ab672 69 */
shintamainjp 0:f9bdb06ab672 70 const std::string FirmwareUpdater:: getURL() const {
shintamainjp 0:f9bdb06ab672 71 return url;
shintamainjp 0:f9bdb06ab672 72 }
shintamainjp 0:f9bdb06ab672 73
shintamainjp 0:f9bdb06ab672 74 /**
shintamainjp 0:f9bdb06ab672 75 * Get a name.
shintamainjp 0:f9bdb06ab672 76 *
shintamainjp 0:f9bdb06ab672 77 * @return name.
shintamainjp 0:f9bdb06ab672 78 */
shintamainjp 0:f9bdb06ab672 79 const std::string FirmwareUpdater:: getName() const {
shintamainjp 0:f9bdb06ab672 80 return name;
shintamainjp 0:f9bdb06ab672 81 }
shintamainjp 0:f9bdb06ab672 82
shintamainjp 0:f9bdb06ab672 83 /**
shintamainjp 0:f9bdb06ab672 84 * Checking a new firmware.
shintamainjp 0:f9bdb06ab672 85 * Compare versions of the software between local storage on mbed and on webserver.
shintamainjp 0:f9bdb06ab672 86 *
shintamainjp 0:f9bdb06ab672 87 * @return Return 0 if a new firmware exists.
shintamainjp 0:f9bdb06ab672 88 */
shintamainjp 0:f9bdb06ab672 89 int FirmwareUpdater::exist() {
shintamainjp 0:f9bdb06ab672 90 int ver_local, ver_server;
shintamainjp 0:f9bdb06ab672 91
shintamainjp 0:f9bdb06ab672 92 /*
shintamainjp 0:f9bdb06ab672 93 * Fetch the version from a local.
shintamainjp 0:f9bdb06ab672 94 */
shintamainjp 0:f9bdb06ab672 95 {
shintamainjp 0:f9bdb06ab672 96 std::string file_local = "/local/" + name + EXT_TXT;
shintamainjp 0:f9bdb06ab672 97 FILE *fp = fopen(file_local.c_str(), "rb");
shintamainjp 0:f9bdb06ab672 98 if (fp == NULL) {
shintamainjp 0:f9bdb06ab672 99 LOG("Local firmware version file '%s' open failed.\n", file_local.c_str());
shintamainjp 0:f9bdb06ab672 100 return -1;
shintamainjp 0:f9bdb06ab672 101 }
shintamainjp 0:f9bdb06ab672 102 if (fscanf(fp, "%d", &ver_local) != 1) {
shintamainjp 0:f9bdb06ab672 103 LOG("Local firmware version file '%s' is invalid.\n", file_local.c_str());
shintamainjp 0:f9bdb06ab672 104 return -2;
shintamainjp 0:f9bdb06ab672 105 }
shintamainjp 0:f9bdb06ab672 106 fclose(fp);
shintamainjp 0:f9bdb06ab672 107 LOG("Local firmware version is %d. (%s)\n", ver_local, file_local.c_str());
shintamainjp 0:f9bdb06ab672 108 }
shintamainjp 0:f9bdb06ab672 109 /*
shintamainjp 0:f9bdb06ab672 110 * Fetch the version from a server.
shintamainjp 0:f9bdb06ab672 111 */
shintamainjp 0:f9bdb06ab672 112 {
shintamainjp 0:f9bdb06ab672 113 std::string file_server = url + "/" + name + EXT_TXT;
shintamainjp 0:f9bdb06ab672 114 HTTPText text;
shintamainjp 0:f9bdb06ab672 115 HTTPResult r = client.get(file_server.c_str(), &text);
shintamainjp 0:f9bdb06ab672 116 if (r != HTTP_OK) {
shintamainjp 0:f9bdb06ab672 117 LOG("Server firmware version file '%s' open failed.\n", file_server.c_str());
shintamainjp 0:f9bdb06ab672 118 return -3;
shintamainjp 0:f9bdb06ab672 119 }
shintamainjp 0:f9bdb06ab672 120 if (sscanf(text.gets(), "%d", &ver_server) != 1) {
shintamainjp 0:f9bdb06ab672 121 LOG("Server firmware version file '%s' is invalid.\n", file_server.c_str());
shintamainjp 0:f9bdb06ab672 122 return -4;
shintamainjp 0:f9bdb06ab672 123 }
shintamainjp 0:f9bdb06ab672 124 LOG("Server firmware version is %d. (%s)\n", ver_server, file_server.c_str());
shintamainjp 0:f9bdb06ab672 125 }
shintamainjp 0:f9bdb06ab672 126
shintamainjp 0:f9bdb06ab672 127 return (ver_local < ver_server) ? 0 : 1;
shintamainjp 0:f9bdb06ab672 128 }
shintamainjp 0:f9bdb06ab672 129
shintamainjp 0:f9bdb06ab672 130 /**
shintamainjp 0:f9bdb06ab672 131 * Execute update.
shintamainjp 0:f9bdb06ab672 132 *
shintamainjp 0:f9bdb06ab672 133 * @return Return 0 if it succeed.
shintamainjp 0:f9bdb06ab672 134 */
shintamainjp 0:f9bdb06ab672 135 int FirmwareUpdater::execute() {
shintamainjp 0:f9bdb06ab672 136 /*
shintamainjp 0:f9bdb06ab672 137 * Fetch the files.
shintamainjp 0:f9bdb06ab672 138 */
shintamainjp 0:f9bdb06ab672 139 std::string serv_txt = url + "/" + name + EXT_TXT;
shintamainjp 0:f9bdb06ab672 140 std::string serv_bin = url + "/" + name + EXT_BIN;
shintamainjp 0:f9bdb06ab672 141 std::string file_txttmp = "/local/" + name + EXT_TXTTMP;
shintamainjp 0:f9bdb06ab672 142 std::string file_bintmp = "/local/" + name + EXT_BINTMP;
shintamainjp 0:f9bdb06ab672 143 if (fetch(serv_txt, file_txttmp) != 0) {
shintamainjp 0:f9bdb06ab672 144 return -1;
shintamainjp 0:f9bdb06ab672 145 }
shintamainjp 0:f9bdb06ab672 146 if (fetch(serv_bin, file_bintmp) != 0) {
shintamainjp 0:f9bdb06ab672 147 return -2;
shintamainjp 0:f9bdb06ab672 148 }
shintamainjp 0:f9bdb06ab672 149 /*
shintamainjp 0:f9bdb06ab672 150 * Copy it.
shintamainjp 0:f9bdb06ab672 151 */
shintamainjp 0:f9bdb06ab672 152 std::string file_txt = "/local/" + name + EXT_TXT;
shintamainjp 0:f9bdb06ab672 153 std::string file_bin = "/local/" + name + EXT_BIN;
shintamainjp 0:f9bdb06ab672 154 if (copy(file_txttmp, file_txt) != 0) {
shintamainjp 0:f9bdb06ab672 155 return -3;
shintamainjp 0:f9bdb06ab672 156 }
shintamainjp 0:f9bdb06ab672 157 if (copy(file_bintmp, file_bin) != 0) {
shintamainjp 0:f9bdb06ab672 158 return -4;
shintamainjp 0:f9bdb06ab672 159 }
shintamainjp 0:f9bdb06ab672 160 /*
shintamainjp 0:f9bdb06ab672 161 * Delete the temporary files.
shintamainjp 0:f9bdb06ab672 162 */
shintamainjp 0:f9bdb06ab672 163 remove(file_txttmp.c_str());
shintamainjp 0:f9bdb06ab672 164 remove(file_bintmp.c_str());
shintamainjp 0:f9bdb06ab672 165 return 0;
shintamainjp 0:f9bdb06ab672 166 }
shintamainjp 0:f9bdb06ab672 167
shintamainjp 0:f9bdb06ab672 168 /**
shintamainjp 0:f9bdb06ab672 169 * Reset system.
shintamainjp 0:f9bdb06ab672 170 */
shintamainjp 0:f9bdb06ab672 171 void FirmwareUpdater::reset() {
shintamainjp 0:f9bdb06ab672 172 mbed_reset();
shintamainjp 0:f9bdb06ab672 173 }
shintamainjp 0:f9bdb06ab672 174
shintamainjp 0:f9bdb06ab672 175 /**
shintamainjp 0:f9bdb06ab672 176 * Fetch a file.
shintamainjp 0:f9bdb06ab672 177 *
shintamainjp 0:f9bdb06ab672 178 * @param src_url URL of a source file.
shintamainjp 0:f9bdb06ab672 179 * @param local_file Local file name.
shintamainjp 0:f9bdb06ab672 180 *
shintamainjp 0:f9bdb06ab672 181 * @return Return 0 if it succeed.
shintamainjp 0:f9bdb06ab672 182 */
shintamainjp 0:f9bdb06ab672 183 int FirmwareUpdater::fetch(std::string src_url, std::string local_file) {
shintamainjp 0:f9bdb06ab672 184 /*
shintamainjp 0:f9bdb06ab672 185 * Fetch the source file from URL to a temporary file on local.
shintamainjp 0:f9bdb06ab672 186 */
shintamainjp 0:f9bdb06ab672 187 HTTPFile file(local_file.c_str());
shintamainjp 0:f9bdb06ab672 188 int r = client.get(src_url.c_str(), &file);
shintamainjp 0:f9bdb06ab672 189 if (r != HTTP_OK) {
shintamainjp 0:f9bdb06ab672 190 LOG("Fetch '%s' from '%s' failed.\n", local_file.c_str(), src_url.c_str());
shintamainjp 0:f9bdb06ab672 191 return -1;
shintamainjp 0:f9bdb06ab672 192 }
shintamainjp 0:f9bdb06ab672 193 LOG("Fetch '%s' from '%s' succeed.\n", local_file.c_str(), src_url.c_str());
shintamainjp 0:f9bdb06ab672 194 return 0;
shintamainjp 0:f9bdb06ab672 195 }
shintamainjp 0:f9bdb06ab672 196
shintamainjp 0:f9bdb06ab672 197 /**
shintamainjp 0:f9bdb06ab672 198 * Copy a file.
shintamainjp 0:f9bdb06ab672 199 *
shintamainjp 0:f9bdb06ab672 200 * @param local_file1 Source file.
shintamainjp 0:f9bdb06ab672 201 * @param local_file2 Destination file.
shintamainjp 0:f9bdb06ab672 202 *
shintamainjp 0:f9bdb06ab672 203 * @return Return 0 if it succeed.
shintamainjp 0:f9bdb06ab672 204 */
shintamainjp 0:f9bdb06ab672 205 int FirmwareUpdater::copy(std::string local_file1, std::string local_file2) {
shintamainjp 0:f9bdb06ab672 206
shintamainjp 0:f9bdb06ab672 207 LOG("File copying... (%s->%s)\n", local_file1.c_str(), local_file2.c_str());
shintamainjp 0:f9bdb06ab672 208
shintamainjp 0:f9bdb06ab672 209 FILE *rp = fopen(local_file1.c_str(), "rb");
shintamainjp 0:f9bdb06ab672 210 if (rp == NULL) {
shintamainjp 0:f9bdb06ab672 211 LOG("File '%s' open failed.\n", local_file1.c_str());
shintamainjp 0:f9bdb06ab672 212 return -1;
shintamainjp 0:f9bdb06ab672 213 }
shintamainjp 0:f9bdb06ab672 214 remove(local_file2.c_str());
shintamainjp 0:f9bdb06ab672 215 FILE *wp = fopen(local_file2.c_str(), "wb");
shintamainjp 0:f9bdb06ab672 216 if (wp == NULL) {
shintamainjp 0:f9bdb06ab672 217 LOG("File '%s' open failed.\n", local_file2.c_str());
shintamainjp 0:f9bdb06ab672 218 fclose(rp);
shintamainjp 0:f9bdb06ab672 219 return -2;
shintamainjp 0:f9bdb06ab672 220 }
shintamainjp 0:f9bdb06ab672 221 int c;
shintamainjp 0:f9bdb06ab672 222 while ((c = fgetc(rp)) != EOF) {
shintamainjp 0:f9bdb06ab672 223 fputc(c, wp);
shintamainjp 0:f9bdb06ab672 224 }
shintamainjp 0:f9bdb06ab672 225 fclose(rp);
shintamainjp 0:f9bdb06ab672 226 fclose(wp);
shintamainjp 0:f9bdb06ab672 227 LOG("File copied. (%s->%s)\n", local_file1.c_str(), local_file2.c_str());
shintamainjp 0:f9bdb06ab672 228 return 0;
shintamainjp 0:f9bdb06ab672 229 }
shintamainjp 0:f9bdb06ab672 230
shintamainjp 0:f9bdb06ab672 231 /**
shintamainjp 0:f9bdb06ab672 232 * Output a message to a log file.
shintamainjp 0:f9bdb06ab672 233 *
shintamainjp 0:f9bdb06ab672 234 * @param format ...
shintamainjp 0:f9bdb06ab672 235 */
shintamainjp 0:f9bdb06ab672 236 void FirmwareUpdater::LOG(const char* format, ...) {
shintamainjp 0:f9bdb06ab672 237 if (log) {
shintamainjp 0:f9bdb06ab672 238 FILE *fplog = fopen("/local/update.log", "a");
shintamainjp 0:f9bdb06ab672 239 if (fplog != NULL) {
shintamainjp 0:f9bdb06ab672 240 char buf[BUFSIZ];
shintamainjp 0:f9bdb06ab672 241 va_list p;
shintamainjp 0:f9bdb06ab672 242 va_start(p, format);
shintamainjp 0:f9bdb06ab672 243 vsnprintf(buf, sizeof(buf) - 1, format, p);
shintamainjp 0:f9bdb06ab672 244 fprintf(fplog, "%s", buf);
shintamainjp 0:f9bdb06ab672 245 va_end(p);
shintamainjp 0:f9bdb06ab672 246 fclose(fplog);
shintamainjp 0:f9bdb06ab672 247 }
shintamainjp 0:f9bdb06ab672 248 }
shintamainjp 0:f9bdb06ab672 249 }