]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/mac/tkn154/DataP.nc
Initial version of TKN15.4, a platform-independent IEEE 802.15.4-2006 MAC implementat...
[tinyos-2.x.git] / tos / lib / mac / tkn154 / DataP.nc
diff --git a/tos/lib/mac/tkn154/DataP.nc b/tos/lib/mac/tkn154/DataP.nc
new file mode 100644 (file)
index 0000000..4e951b0
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+#include "TKN154_MAC.h"
+
+module DataP
+{
+  provides
+  {
+    interface Init;
+    interface MCPS_DATA; 
+    interface MCPS_PURGE;
+  } uses {
+    interface Get<bool> as IsSendingBeacons;
+    interface FrameRx as CoordCapRx;
+    interface FrameTx as DeviceCapTx;
+    interface FrameTx as CoordCapTx;
+    interface FrameTx as BroadcastTx;
+    interface FrameRx as DeviceCapRx;
+    interface Pool<ieee154_txframe_t> as TxFramePool;
+    interface FrameTx as DeviceCfpTx;
+    interface FrameTx as CoordCfpTx;
+    interface FrameTx as IndirectTx;
+    interface FrameRx as CoordCfpRx;
+    interface FrameRx as DeviceCfpRx;
+    interface FrameUtility;
+    interface Purge as PurgeDirect;
+    interface Purge as PurgeIndirect;
+    interface Purge as PurgeGtsDevice;
+    interface Purge as PurgeGtsCoord;
+    interface MLME_GET;
+    interface Leds;
+    interface Packet;
+    interface IEEE154Frame as Frame;
+    interface Get<uint64_t> as LocalExtendedAddress;
+  }
+}
+implementation
+{
+  message_t* dataReceived(message_t* frame);
+  void finishTxTransaction(ieee154_txframe_t *txFrame, ieee154_status_t status);
+
+  command error_t Init.init()
+  {
+    return SUCCESS;
+  }
+  
+  command ieee154_status_t MCPS_DATA.request  (
+                          message_t *frame,
+                          uint8_t payloadLen,
+                          uint8_t msduHandle,
+                          uint8_t txOptions
+                        )
+  {
+    uint8_t srcAddrMode = call Frame.getSrcAddrMode(frame);
+    uint8_t dstAddrMode = call Frame.getDstAddrMode(frame);
+    ieee154_address_t dstAddr;
+    ieee154_status_t txStatus;
+    ieee154_txframe_t *txFrame;
+    uint8_t sfType=0;
+    uint8_t *mhr;
+
+    if (payloadLen > call Packet.maxPayloadLength())
+      txStatus = IEEE154_INVALID_PARAMETER;
+    else if ((!srcAddrMode && !dstAddrMode) || 
+        (srcAddrMode > ADDR_MODE_EXTENDED_ADDRESS || dstAddrMode > ADDR_MODE_EXTENDED_ADDRESS) ||
+        (srcAddrMode == ADDR_MODE_RESERVED || dstAddrMode  == ADDR_MODE_RESERVED))
+      txStatus = IEEE154_INVALID_ADDRESS; 
+    else if (!(txFrame = call TxFramePool.get()))
+      txStatus = IEEE154_TRANSACTION_OVERFLOW;
+    else {
+      // construct the DATA frame
+      txFrame->header = &((message_header_t*) frame->header)->ieee154;
+      txFrame->payload = (uint8_t*) frame->data;
+      txFrame->metadata = &((message_metadata_t*) frame->metadata)->ieee154;
+      txFrame->payloadLen = payloadLen;
+      mhr = txFrame->header->mhr;
+      txFrame->headerLen = call Frame.getHeaderLength(frame);
+      mhr[MHR_INDEX_FC1] &= ~(FC1_FRAMETYPE_MASK | FC1_FRAME_PENDING | FC1_ACK_REQUEST);
+      mhr[MHR_INDEX_FC1] |= FC1_FRAMETYPE_DATA;
+      if (txOptions & TX_OPTIONS_ACK)
+        mhr[MHR_INDEX_FC1] |= FC1_ACK_REQUEST;
+      mhr[MHR_INDEX_FC2] &= ~FC2_FRAME_VERSION_MASK;
+      if (payloadLen > IEEE154_aMaxMACSafePayloadSize)
+        mhr[MHR_INDEX_FC2] |= FC2_FRAME_VERSION_1;
+      txFrame->handle = msduHandle;
+      
+      // in case a node is both, coordinator and device (e.g. in a 
+      // cluster-tree topology), it has to be decided whether the frame 
+      // is to be sent in the incoming or outgoing superframe (sf); 
+      // we do this by comparing the destination address to the
+      // coordinator address in the PIB, if they match the frame is
+      // sent in the incoming sf otherwise in the outgoing sf
+      call Frame.getDstAddr(frame, &dstAddr);
+      if (dstAddrMode == ADDR_MODE_SHORT_ADDRESS){
+        if (dstAddr.shortAddress == call MLME_GET.macCoordShortAddress())
+          sfType = INCOMING_SUPERFRAME;
+        else
+          sfType = OUTGOING_SUPERFRAME;
+      } else if (dstAddrMode == ADDR_MODE_EXTENDED_ADDRESS){
+        if (dstAddr.extendedAddress == call MLME_GET.macCoordExtendedAddress())
+          sfType = INCOMING_SUPERFRAME;
+        else
+          sfType = OUTGOING_SUPERFRAME;
+      } else if (dstAddrMode == ADDR_MODE_NOT_PRESENT) // to PAN Coord
+        sfType = INCOMING_SUPERFRAME;
+
+      // GTS?
+      if (txOptions & TX_OPTIONS_GTS){
+        if (sfType == INCOMING_SUPERFRAME)
+          txStatus = call DeviceCfpTx.transmit(txFrame);
+        else
+          txStatus = call CoordCfpTx.transmit(txFrame);
+
+      // indirect transmission?
+      } else if ((txOptions & TX_OPTIONS_INDIRECT) && 
+          call IsSendingBeacons.get() && 
+          (dstAddrMode >= ADDR_MODE_SHORT_ADDRESS)){
+        if (dstAddrMode == ADDR_MODE_SHORT_ADDRESS && dstAddr.shortAddress == 0xFFFF){
+          mhr[MHR_INDEX_FC1] &= ~FC1_ACK_REQUEST;
+          txStatus = call BroadcastTx.transmit(txFrame);
+        } else
+          txStatus = call IndirectTx.transmit(txFrame);
+
+      // transmission in the CAP
+      } else 
+        if (sfType == INCOMING_SUPERFRAME)
+          txStatus = call DeviceCapTx.transmit(txFrame);
+        else
+          txStatus = call CoordCapTx.transmit(txFrame);
+
+      if (txStatus != IEEE154_SUCCESS){
+        call TxFramePool.put(txFrame);
+      }
+    }
+    return txStatus;
+  }
+
+  command ieee154_status_t MCPS_PURGE.request  (
+                          uint8_t msduHandle
+                        )
+  {
+    if (call PurgeDirect.purge(msduHandle) == IEEE154_SUCCESS ||
+        call PurgeIndirect.purge(msduHandle) == IEEE154_SUCCESS ||
+        call PurgeGtsDevice.purge(msduHandle) == IEEE154_SUCCESS ||
+        call PurgeGtsCoord.purge(msduHandle) == IEEE154_SUCCESS)
+      return IEEE154_SUCCESS;
+    else
+      return IEEE154_INVALID_HANDLE;
+  }
+
+  event void PurgeDirect.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
+  {
+    finishTxTransaction(data, status);
+  }
+
+  event void PurgeIndirect.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
+  {
+    finishTxTransaction(data, status);
+  }
+
+  event void PurgeGtsDevice.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
+  {
+    finishTxTransaction(data, status);
+  }
+
+  event void PurgeGtsCoord.purgeDone(ieee154_txframe_t *data, ieee154_status_t status)
+  {
+    finishTxTransaction(data, status);
+  }
+
+  event message_t* CoordCfpRx.received(message_t* frame)
+  {
+    return dataReceived(frame);
+  }
+
+  event message_t* DeviceCfpRx.received(message_t* frame)
+  {
+    return dataReceived(frame);
+  }
+
+  event message_t* CoordCapRx.received(message_t* frame)
+  {
+    return dataReceived(frame);
+  }
+
+  event message_t* DeviceCapRx.received(message_t* frame)
+  {
+    return dataReceived(frame);
+  }
+
+  message_t* dataReceived(message_t* frame)
+  {
+    return signal MCPS_DATA.indication( frame );
+  }
+
+  void finishTxTransaction(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    uint8_t handle = txFrame->handle;
+    uint32_t txTime = txFrame->metadata->timestamp;
+    message_t *msg = (message_t*) ((uint8_t*) txFrame->header - offsetof(message_t, header));
+    call TxFramePool.put(txFrame);
+    signal MCPS_DATA.confirm(msg, handle, status, txTime);
+  }
+
+  event void BroadcastTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    finishTxTransaction(txFrame, status);
+  }
+
+  event void DeviceCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    finishTxTransaction(txFrame, status);
+  }
+  
+  event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    finishTxTransaction(txFrame, status);
+  }
+
+  event void DeviceCfpTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    finishTxTransaction(txFrame, status);
+  }
+  
+  event void CoordCfpTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    finishTxTransaction(txFrame, status);
+  }
+
+
+  event void IndirectTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
+  {
+    finishTxTransaction(txFrame, status);
+  }
+
+  default event void MCPS_DATA.confirm(  
+                          message_t *msg,
+                          uint8_t msduHandle,
+                          ieee154_status_t status,
+                          uint32_t Timestamp
+                        ){}
+
+  default event message_t* MCPS_DATA.indication ( message_t* frame ){ return frame; }
+  default command ieee154_status_t DeviceCfpTx.transmit(ieee154_txframe_t *data){return IEEE154_INVALID_GTS;}
+  default command ieee154_status_t CoordCfpTx.transmit(ieee154_txframe_t *data){return IEEE154_INVALID_GTS;}
+}