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

📄 indirecttxp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/*
 * Copyright (c) 2008, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * 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 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) 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.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.8 $
 * $Date: 2009/09/14 14:15:09 $
 * @author Jan Hauer <hauer@tkn.tu-berlin.de>
 * @author: Jasper Buesch <buesch@tkn.tu-berlin.de>
 * ========================================================================
 */

module IndirectTxP
{
  provides
  {
    interface Init as Reset;
    interface FrameTx[uint8_t client];
    interface WriteBeaconField as PendingAddrWrite;
    interface Notify<bool> as PendingAddrSpecUpdated;
    interface Get<ieee154_txframe_t*> as GetIndirectTxFrame; 
    interface Purge;
  }
  uses
  {
    interface FrameTx as CoordCapTx;
    interface FrameRx as DataRequestRx;
    interface MLME_GET;
    interface IEEE154Frame;
    interface Timer<TSymbolIEEE802154> as IndirectTxTimeout;
    interface TimeCalc;
    interface Leds;
  }
}
implementation
{
  enum {
    SEND_THIS_FRAME = 0x80,
    NUM_MAX_PENDING = 7,
  };

  ieee154_txframe_t *m_txFrameTable[NUM_MAX_PENDING];
  ieee154_txframe_t *m_pendingTxFrame;
  uint8_t m_client;
  uint8_t m_numTableEntries;
  uint8_t m_numShortPending;
  uint8_t m_numExtPending;
  ieee154_txframe_t m_emptyDataFrame;
  ieee154_metadata_t m_emptyDataFrameMetadata;
  ieee154_header_t m_emptyDataFrameHeader;

  task void tryCoordCapTxTask();
  void tryCoordCapTx();
  void transmitEmptyDataFrame(message_t* dataRequestFrame);

  command error_t Reset.init()
  {
    uint8_t i;
    // CAP/Queue component is always reset first, i.e. there
    // should be no outstanding frames
    call IndirectTxTimeout.stop();
    for (i=0; i<NUM_MAX_PENDING; i++)
      if (m_txFrameTable[i] != NULL)
        signal FrameTx.transmitDone[m_txFrameTable[i]->client](m_txFrameTable[i], IEEE154_TRANSACTION_OVERFLOW);    
    for (i=0; i<NUM_MAX_PENDING; i++)
      m_txFrameTable[i] = NULL; // empty slot
    m_pendingTxFrame = NULL;
    m_numTableEntries = 0;
    m_numShortPending = 0;
    m_numExtPending = 0;

    m_emptyDataFrame.header = &m_emptyDataFrameHeader;
    m_emptyDataFrame.metadata = &m_emptyDataFrameMetadata;
    m_emptyDataFrame.payload = &m_numExtPending; // dummy (payloadLen is always 0)
    m_emptyDataFrame.payloadLen = 0;
    m_emptyDataFrame.client = 0; // unlock
    return SUCCESS;
  }

  uint32_t getPersistenceTimeSymbols()
  {
    // transform macTransactionPersistenceTime PIB attribute
    // from "unit periods" to symbols (cf. page 166) 
    uint32_t unitPeriod;
    ieee154_macBeaconOrder_t BO = call MLME_GET.macBeaconOrder();

    if (BO <= 14) {
      unitPeriod = IEEE154_aBaseSuperframeDuration;
      unitPeriod *= ((uint16_t) 1) << BO;
    } else
      unitPeriod = IEEE154_aBaseSuperframeDuration;
    return unitPeriod * call MLME_GET.macTransactionPersistenceTime();
  }

  command ieee154_status_t Purge.purge(uint8_t msduHandle)
  {
    uint8_t i = 0;
    for (i=0; i<NUM_MAX_PENDING; i++) {
      if ((m_txFrameTable[i]->handle == msduHandle) && (m_client != m_txFrameTable[i]->client) ){
        ieee154_txframe_t *purgedFrame;
        purgedFrame = m_txFrameTable[i];
        m_txFrameTable[i] = NULL;
        m_numTableEntries -= 1;
        signal Purge.purgeDone(purgedFrame, IEEE154_PURGED);
        return IEEE154_SUCCESS;
      }
    }
    return IEEE154_INVALID_HANDLE;
  }

  command uint8_t PendingAddrWrite.write(uint8_t *pendingAddrField, uint8_t maxlen)
  {
    // writes the pending addr field (inside the beacon frame)
    uint8_t i, j, k=0;
    uint8_t *longAdrPtr[NUM_MAX_PENDING];
    nxle_uint16_t *adrPtr;
    ieee154_txframe_t *txFrame;
    uint8_t len = call PendingAddrWrite.getLength();

    if (len > maxlen)
      return 0;
    pendingAddrField[0] = 0;
    adrPtr = (nxle_uint16_t *) &pendingAddrField[1];
    for (i=0; i<NUM_MAX_PENDING; i++) {
      if (!m_txFrameTable[i])
        continue;
      txFrame = m_txFrameTable[i];
      if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT) {
        *adrPtr++ = *((nxle_uint16_t*) &txFrame->header->mhr[MHR_INDEX_ADDRESS + sizeof(ieee154_macPANId_t)]);
      } else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
        longAdrPtr[k++] = &(txFrame->header->mhr[MHR_INDEX_ADDRESS + sizeof(ieee154_macPANId_t)]);
    }
    for (i=0; i<m_numExtPending; i++)
      for (j=0; j<8; j++)
        pendingAddrField[1 + 2*m_numShortPending + i*8 + j] = longAdrPtr[i][j];
    pendingAddrField[0] = m_numShortPending | (m_numExtPending << 4);
    return len;
  }

  command uint8_t PendingAddrWrite.getLength()
  {
    return 1 + m_numShortPending * 2 + m_numExtPending * 8;
  }

  command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame)
  {
    // sends a frame using indirect transmission
    uint8_t i;
    if (m_numTableEntries >= NUM_MAX_PENDING) {
      dbg_serial("IndirectTxP", "Overflow\n");
      return IEEE154_TRANSACTION_OVERFLOW;
    }
    txFrame->client = client;
    txFrame->metadata->timestamp = call IndirectTxTimeout.getNow();
    for (i=0; i<NUM_MAX_PENDING; i++)
      if (!m_txFrameTable[i]) // there must be an empty slot
        break;
    m_txFrameTable[i] = txFrame;
    m_numTableEntries += 1;
    if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
      m_numShortPending++;
    else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
      m_numExtPending++;
    if (!call IndirectTxTimeout.isRunning())
      call IndirectTxTimeout.startOneShot(getPersistenceTimeSymbols());
    dbg_serial("IndirectTxP", "Preparing a transmission.\n");
    signal PendingAddrSpecUpdated.notify(TRUE);
    return IEEE154_SUCCESS;
  }

  event message_t* DataRequestRx.received(message_t* frame)
  {
    uint8_t i, j, srcAddressMode, dstAddressMode, *src;
    uint8_t *mhr = MHR(frame);
    uint8_t destMode = (mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK);
    ieee154_txframe_t *dataResponseFrame = NULL;

    // received a data request frame from a device
    // have we got some pending data for it ?
    srcAddressMode = (mhr[MHR_INDEX_FC2] & FC2_SRC_MODE_MASK);
    if (!(srcAddressMode & FC2_SRC_MODE_SHORT))
      return frame;  // no source address
    src = mhr + MHR_INDEX_ADDRESS;
    if (destMode == FC2_DEST_MODE_SHORT)
      src += 4;
    else if (destMode == FC2_DEST_MODE_EXTENDED)
      src += 10;
    if (!((mhr[MHR_INDEX_FC1] & FC1_PAN_ID_COMPRESSION) && (mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_SHORT)))
      src += 2;
    for (i=0; i<NUM_MAX_PENDING; i++) {
      if (m_txFrameTable[i] == NULL)
        continue;
      else {
        dstAddressMode = (m_txFrameTable[i]->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK);
        if ((dstAddressMode << 4) != srcAddressMode)
          continue;
        else {
          // we know: dstAddressMode IN [2,3]
          uint8_t *dst = &(m_txFrameTable[i]->header->mhr[MHR_INDEX_ADDRESS]) + 2;
          uint8_t len = ((srcAddressMode == FC2_SRC_MODE_SHORT) ? 2 : 8);
          for (j=0; j<len; j++)
            if (dst[j] != src[j])
              break;  // no match!
          if (j==len) { // match!
            if (dataResponseFrame == NULL)
              dataResponseFrame = m_txFrameTable[i];
            else // got even more than one frame for this device: set pending flag
              dataResponseFrame->header->mhr[MHR_INDEX_FC1] |= FC1_FRAME_PENDING;
          }
        }
      }
    }
    if (dataResponseFrame != NULL) {
      // found a matching frame, mark it for transmission
      dbg_serial("IndirectTxP", "We have data for this device, trying to transmit...");
      dataResponseFrame->client |= SEND_THIS_FRAME;
      post tryCoordCapTxTask();
    } else {
      dbg_serial("IndirectTxP", "We don't have data for this device, sending an empty frame...");
      transmitEmptyDataFrame(frame);
    }
    return frame;
  }

  void transmitEmptyDataFrame(message_t* dataRequestFrame)
  {
    // the cast in the next line is dangerous -> this is only a temporary workaround!
    // (until the new T2 message buffer abstraction is available)
    message_t *emptyDataMsg = (message_t *) m_emptyDataFrame.header;
    ieee154_address_t dstAddr;
    uint16_t dstPanID;

    if (m_emptyDataFrame.client != 0)
      return; // locked (already transmitting an empty data frame)
    if (call IEEE154Frame.getSrcAddr(dataRequestFrame, &dstAddr) != IEEE154_SUCCESS ||
        call IEEE154Frame.getSrcPANId(dataRequestFrame, &dstPanID) != IEEE154_SUCCESS)
      return;
    call IEEE154Frame.setAddressingFields(emptyDataMsg,
        call IEEE154Frame.getDstAddrMode(dataRequestFrame), // will become srcAddrMode
        call IEEE154Frame.getSrcAddrMode(dataRequestFrame), // will become dstAddrMode
        dstPanID,
        &dstAddr,
        NULL //security
        );
    MHR(&m_emptyDataFrame)[MHR_INDEX_FC1] |= FC1_FRAMETYPE_DATA;
    m_emptyDataFrame.headerLen = 9;
    m_emptyDataFrame.client = 1; // lock
    if (call CoordCapTx.transmit(&m_emptyDataFrame) != IEEE154_SUCCESS)
      m_emptyDataFrame.client = 0; // unlock
  }

  void tryCoordCapTx()
  {
    // iterate over the queued frames and transmit them in the CAP 
    // (if they are marked for transmission)
    uint8_t i;
    if (m_pendingTxFrame == NULL && m_numTableEntries) {
      for (i=0; i<NUM_MAX_PENDING; i++)
        if (m_txFrameTable[i] && (m_txFrameTable[i]->client & SEND_THIS_FRAME)) {
          m_pendingTxFrame = m_txFrameTable[i];
          m_client = m_txFrameTable[i]->client;
          if (call CoordCapTx.transmit(m_txFrameTable[i]) == IEEE154_SUCCESS) {
            dbg_serial("IndirectTxP", "Started a transmission.\n");
          } else {
            m_pendingTxFrame = NULL;
            post tryCoordCapTxTask();
          }
          return; // done - wait for txDone
        }
    }
  }

  task void tryCoordCapTxTask()
  {
    tryCoordCapTx();
  }

  event void IndirectTxTimeout.fired()
  {
    // a transaction has expired 
    uint32_t now = call IndirectTxTimeout.getNow(), dt=0;
    uint32_t persistenceTime = getPersistenceTimeSymbols();
    uint8_t i;

    for (i=0; i<NUM_MAX_PENDING; i++)
      if (m_txFrameTable[i] && m_txFrameTable[i] != m_pendingTxFrame) {
        if (call TimeCalc.hasExpired(m_txFrameTable[i]->metadata->timestamp, persistenceTime)) { 
          ieee154_txframe_t *txFrame = m_txFrameTable[i];
          txFrame->client &= ~SEND_THIS_FRAME;
          m_txFrameTable[i] = NULL;
          m_numTableEntries -= 1;
          if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
            m_numShortPending--;
          else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
            m_numExtPending--;
          signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_EXPIRED);
          signal PendingAddrSpecUpdated.notify(TRUE);
        } else if (call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now) > dt) {
          dt = call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now);
        }
      }
    if (dt != 0) {
      if (dt > persistenceTime)
        dt = persistenceTime;
      call IndirectTxTimeout.startOneShot(persistenceTime - dt);
    }
  }

  event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
  {
    uint8_t i;
    // TODO: if CSMA-CA algorithm failed, then frame shall still remain in transaction queue
    dbg_serial("IndirectTxP", "transmitDone(), status: %lu\n", (uint32_t) status);

    if (txFrame == &m_emptyDataFrame) {
      m_emptyDataFrame.client = 0; // unlock
      return;
    }
    for (i=0; i<NUM_MAX_PENDING; i++)
      if (m_txFrameTable[i] == txFrame) {
        m_txFrameTable[i] = NULL; // slot is now empty
        break;
      }
    signal PendingAddrSpecUpdated.notify(TRUE);
    m_pendingTxFrame = NULL;
    txFrame->client = m_client;
    txFrame->client &= ~SEND_THIS_FRAME;
    m_numTableEntries -= 1;
    if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT)
      m_numShortPending--;
    else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED)
      m_numExtPending--;    
    signal FrameTx.transmitDone[txFrame->client](txFrame, status);
    post tryCoordCapTxTask();
  }

  command ieee154_txframe_t* GetIndirectTxFrame.get() { return m_pendingTxFrame;}
  command error_t PendingAddrSpecUpdated.enable() {return FAIL;}
  command error_t PendingAddrSpecUpdated.disable() {return FAIL;}
  default event void PendingAddrSpecUpdated.notify( bool val ) {return;}
  default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status) {}
}

⌨️ 快捷键说明

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