]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/net/blip/nwprog/DelugePatchP.nc
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / tos / lib / net / blip / nwprog / DelugePatchP.nc
diff --git a/tos/lib/net/blip/nwprog/DelugePatchP.nc b/tos/lib/net/blip/nwprog/DelugePatchP.nc
new file mode 100644 (file)
index 0000000..d2c7878
--- /dev/null
@@ -0,0 +1,244 @@
+/* Copyright (c) 2007 Johns Hopkins University.
+*  All rights reserved.
+*
+*  Permission to use, copy, modify, and distribute this software and its
+*  documentation for any purpose, without fee, and without written
+*  agreement is hereby granted, provided that the above copyright
+*  notice, the (updated) modification history and the author appear in
+*  all copies of this source code.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+*  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+*  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+*  OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+*  THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#include "imgNum2volumeId.h"
+
+module DelugePatchP
+{
+  provides interface DelugePatch[uint8_t client];
+  uses {
+    interface BlockRead[uint8_t volumeId];
+    interface BlockWrite[uint8_t volumeId];
+    interface StorageMap[uint8_t volumeId];
+    event void storageReady();
+  }
+}
+
+implementation
+{
+  enum {
+    S_READ_IDENT,
+    S_READY,
+    S_BUSY,
+    S_READ_PATCH_CMD,
+    S_READ_PATCH_DATA, 
+    S_READ_PATCH_COPY,
+    S_WRITE_PATCH,
+  };
+
+  DelugeIdent ident;
+  DelugePatchCmd patch;
+
+  uint8_t patchData[MAX_PATCH_DATA_SIZE];
+
+  uint8_t state;
+  uint8_t currentClient;
+
+  uint16_t patchNumLinesRead;
+  uint16_t patchNumLines;
+
+  uint32_t patchByteAddr;  
+  uint8_t patchVolume;
+  uint8_t patchImageIdx;
+  uint8_t patchPage;
+
+  uint32_t dstByteAddr;  
+  uint8_t srcVolume;
+  uint8_t srcImageIdx;
+  uint8_t srcPage;
+
+  uint32_t dstByteAddr;  
+  uint8_t dstVolume;
+  uint8_t dstImageIdx;
+  uint8_t dstPage;
+
+
+  void setStorageReady()
+  {
+    signal storageReady();
+    state = S_READY;
+  }
+
+  void notifySuccess() 
+  {
+    signal DelugePatch.decodePatchDone[currentClient](
+            patchImageIdx, srcImageIdx, dstImageIdx, SUCCESS);
+    setStorageReady();
+  }
+
+  void notifyFailure(error_t error)
+  {
+    signal DelugePatch.decodePatchDone[currentClient](
+            patchImageIdx, srcImageIdx, dstImageIdx, error);
+    setStorageReady();
+  }
+
+  command error_t DelugePatch.decodePatch[uint8_t client](uint8_t imgNumPatch,
+                                                          uint8_t imgNumSrc,
+                                                          uint8_t imgNumDst)
+  {
+    patchImageIdx = imgNumPatch;
+    patchVolume   = _imgNum2volumeId[patchImageIdx];
+    srcImageIdx   = imgNumSrc;
+    srcVolume     = _imgNum2volumeId[srcImageIdx];
+    dstImageIdx   = imgNumDst;
+    dstVolume     = _imgNum2volumeId[dstImageIdx];
+
+    // First, read the DelugeIdent section.
+    if (patchImageIdx < DELUGE_NUM_VOLUMES) {
+      state = S_READ_IDENT;
+      call BlockRead.read[patchVolume](0, &ident, sizeof(ident));
+    } else {
+      signal storageReady();
+      state = S_READY;
+    }
+
+    return SUCCESS;
+  }
+
+  event void BlockRead.readDone[uint8_t imgNum](
+    storage_addr_t addr, void* buf, storage_len_t len, error_t error)
+  {
+    switch (state) {
+    case S_BUSY:
+      notifyFailure(error);
+      break;
+    // Read the DelugeIdent structure into ident.
+    // If it is valid, ident.userhash contains
+    // number of patch command lines.
+    // Initialize patchByteAddr to the beginning of
+    // the patch commands.
+    case S_READ_IDENT:
+      if (error == SUCCESS) {
+        if (ident.uidhash != DELUGE_INVALID_UID) {
+          patchNumLines = ident.userhash;
+          state = S_READ_PATCH_CMD;
+          patchByteAddr = DELUGE_IDENT_SIZE + DELUGE_CRC_BLOCK_SIZE; 
+          call BlockRead.read[patchVolume](patchByteAddr, &patch, sizeof(patch)); 
+          break;
+        } 
+      }
+      notifyFailure(error);
+      break;
+    // Read a patch command.
+    // If successful, check it is UPLOAD or COPY.
+    // For an UPLOAD commandy
+    //   increment the number of patch lines read,
+    //   increase patchByteAddr by PATCH_LINE_SIZE,
+    //   and read the patch data.
+    // For a COPY command,
+    //   increment the number of patch lines read,
+    //   increase patchByteAddr by PATCH_LINE_SIZE,
+    //   and read data from the source volume.
+    case S_READ_PATCH_CMD:
+      if (error == SUCCESS) {
+        if (patch.cmd == PATCH_CMD_UPLOAD) { 
+          patchNumLinesRead++;
+          patchByteAddr += PATCH_LINE_SIZE;  // read the next line of patch
+          state = S_READ_PATCH_DATA;
+          call BlockRead.read[patchVolume](patchByteAddr, patchData, patch.data_length);
+          break;
+        }
+        else if (patch.cmd == PATCH_CMD_COPY) { 
+          patchNumLinesRead++; 
+          patchByteAddr += PATCH_LINE_SIZE;  // read the next line of patch
+          state = S_READ_PATCH_COPY;
+          call BlockRead.read[srcVolume](patch.src_offset, patchData, patch.data_length);
+          break;
+        }
+      }
+      notifyFailure(error);
+      break;
+    // When the patch data of PATCH_UPLOAD is ready,
+    // increase patchByteAddr ceiling(len / PATCH_LINE_SIZE) * PATCH_LINE_SIZE,
+    // and  write it into the destination volume.  
+    case S_READ_PATCH_DATA:
+      if (error == SUCCESS) {
+        state = S_WRITE_PATCH;
+        patchByteAddr += ((len + PATCH_LINE_SIZE - 1) / PATCH_LINE_SIZE * PATCH_LINE_SIZE); 
+        call BlockWrite.write[dstVolume](patch.dst_offset, buf, len);
+        break;
+      }
+      notifyFailure(error);
+      break;
+    // When the source data of PATCH_COPY is ready,
+    // write it into the destination volume.
+    case S_READ_PATCH_COPY:
+      if (error == SUCCESS) {
+        state = S_WRITE_PATCH;
+        call BlockWrite.write[dstVolume](patch.dst_offset, buf, len);
+        break;
+      }
+      notifyFailure(error);
+      break;
+    }
+  }
+
+  event void BlockWrite.writeDone[uint8_t imgNum](
+    storage_addr_t addr, void* buf, storage_len_t len, error_t error) 
+  {
+    switch (state) {
+    case S_WRITE_PATCH:
+      if (error == SUCCESS) {
+        // When more patch commands remaining, read the next one.
+        if (patchNumLinesRead < patchNumLines) {
+          state = S_READ_PATCH_CMD;
+          call BlockRead.read[patchVolume](patchByteAddr, &patch, sizeof(patch)); 
+        }
+        else {
+          notifySuccess();
+        }
+        break;
+      }
+      notifyFailure(error);
+      break;
+    }
+  }
+
+  event void BlockWrite.eraseDone[uint8_t imgNum](error_t error)
+  {
+    switch (state) {
+    case S_READY:
+      signal BlockWrite.eraseDone[imgNum](error);
+      break;
+    }
+  }
+
+  default command error_t BlockWrite.write[uint8_t imgNum](
+    storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
+  default command error_t BlockRead.read[uint8_t imgNum](
+    storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
+  default command error_t BlockRead.computeCrc[uint8_t imgNum](
+    storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; }
+  event void BlockRead.computeCrcDone[uint8_t imgNum](
+    storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) {}
+  event void BlockWrite.syncDone[uint8_t imgNum](error_t error) {}
+  default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; }
+  default event void storageReady() {}
+  default event void DelugePatch.decodePatchDone[uint8_t client](
+    uint8_t imgNumPatch, uint8_t imgNumSrc, uint8_t imgNumDst, error_t error) {}
+
+}