⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nwprogp.nc

📁 tinyos-2.x.rar
💻 NC
字号:

#include <Storage.h>
#include <Shell.h>
#include "imgNum2volumeId.h"
#include "Deluge.h"
#include "PrintfUART.h"
module NWProgP {
  provides interface BootImage;
  uses {
    interface Boot;
    interface UDP as Recv;
    interface StorageMap[uint8_t imag_num];
    interface NetProg;
    interface BlockRead[uint8_t img_num];
    interface BlockWrite[uint8_t img_num];
    interface Resource;
    interface DelugeMetadata;
    interface Timer<TMilli> as RebootTimer;

    event void storageReady();

    interface ShellCommand;
  }
} implementation {

  enum {
    S_IDLE,
    S_BUSY,
  };
  uint8_t state;
  struct sockaddr_in6 endpoint;
  prog_reply_t reply;
  prog_reply_t *read_buffer;

  // SDH : if this is defined, we read back each packet after we write
  // it and check that it matches.  It turns out that this doesn't
  // actually guarantee you much, due to buffering.
#undef PARANOID

#ifdef PARANOID
  bool paranoid_read;
  uint16_t cmp_len;
  uint8_t cmp_img;
  uint32_t cmp_off;
  uint8_t cmp_buf[256];
#endif

  // Begin-added by Jaein Jeong
  command error_t BootImage.erase(uint8_t img_num) {
    error_t error = call BlockWrite.erase[img_num]();
    return error;
  }
  // End-added

  command void BootImage.reboot() {
    call NetProg.reboot();
  }

  command error_t BootImage.boot(uint8_t img_num) {
    return call NetProg.programImageAndReboot(call StorageMap.getPhysicalAddress[img_num](0));
  }

  event void Boot.booted() {
#ifdef PARANOID
    paranoid_read = FALSE;
#endif
    state = S_IDLE;
    call Recv.bind(5213);
  }

  void sendDone(error_t error) {
    reply.error = error;
    call Recv.sendto(&endpoint, &reply, sizeof(prog_reply_t));
  }

  event void Recv.recvfrom(struct sockaddr_in6 *from,
                           void *payload, uint16_t len,
                           struct ip_metadata *meta) {
    prog_req_t *req = (prog_req_t *)payload;
    uint8_t imgNum = imgNum2volumeId(req->imgno);
    error_t error = FAIL;
    void *buffer;

    // just copy the payload out and write it into flash
    // we'll send the ack from the write done event.
    if (state != S_IDLE) return;
    
    memcpy(&endpoint, from, sizeof(struct sockaddr_in6));
    memcpy(&reply.req, req, sizeof(prog_req_t));

    if (!call Resource.isOwner()) {
      error = call Resource.immediateRequest();
    }
    if (error == SUCCESS) {
      switch (req->cmd) {
      case NWPROG_CMD_ERASE:
        error = call BlockWrite.erase[imgNum]();
        break;
      case NWPROG_CMD_WRITE:
        len -= sizeof(prog_req_t);

#ifdef PARANOID
        if (len > sizeof(cmp_buf)) {
          error = ENOMEM;
          break;
        }
        memcpy(cmp_buf, req->data, len);
        cmp_len = len;
        cmp_off = req->cmd_data.offset;
        cmp_img = imgNum;
#endif
        
        buffer = ip_malloc(len);
        if (buffer == NULL) {
          error = ENOMEM;
          break;
        }
        memcpy(buffer, req->data, len);
        error = call BlockWrite.write[imgNum](req->cmd_data.offset,
                                              buffer,
                                              len);
        if (error != SUCCESS) ip_free(buffer);
        break;
      case NWPROG_CMD_READ: {

        read_buffer = (prog_reply_t *)ip_malloc(64 + sizeof(prog_reply_t));
        if (read_buffer == NULL) {
          error = ENOMEM;
          break;
        }
        memcpy(&read_buffer->req, req, sizeof(prog_req_t));
        error = call BlockRead.read[imgNum](req->cmd_data.offset,
                                            read_buffer->req.data,
                                            64);
        if (error != SUCCESS) {
          ip_free(read_buffer);
        }
        break;
      }
      default:
        error = FAIL;
      }
    }

    if (error != SUCCESS) {
      sendDone(error);
      if (call Resource.isOwner()) {
        call Resource.release();
      }
    } else {
      state = S_BUSY;
    }
  }

  event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {
    if (state != S_BUSY) return;

#ifdef PARANOID
    if (len != cmp_len) {
      printfUART("WARNING: write length changed from %i to %lu!\n", cmp_len, len);
    }
    if (addr != cmp_off) {
      printfUART("WARNING: write address changed from %li to %li!\n", cmp_off, addr);
    }
    if (img_num != cmp_img) {
      printfUART("WARNING: write volume changed from %i to %i\n", cmp_img, img_num);
    }
    if (memcmp(buf, cmp_buf, cmp_len) != 0) {
      printfUART("WARNING: write data changed during call!\n");
    }
    memset(buf, 0, cmp_len);
    if (call BlockRead.read[cmp_img](cmp_off, buf, cmp_len) == SUCCESS) {
      paranoid_read = TRUE;
      return;
    } 


#else
    ip_free(buf);
#endif

    if (error == SUCCESS) {
      call BlockWrite.sync[img_num]();
    } else {
      state = S_IDLE;
      call Resource.release();
      sendDone(error);
    }
  }
  event void BlockRead.readDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {

#ifdef PARANOID
    if (paranoid_read) {
      if (len != cmp_len) {
        printfUART("WARNING: read length changed from %u to %lu!\n", cmp_len, len);
      }
      if (addr != cmp_off) {
        printfUART("WARNING: read address changed from %li to %li!\n", cmp_off, addr);
      }
      if (img_num != cmp_img) {
        printfUART("WARNING: read volume changed from %i to %i\n", cmp_img, img_num);
      }
      if (memcmp(buf, cmp_buf, cmp_len) != 0) {
        printfUART("WARNING: write data changed during call!\n");
      } else {
        printfUART("SUCCESS: write verified!\n");
      }

      paranoid_read = FALSE;
      ip_free(buf);
      if (error == SUCCESS) {
        call BlockWrite.sync[img_num]();
      } else {
        call Resource.release();
        state = S_IDLE;
        sendDone(error);
      }

      return;
    }
#endif


    if (state != S_BUSY || buf != read_buffer->req.data) return;
    call Resource.release();

    read_buffer->error = error;
    call Recv.sendto(&endpoint, read_buffer, sizeof(prog_reply_t) + 64);

    ip_free(read_buffer);
    state = S_IDLE;
  }

  event void BlockWrite.eraseDone[uint8_t img_num](error_t error) {
    if (state != S_BUSY) return;
    if (error == SUCCESS) 
      call BlockWrite.sync[img_num]();
    else {
      sendDone(error);
      state = S_IDLE;
      call Resource.release();
    }
  }

  event void BlockWrite.syncDone[uint8_t img_num](error_t error) { 
    if (state != S_BUSY) return;
    sendDone(error);
    state = S_IDLE;
    call Resource.release();
  }

  event void Resource.granted() {

  }


  /*
   * Shell command implementation
   */
  uint8_t nwprog_currentvol, nwprog_validvols;
  uint8_t boot_image;

  uint8_t volumeID2imgNum(uint8_t volumeID) {
    switch(volumeID) {
    case VOLUME_GOLDENIMAGE: return 0;
    case VOLUME_DELUGE1: return 1;
    case VOLUME_DELUGE2: return 2;
    case VOLUME_DELUGE3: return 3;
    }
  }
  event void DelugeMetadata.readDone(uint8_t imgNum, DelugeIdent* ident, error_t error) {
    int len;
    char *reply_buf = call ShellCommand.getBuffer(MAX_REPLY_LEN);
    if (error == SUCCESS) {
      if (ident->uidhash != DELUGE_INVALID_UID) {
        len = snprintf(reply_buf, MAX_REPLY_LEN,
                       "image: %i\n\t[size: %li]\n\t[app: %s]\n\t[user: %s]\n\t[host: %s]\n\t[arch: %s]\n\t[time: 0x%lx]\n",
                       volumeID2imgNum(imgNum), ident->size, (char *)ident->appname, (char *) ident->username,
                       (char *)ident->hostname, (char *)ident->platform, (uint32_t)ident->timestamp);
        nwprog_validvols++;
        call ShellCommand.write(reply_buf, len);
      }
      
    }
    if (++nwprog_currentvol < DELUGE_NUM_VOLUMES) {
      call DelugeMetadata.read(imgNum2volumeId(nwprog_currentvol));
    } else {
      len = snprintf(reply_buf, MAX_REPLY_LEN,
                     "%i valid image(s)\n", nwprog_validvols);
      call ShellCommand.write(reply_buf, len);
    }
  }

  event void RebootTimer.fired() {
    call BootImage.boot(boot_image);
  }

  event char *ShellCommand.eval(int argc, char **argv) {
    char *nwprog_help_str = "nwprog [list | boot <imgno> [when] | reboot]\n";
    if (argc >= 2) {
      if (memcmp(argv[1], "list", 4) == 0) {
        nwprog_currentvol = 0;
        nwprog_validvols = 0;
        call DelugeMetadata.read(imgNum2volumeId(nwprog_currentvol));
        return NULL;
      } else if (memcmp(argv[1], "boot", 4) == 0 && (argc == 3 || argc == 4)) {

        uint32_t when = 15;
        boot_image = atoi(argv[2]),
        boot_image = imgNum2volumeId(boot_image);
        if (argc == 4)
          when = atoi(argv[3]);
        if (when == 0)
          call RebootTimer.stop();
        else {
          char *ack = call ShellCommand.getBuffer(15);
          snprintf(ack, 15, "REBOOT %li\n", when);
          call RebootTimer.startOneShot(when);
          return ack;
        }
        return NULL;
      } else if (memcmp(argv[1], "reboot", 6) == 0) {
        call BootImage.reboot();
        return NULL;
      } 
    }
    return nwprog_help_str;
  }

  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 BlockWrite.erase[uint8_t imgNum]() { return FAIL; }
  default command error_t BlockWrite.sync[uint8_t imgNum]() { return FAIL; }
  
 default command error_t BlockRead.read[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len) {return FAIL;}

  event void BlockRead.computeCrcDone[uint8_t imgNum](storage_addr_t addr, storage_len_t len,uint16_t crc, error_t error) {}


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -