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

📄 linklayerp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/* -*- mode:c++; indent-tabs-mode: nil -*-
 * Copyright (c) 2004-2006, 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.
 *
 */

#include "radiopacketfunctions.h"
#include "message.h"
#include "PacketAck.h"

/**
 * This is the implementation of a really simple link layer. 
 *
 * @author Andreas Koepke <koepke@tkn.tu-berlin.de>
 */
module LinkLayerP {
    provides {
      interface Init;
      interface SplitControl;
      interface Receive;
      interface Send;
      interface PacketAcknowledgements;
    }
    uses {
      interface SplitControl as MacSplitControl;
      interface SplitControl as RadioSplitControl;
      interface MacSend as SendDown;
      interface MacReceive as ReceiveLower;
      interface Packet;
    }
}
implementation
{
  /* Tx/Rx buffers & pointers */
  message_t* txBufPtr;
  message_t* rxBufPtr;
  message_t  rxBuf;

  /* state vars */
  error_t splitStateError;    // state of SplitControl interfaces
  bool rxBusy;                // blocks an incoming packet if the rxBuffer is in use
    
// #define LLCM_DEBUG  
    /**************** Helper functions ******/
    void signalFailure() {
#ifdef LLCM_DEBUG
        atomic {
            for(;;) {
                ;
            }
        }
#endif
    }
    
    /**************** Init  *****************/
    command error_t Init.init(){
        atomic {
          rxBufPtr = &rxBuf;
          txBufPtr = 0;
          splitStateError = EOFF;
          rxBusy = FALSE;
        }
        return SUCCESS;
    }

    /**************** Start  *****************/
    void checkStartDone(error_t error) {
      atomic {
        if ( (splitStateError == SUCCESS) && (error == SUCCESS) ) {
          signal SplitControl.startDone(SUCCESS);
        } else if ( (error == SUCCESS) && (splitStateError == EOFF) ) {
          splitStateError = SUCCESS;
        } else {
          signal SplitControl.startDone(FAIL);
        }
      }
    }
    
    event void MacSplitControl.startDone(error_t error) {
      checkStartDone(error);
    }
    
    event void RadioSplitControl.startDone(error_t error) {
      checkStartDone(error);
    }
    
    command error_t SplitControl.start() {
      call MacSplitControl.start();
      call RadioSplitControl.start();
      return SUCCESS;
    }
    /**************** Stop  *****************/
    void checkStopDone(error_t error) {
      atomic {
        if ( (splitStateError == EOFF) && (error == SUCCESS) ) {
          signal SplitControl.stopDone(SUCCESS);
        } else if ( (error == SUCCESS) && (splitStateError == SUCCESS) ) {
          splitStateError = EOFF;
        } else {
          signal SplitControl.stopDone(FAIL);
        }
      }
    }
    
    event void MacSplitControl.stopDone(error_t error) {
      checkStopDone(error);
    }
    
    event void RadioSplitControl.stopDone(error_t error) {
      checkStopDone(error);
    }
    
    command error_t SplitControl.stop(){
      call MacSplitControl.stop();
      call RadioSplitControl.stop();
      return SUCCESS;
    }
    /**************** Send ****************/
    task void SendDoneSuccessTask() {
      message_t* txPtr;
      atomic txPtr = txBufPtr;
      signal Send.sendDone(txPtr, SUCCESS);
    }
    task void SendDoneCancelTask() {
      message_t* txPtr;
      atomic txPtr = txBufPtr;
      signal Send.sendDone(txPtr, ECANCEL); 
    }
    task void SendDoneFailTask() {
      message_t* txPtr;
      atomic txPtr = txBufPtr;
      signal Send.sendDone(txPtr, FAIL);
    }
    
    command error_t Send.send(message_t *msg, uint8_t len) {
        if(getMetadata(msg)->ack != NO_ACK_REQUESTED) {
            // ensure reasonable value
            getMetadata(msg)->ack = ACK_REQUESTED;
        }
        return call SendDown.send(msg, len);
    }

    command error_t Send.cancel(message_t* msg) {
      return call SendDown.cancel(msg);
    }
    
    command uint8_t Send.maxPayloadLength() {
      return call Packet.maxPayloadLength();
    }

    command void* Send.getPayload(message_t* msg, uint8_t len) {
      return call Packet.getPayload(msg, len);
    }
    
    async event void SendDown.sendDone(message_t* msg, error_t error) { 
        atomic {
          txBufPtr = msg;
        }
        if (error == SUCCESS) {
          post SendDoneSuccessTask();
        } else if (error == ECANCEL) {
          post SendDoneCancelTask();
        } else {
          post SendDoneFailTask();
        }
    }
    
    /*************** Receive ***************/
    task void ReceiveTask() {
      void *payload;
      uint8_t len;
      message_t* tmpMsgPtr;
      atomic {
        len = call Packet.payloadLength(rxBufPtr);
        payload = call Packet.getPayload(rxBufPtr, len);
        tmpMsgPtr = rxBufPtr;
      }
      tmpMsgPtr = signal Receive.receive(tmpMsgPtr, payload , len);
      atomic {
        rxBufPtr = tmpMsgPtr;
        rxBusy = FALSE;
      }
    }
    
    async event message_t* ReceiveLower.receiveDone(message_t* msg) {
      message_t* msgPtr;
      atomic {
        if (rxBusy) {
          msgPtr = msg;
        }
        else {
          rxBusy = TRUE;
          msgPtr = rxBufPtr;
          rxBufPtr = msg;
          post ReceiveTask();
        }
      } 
      return msgPtr;
    }


    /*************** default events ***********/

    /* for lazy buggers who do not want to do something with a packet */
    default event void Send.sendDone(message_t* sent, error_t success) {
    }

    default event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
        return msg;
    }     
    
    
    /* PacketAcknowledgements interface */

    async command error_t PacketAcknowledgements.requestAck(message_t* msg) {
        getMetadata(msg)->ack = ACK_REQUESTED;
        return SUCCESS;
    }

    async command error_t PacketAcknowledgements.noAck(message_t* msg) {
        getMetadata(msg)->ack = NO_ACK_REQUESTED;
        return SUCCESS;
    }

    async command bool PacketAcknowledgements.wasAcked(message_t* msg) {
        bool rVal = FALSE;
        if(getMetadata(msg)->ack == WAS_ACKED) rVal = TRUE;
        return rVal;
    }
}



⌨️ 快捷键说明

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