[Tinyos-beta-commits] CVS: tinyos-1.x/beta/Drain Drain.h, NONE,
1.1 DrainC.nc, NONE, 1.1 DrainLinkEst.nc, NONE,
1.1 DrainLinkEstM.nc, NONE, 1.1 DrainM.nc, NONE, 1.1
Gilman Tolle
gtolle at users.sourceforge.net
Mon Feb 14 15:16:39 PST 2005
Update of /cvsroot/tinyos/tinyos-1.x/beta/Drain
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13285
Added Files:
Drain.h DrainC.nc DrainLinkEst.nc DrainLinkEstM.nc DrainM.nc
Log Message:
First checkin of Drain -- untested
--- NEW FILE: Drain.h ---
// $Id: Drain.h,v 1.1 2005/02/14 23:16:37 gtolle Exp $
/* tab:4
* "Copyright (c) 2000-2005 The Regents of the University of California.
* 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 following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2005 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @author Gilman Tolle
*/
#ifndef __DRAIN_H__
#define __DRAIN_H__
enum {
AM_DRAINMSG = 4,
AM_DRAINBEACONMSG = 5,
};
enum {
DRAIN_QUEUE_SIZE = 3,
DRAIN_MAX_RETRANSMITS = 5,
DRAIN_MAX_MISSED_BEACONS = 5,
DRAIN_UNKNOWN_ACK_EST = 127,
};
typedef struct DrainMsg {
uint16_t sourceaddr;
uint16_t originaddr;
uint8_t ttl;
uint8_t type;
uint8_t data[0];
} DrainMsg;
typedef struct DrainBeaconMsg {
uint16_t parent;
uint16_t sourceAddr;
uint16_t cost;
uint16_t treeID;
uint32_t timestamp;
uint16_t beaconPeriod;
uint8_t beaconSeqno;
uint8_t level;
} DrainBeaconMsg;
#endif
--- NEW FILE: DrainC.nc ---
includes Drain;
configuration DrainC {
provides {
interface StdControl;
interface Send[uint8_t id];
interface Receive[uint8_t id];
interface Intercept[uint8_t id];
interface Intercept as Snoop[uint8_t id];
}
}
implementation {
components
DrainM,
DrainLinkEstM,
GenericComm,
RandomLFSR,
TimerC,
LedsC as Leds;
#if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT) || defined(PLATFORM_XSM)
components CC1000RadioC as RadioC;
#elif defined(PLATFORM_TELOS) || defined (PLATFORM_TELOSB)
components CC2420RadioC as RadioC;
#endif
StdControl = DrainM.StdControl;
Receive = DrainM.Receive;
Send = DrainM.Send;
Intercept = DrainM.Intercept;
Snoop = DrainM.Snoop;
DrainM.SubControl -> GenericComm;
DrainM.SubControl -> DrainLinkEstM;
DrainM.Leds -> Leds;
DrainM.DrainLinkEst -> DrainLinkEstM;
DrainM.SendMsg -> GenericComm.SendMsg[AM_DRAINMSG];
DrainM.ReceiveMsg -> GenericComm.ReceiveMsg[AM_DRAINMSG];
#ifndef PLATFORM_PC
DrainM.MacControl -> RadioC.MacControl;
#endif
DrainLinkEstM.Timer -> TimerC.Timer[unique("Timer")];
DrainLinkEstM.AgingTimer -> TimerC.Timer[unique("Timer")];
DrainLinkEstM.Random -> RandomLFSR;
DrainLinkEstM.SendMsg -> GenericComm.SendMsg[AM_DRAINBEACONMSG];
DrainLinkEstM.ReceiveMsg -> GenericComm.ReceiveMsg[AM_DRAINBEACONMSG];
}
--- NEW FILE: DrainLinkEst.nc ---
// $Id: DrainLinkEst.nc,v 1.1 2005/02/14 23:16:37 gtolle Exp $
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* 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 following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @author Gilman Tolle
*/
interface DrainLinkEst {
/**
* Whether there is currently a valid route.
*
* @return Whether there is a valid route.
*/
command bool isActive();
/**
* Given a TOS_MsgPtr, initialize its routing fields to a known
* state, specifying that the message is originating from this node.
* This known state can then be used by selectRoute() to fill in
* the necessary data.
*
* @param msg Message to select route for and fill in init data.
*
* @return Should always return SUCCESS.
*
*/
command result_t initializeFields(TOS_MsgPtr msg, uint8_t id);
/**
* Select a route and fill in all of the necessary routing
* information to a packet.
*
* @param msg Message to select route for and fill in routing information.
*
* @return Whether a route was selected succesfully. On FAIL the
* packet should not be sent.
*
*/
command result_t selectRoute(TOS_MsgPtr msg, uint8_t id, bool firstTime);
/**
* Inform the link estimator that the message has been sent,
* possibly successfully, possibly not.
*
*/
command result_t messageSent(TOS_MsgPtr msg, uint8_t id, result_t success);
}
--- NEW FILE: DrainLinkEstM.nc ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* 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 following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
* Authors: Gilman Tolle
*/
module DrainLinkEstM {
provides {
interface StdControl;
interface DrainLinkEst;
}
uses {
interface Timer;
interface Timer as AgingTimer;
interface Random;
interface SendMsg;
interface ReceiveMsg;
}
}
implementation {
int8_t beaconSeqno;
uint8_t missedBeacons;
uint16_t beaconPeriod;
uint16_t currentTreeID;
uint16_t currentParentAddr;
uint16_t currentParentCost;
uint16_t currentParentLinkEst;
uint16_t currentParentLQI;
uint16_t currentParentAckEst;
uint8_t currentDepth;
uint16_t successCounter;
uint16_t failCounter;
bool msgBufBusy;
TOS_Msg buf;
#define MAX(a_,b_) (a_ > b_ ? a_ : b_)
#define MIN(a_,b_) (a_ < b_ ? a_ : b_)
uint16_t adjustLQI(uint8_t val);
task void SendRouteTask();
command result_t StdControl.init() {
msgBufBusy = FALSE;
#ifdef PLATFORM_PC
currentParentAddr = TOS_LOCAL_ADDRESS-1; // For debugging.
#else
currentParentAddr = TOS_BCAST_ADDR;
#endif
currentParentCost = 0xffff;
currentParentLinkEst = 0xffff;
currentParentAckEst = DRAIN_UNKNOWN_ACK_EST;
currentParentLQI = 0x0;
currentTreeID = 0;
currentDepth = 0;
beaconSeqno = 1;
missedBeacons = 0;
successCounter = failCounter = 0;
return SUCCESS;
}
command result_t StdControl.start() {
return SUCCESS;
}
command result_t StdControl.stop() {
call AgingTimer.stop();
call Timer.stop();
return SUCCESS;
}
command result_t DrainLinkEst.initializeFields(TOS_MsgPtr Msg, uint8_t id) {
DrainMsg *pMHMsg = (DrainMsg *)&Msg->data[0];
pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
pMHMsg->ttl = 16;
pMHMsg->type = id;
return SUCCESS;
}
command result_t DrainLinkEst.selectRoute(TOS_MsgPtr Msg, uint8_t id,
bool firstTime) {
DrainMsg *pMHMsg = (DrainMsg *)&Msg->data[0];
Msg->addr = currentParentAddr;
pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
if (firstTime) {
pMHMsg->ttl--;
}
if (pMHMsg->ttl == 0) {
return FAIL;
} else {
return SUCCESS;
}
}
event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr Msg) {
DrainBeaconMsg *pRP = (DrainBeaconMsg *)&Msg->data[0];
/*
If we already belong to the newest tree we know of, consider
the beacon seqno. If it is newer, send out our own beacon.
*/
if ((int8_t)(pRP->beaconSeqno - beaconSeqno) > 0
|| pRP->beaconSeqno == 0) {
if (pRP->beaconSeqno == 0) {
beaconSeqno++;
if (beaconSeqno == 0)
beaconSeqno++;
} else {
beaconSeqno = pRP->beaconSeqno;
}
if (pRP->beaconPeriod != beaconPeriod) {
beaconPeriod = pRP->beaconPeriod;
call AgingTimer.stop();
call AgingTimer.start(TIMER_ONE_SHOT,
1024 * beaconPeriod);
}
call Timer.start(TIMER_ONE_SHOT,
(call Random.rand() % (1024 * beaconPeriod)) + 1);
}
/* Now evaluate whether we should reparent to the beacon. */
if (pRP->sourceAddr == currentParentAddr) {
uint16_t newLinkEst;
currentTreeID = pRP->treeID;
currentParentCost = pRP->cost;
#ifdef PLATFORM_TELOS
newLinkEst = adjustLQI(Msg->lqi);
currentParentLQI = Msg->lqi;
#else
newLinkEst = Msg->strength;
#endif
currentParentLinkEst = newLinkEst;
missedBeacons = 0;
currentDepth = pRP->level + 1;
} else {
/* if the message is not from my parent,
compare the message's cost + link estimate to my current cost,
switch if necessary */
uint32_t currentQuality =
(uint32_t) currentParentCost + (uint32_t) currentParentLinkEst;
uint16_t newLinkEst;
uint32_t newQuality = pRP->cost;
#ifdef PLATFORM_TELOS
newLinkEst = adjustLQI(Msg->lqi);
newQuality += (uint32_t) adjustLQI(Msg->lqi);
#else
newLinkEst = Msg->strength;
newQuality += (uint32_t) Msg->strength;
#endif
#ifdef NO_ACK_EST
// do nothing
#else
currentQuality += (uint32_t) currentParentAckEst;
newQuality += (uint32_t) DRAIN_UNKNOWN_ACK_EST;
#endif
if (newQuality < currentQuality && pRP->parent != TOS_LOCAL_ADDRESS) {
currentTreeID = pRP->treeID;
currentParentAddr = pRP->sourceAddr;
currentParentCost = pRP->cost;
currentParentLinkEst = newLinkEst;
currentParentAckEst = DRAIN_UNKNOWN_ACK_EST;
#ifdef PLATFORM_TELOS
currentParentLQI = Msg->lqi;
#endif
currentDepth = pRP->level + 1;
successCounter = 0;
failCounter = 0;
}
}
return Msg;
}
uint16_t adjustLQI(uint8_t val) {
uint16_t result = (80 - (val - 50));
result = (((result * result) >> 3) * result) >> 3;
return result;
}
event result_t Timer.fired() {
post SendRouteTask();
return SUCCESS;
}
task void SendRouteTask() {
TOS_MsgPtr pMsgBuf = &buf;
DrainBeaconMsg *pRP = (DrainBeaconMsg *)&pMsgBuf->data[0];
uint8_t length = sizeof(DrainBeaconMsg);
dbg(DBG_ROUTE,"MultiHopRSSI Sending route update msg.\n");
if (currentParentAddr != TOS_BCAST_ADDR) {
dbg(DBG_ROUTE,"MultiHopRSSI: Parent = %d\n", currentParentAddr);
}
if (msgBufBusy) {
#ifndef PLATFORM_PC
post SendRouteTask();
#endif
return;
}
atomic msgBufBusy = TRUE;
dbg(DBG_ROUTE,"MultiHopRSSI: Current cost: %d.\n",
currentParentCost + currentParentLinkEst);
pRP->parent = currentParentAddr;
pRP->sourceAddr = TOS_LOCAL_ADDRESS;
pRP->cost = currentParentCost + currentParentLinkEst;
#ifndef NO_ACK_EST
pRP->cost += currentParentAckEst;
#endif
pRP->treeID = currentTreeID;
pRP->beaconSeqno = beaconSeqno;
pRP->beaconPeriod = beaconPeriod;
pRP->level = currentDepth;
if (!call SendMsg.send(TOS_BCAST_ADDR, length, pMsgBuf)) {
#ifndef PLATFORM_PC
post SendRouteTask();
#else
atomic msgBufBusy = FALSE;
#endif
}
}
event result_t AgingTimer.fired() {
#ifndef NO_ACK_EST
if (successCounter + failCounter > 0) {
currentParentAckEst = (255 - (255 * successCounter) / (successCounter + failCounter));
successCounter = failCounter = 0;
}
#endif
if (missedBeacons > DRAIN_MAX_MISSED_BEACONS) {
if (currentParentLinkEst << 1 < 0xffff) {
currentParentLinkEst <<= 1;
} else {
currentParentLinkEst = 0xffff;
}
}
if (missedBeacons != 0xff) {
missedBeacons++;
}
call AgingTimer.start(TIMER_ONE_SHOT, (1024 * beaconPeriod));
return SUCCESS;
}
command bool DrainLinkEst.isActive() {
if (currentParentAddr == TOS_BCAST_ADDR) {
return FALSE;
} else {
return TRUE;
}
}
command result_t DrainLinkEst.messageSent(TOS_MsgPtr msg, uint8_t id,
result_t success) {
if (success) {
successCounter++;
} else {
failCounter++;
}
return SUCCESS;
}
event result_t SendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
if (pMsg == &buf) {
atomic msgBufBusy = FALSE;
}
return SUCCESS;
}
}
--- NEW FILE: DrainM.nc ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* 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 following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @author Gilman Tolle
*/
module DrainM {
provides {
interface StdControl;
interface Receive[uint8_t id];
interface Send[uint8_t id];
interface Intercept[uint8_t id];
interface Intercept as Snoop[uint8_t id];
}
uses {
interface StdControl as SubControl;
interface Leds;
interface ReceiveMsg;
interface SendMsg;
interface DrainLinkEst;
#ifndef PLATFORM_PC
interface MacControl;
#endif
}
}
implementation {
enum {
DRAIN_SEND_QUEUE_SIZE = DRAIN_QUEUE_SIZE, // Send Queue
DRAIN_FWD_QUEUE_SIZE = DRAIN_QUEUE_SIZE, // Forwarding Queue
};
// Send Queue
TOS_MsgPtr sendQueue[DRAIN_SEND_QUEUE_SIZE];
uint8_t sendQueueIn, sendQueueOut;
// Forward Queue
TOS_Msg fwdBuffers[DRAIN_FWD_QUEUE_SIZE];
TOS_MsgPtr fwdQueue[DRAIN_FWD_QUEUE_SIZE];
uint8_t fwdQueueIn, fwdQueueOut;
bool sendQueueFull;
bool fwdQueueFull;
bool queuesBusy;
uint8_t maxRetransmits;
uint8_t currentFailCount;
task void QueueServiceTask();
void initializeBufs();
TOS_MsgPtr mForward(TOS_MsgPtr pMsg, uint8_t id);
void inc(uint16_t *val);
void clear(uint16_t *val);
task void errorBlink();
/***********************************************************************
* Initialization
***********************************************************************/
command result_t StdControl.init() {
initializeBufs();
#ifdef PLATFORM_PC
maxRetransmits = 0;
#else
maxRetransmits = DRAIN_MAX_RETRANSMITS;
#endif
currentFailCount = 0;
return call SubControl.init();
}
void initializeBufs() {
int n;
for (n=0; n < DRAIN_FWD_QUEUE_SIZE; n++) {
fwdQueue[n] = &fwdBuffers[n];
}
fwdQueueIn = fwdQueueOut = 0;
fwdQueueFull = FALSE;
sendQueueIn = sendQueueOut = 0;
sendQueueFull = FALSE;
queuesBusy = FALSE;
}
command result_t StdControl.start() {
#ifndef PLATFORM_PC
atomic call MacControl.enableAck();
#endif
return call SubControl.start();
}
command result_t StdControl.stop() {
return SUCCESS;
}
/***********************************************************************
* Commands and events
***********************************************************************/
command void* Send.getBuffer[uint8_t id](TOS_MsgPtr pMsg, uint16_t* length) {
DrainMsg *pMHMsg = (DrainMsg *)pMsg->data;
*length = TOSH_DATA_LENGTH - offsetof(DrainMsg,data);
dbg(DBG_ROUTE, "Drain: getBuffer(pMsg=0x%x,id=%d,len=%d)\n",
pMsg, id, *length);
return (&pMHMsg->data[0]);
}
command result_t Send.send[uint8_t id](TOS_MsgPtr pMsg, uint16_t payloadLen) {
uint16_t usMHLength = offsetof(DrainMsg,data) + payloadLen;
dbg(DBG_ROUTE, "Drain: send(pMsg=0x%x,id=%d,len=%d)\n",
pMsg, id, payloadLen);
if (usMHLength > TOSH_DATA_LENGTH) {
return FAIL;
}
if (sendQueueFull) {
dbg(DBG_ROUTE, "Drain: sendQueueFull(pMsg=0x%x,id=%d,len=%d)\n",
pMsg, id, payloadLen);
return FAIL;
}
call DrainLinkEst.initializeFields(pMsg, id);
if (call DrainLinkEst.selectRoute(pMsg, id, TRUE) != SUCCESS) {
dbg(DBG_ROUTE, "Drain: sendSelectRouteFail(pMsg=0x%x,id=%d,len=%d)\n",
pMsg, id, payloadLen);
return FAIL;
}
dbg(DBG_ROUTE, "Drain: sendEnterQueue(pMsg=0x%x,id=%d,len=%d)\n",
pMsg, id, payloadLen);
pMsg->length = usMHLength;
if (!queuesBusy) {
if (post QueueServiceTask() == FAIL) {
return FAIL;
} else {
queuesBusy = TRUE;
}
}
sendQueue[sendQueueIn] = pMsg;
sendQueueIn = (sendQueueIn + 1) % DRAIN_SEND_QUEUE_SIZE;
if (sendQueueIn == sendQueueOut)
sendQueueFull = TRUE;
return SUCCESS;
}
event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr pMsg) {
DrainMsg *pMHMsg = (DrainMsg *)pMsg->data;
uint16_t payloadLen = pMsg->length - offsetof(DrainMsg,data);
uint8_t id = pMHMsg->type;
dbg(DBG_ROUTE, "Drain: receive(pMsg=0x%x,src=0x%02x,org=0x%02x)\n",
pMsg, pMHMsg->sourceaddr, pMHMsg->originaddr);
signal Snoop.intercept[id](pMsg, &pMHMsg->data[0], payloadLen);
if (pMsg->addr == TOS_LOCAL_ADDRESS) { // Addressed to local node
if ((signal Intercept.intercept[id](pMsg,
&pMHMsg->data[0],
payloadLen)) == SUCCESS) {
dbg(DBG_ROUTE, "Drain: forward(pMsg=0x%x,src=0x%02x,org=0x%02x)\n",
pMHMsg->sourceaddr, pMHMsg->originaddr);
pMsg = mForward(pMsg, id);
}
}
return pMsg;
}
TOS_MsgPtr mForward(TOS_MsgPtr pMsg, uint8_t id) {
TOS_MsgPtr pNewBuf = pMsg;
if (fwdQueueFull) {
dbg(DBG_ROUTE, "Drain: forwardQueueFull(pMsg=0x%x)\n", pMsg);
return pMsg;
}
if (call DrainLinkEst.selectRoute(pMsg, id, TRUE) != SUCCESS) {
dbg(DBG_ROUTE, "Drain: forwardSelectRouteFail(pMsg=0x%x)\n", pMsg);
return pMsg;
}
pNewBuf = fwdQueue[fwdQueueIn];
fwdQueue[fwdQueueIn] = pMsg;
fwdQueueIn = (fwdQueueIn + 1) % DRAIN_FWD_QUEUE_SIZE;
if (fwdQueueIn == fwdQueueOut)
fwdQueueFull = TRUE;
dbg(DBG_ROUTE, "Drain: forwardEnterQueue(pMsg=0x%x)\n", pMsg);
if (!queuesBusy) {
if (post QueueServiceTask()) {
queuesBusy = TRUE;
}
}
return pNewBuf;
}
task void QueueServiceTask() {
TOS_MsgPtr pMsg;
dbg(DBG_ROUTE, "Drain: queueServiceTask\n");
// First check send queue.
if (sendQueueIn != sendQueueOut ||
(sendQueueIn == sendQueueOut && sendQueueFull == TRUE)) {
dbg(DBG_ROUTE, "Drain: queueServiceTask(servicing=sendQueue)\n");
// We've got a message in the send queue.
pMsg = sendQueue[sendQueueOut];
pMsg->ack = 0;
if (call SendMsg.send(pMsg->addr, pMsg->length, pMsg) == SUCCESS) {
// Wait for the sendDone.
} else {
// The radio didn't accept our message.
post QueueServiceTask();
}
// Then check forward queue.
} else if (fwdQueueIn != fwdQueueOut ||
(fwdQueueIn == fwdQueueOut && fwdQueueFull == TRUE)) {
dbg(DBG_ROUTE, "Drain: queueServiceTask(servicing=forwardQueue)\n");
// We've got a message in the forward queue.
pMsg = fwdQueue[fwdQueueOut];
pMsg->ack = 0;
if (call SendMsg.send(pMsg->addr, pMsg->length, pMsg) == SUCCESS) {
// Wait for the sendDone.
} else {
// The radio didn't accept our message.
post QueueServiceTask();
}
} else {
dbg(DBG_ROUTE, "Drain: queueServiceTask(queuesAllEmpty)\n");
queuesBusy = FALSE;
return;
}
}
event result_t SendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
result_t forwardResultVal = SUCCESS;
DrainMsg* mhMsg = (DrainMsg*) pMsg->data;
dbg(DBG_ROUTE, "Drain: sendDone(pMsg=0x%x,success=%d)\n",
pMsg, success);
if (pMsg != sendQueue[sendQueueOut] &&
pMsg != fwdQueue[fwdQueueOut])
return SUCCESS;
if (!success) {
post QueueServiceTask();
return SUCCESS;
}
if (pMsg->addr == TOS_BCAST_ADDR) {
// It didn't have a destination. Don't try retransmitting.
} else {
// It did have a destination. Consider retransmitting.
if (pMsg->ack == 0) {
// It wasn't acked.
call DrainLinkEst.messageSent(pMsg, pMsg->type, FAIL);
currentFailCount++;
if (maxRetransmits > 0 && currentFailCount < maxRetransmits) {
// See if we should retransmit
if (call DrainLinkEst.selectRoute(pMsg, pMsg->type, FALSE) == SUCCESS) {
post QueueServiceTask();
return SUCCESS;
}
} else {
// We've tried to retransmit too many times. Give up.
forwardResultVal = FAIL;
}
} else {
// It was acked.
call DrainLinkEst.messageSent(pMsg, pMsg->type, SUCCESS);
}
}
dbg(DBG_ROUTE, "Drain: sendComplete(pMsg=0x%x,result=%d)\n",
pMsg, forwardResultVal);
if (pMsg == sendQueue[sendQueueOut]) {
signal Send.sendDone[mhMsg->type](pMsg, forwardResultVal);
sendQueueOut = (sendQueueOut + 1) % DRAIN_SEND_QUEUE_SIZE;
if (sendQueueFull)
sendQueueFull = FALSE;
currentFailCount = 0;
post QueueServiceTask();
} else if (pMsg == fwdQueue[fwdQueueOut]) {
fwdQueueOut = (fwdQueueOut + 1) % DRAIN_SEND_QUEUE_SIZE;
if (fwdQueueFull)
fwdQueueFull = FALSE;
currentFailCount = 0;
post QueueServiceTask();
} else {
dbg(DBG_ROUTE, "Drain: ERROR! RECEIVED SEND DONE FOR MESSAGE NOT IN QUEUE (pMsg=0x%x)\n", pMsg);
}
return SUCCESS;
}
default event result_t Send.sendDone[uint8_t id](TOS_MsgPtr pMsg,
result_t success) {
return SUCCESS;
}
default event result_t Intercept.intercept[uint8_t id](TOS_MsgPtr pMsg,
void* payload,
uint16_t payloadLen) {
return SUCCESS;
}
default event result_t Snoop.intercept[uint8_t id](TOS_MsgPtr pMsg,
void* payload,
uint16_t payloadLen) {
return SUCCESS;
}
}
More information about the Tinyos-beta-commits
mailing list