[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac Ieee802154MacC.nc, 1.12, 1.13 PollServiceM.nc, NONE, 1.1 PollM.nc, NONE, 1.1 MacConst.h, NONE, 1.1 StartM.nc, 1.5, 1.6 BeaconGeneratorM.nc, NONE, 1.1 DataM.nc, 1.5, 1.6 todo.txt, NONE, 1.1 IndirectTxM.nc, NONE, 1.1 OrphanHandlerM.nc, NONE, 1.1 CfpControlM.nc, NONE, 1.1 TimingServiceM.nc, NONE, 1.1 DummyM.nc, NONE, 1.1 MacAddressM.nc, NONE, 1.1 AssociateM.nc, 1.7, 1.8 CsmaM.nc, 1.12, 1.13 MacPib.h, 1.6, 1.7 MacPibDatabaseM.nc, 1.9, 1.10 CapControlM.nc, 1.6, 1.7 FrameTxM.nc, 1.5, 1.6 SuperframeM.nc, 1.7, 1.8 macFrame.h, 1.1, 1.2 ScanServiceM.nc, 1.2, 1.3 EdM.nc, 1.5, 1.6 BeaconTrackerM.nc, 1.11, 1.12 ScanM.nc, 1.10, 1.11 GetSetM.nc, 1.3, 1.4 MacSuperframes.h, 1.1, 1.2 mac.h, 1.11, 1.12 FrameRxM.nc, 1.6, 1.7 RxEnableM.nc, 1.7, 1.8 Ieee802154Adts.h, 1.9, 1.10 ScanOldM.nc, 1.1, NONE RawTxM.nc, 1.6, NONE RadioOperationsC.nc, 1.8, NONE DeviceAssocM.nc, 1.2, NONE RxFilterM.nc, 1.7, NONE CcaM.nc, 1.5, NONE AckTxM.nc, 1.7, NONE PhyGetSetM.nc, 1.7, NONE AckRxM.nc, 1.6, NONE const.h, 1.3, NONE RadioControlM.nc, 1.4, NONE TimingC.nc, 1.1, NONE BeaconC.nc, 1.1, NONE FrameControlC.nc, 1.1, NONE CoordinatorGtsM.nc, 1.1, NONE PrimitiveHandlerC.nc, 1.4, NONE RadioServiceM.nc, 1.7, NONE

Jan Flora janflora at users.sourceforge.net
Wed Aug 23 02:54:59 PDT 2006


Update of /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv17970/tos/lib/ieee802154/mac

Modified Files:
	CsmaM.nc MacPib.h MacPibDatabaseM.nc CapControlM.nc 
	FrameTxM.nc SuperframeM.nc macFrame.h ScanServiceM.nc EdM.nc 
	BeaconTrackerM.nc ScanM.nc GetSetM.nc MacSuperframes.h mac.h 
	FrameRxM.nc RxEnableM.nc Ieee802154Adts.h 
Added Files:
	Ieee802154MacC.nc PollServiceM.nc PollM.nc MacConst.h 
	StartM.nc BeaconGeneratorM.nc DataM.nc todo.txt IndirectTxM.nc 
	OrphanHandlerM.nc CfpControlM.nc TimingServiceM.nc DummyM.nc 
	MacAddressM.nc AssociateM.nc 
Removed Files:
	ScanOldM.nc RawTxM.nc RadioOperationsC.nc DeviceAssocM.nc 
	RxFilterM.nc CcaM.nc AckTxM.nc PhyGetSetM.nc AckRxM.nc const.h 
	RadioControlM.nc TimingC.nc BeaconC.nc FrameControlC.nc 
	CoordinatorGtsM.nc PrimitiveHandlerC.nc RadioServiceM.nc 
Log Message:
802.15.4 library updates


--- NEW FILE: PollServiceM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

#include "PhyTypes.h"
#include "mac.h"

module PollServiceM
{
	provides
	{
		interface PollService[uint8_t service];
		interface Reset;
	}
	uses
	{
		interface CapTx as DeviceTx;
		interface CapRx as DeviceRx;
		interface TimingService;
		interface PollEvents;
		interface MacAddress;
		interface Debug;
	}

}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"
	
	// Note that this module can only handle one poll at a time.
	// It would be possible to create two request queues, one for each poll type,
	// and handle subsequent requests upon poll completion.
	uint8_t dataRequestFrame[22];
	txHeader_t dataRequest;
	uint8_t pendingService;
	bool isPolling = FALSE;
	
	bool initPoll();
	bool doPoll();
	
	command void Reset.reset()
	{
		isPolling = FALSE;
	}
	
	command result_t PollService.pollCoordinator[uint8_t service](bool pollExtended)
	{
		if (!initPoll()) return FAIL;
		DBG_STRINT("Polling for service: ",service,1);
		pendingService = service;
		call MacAddress.setDstCoordinator(dataRequestFrame);
		call MacAddress.setSrcLocal(dataRequestFrame, pollExtended);
		if (!doPoll()) return FAIL;
		return SUCCESS;
	}
	
	command result_t PollService.pollAddress[uint8_t service](ieeeAddress_t *coordAddr)
	{
		if (!initPoll()) return FAIL;
		DBG_STRINT("Polling for service: ",service,1);
		pendingService = service;
		call MacAddress.setDstAddr(dataRequestFrame, coordAddr);
		call MacAddress.setSrcLocal(dataRequestFrame, FALSE);
		if (!doPoll()) return FAIL;
		return SUCCESS;
	}
	
	bool initPoll()
	{
		bool wasPolling;
		
		atomic {
			wasPolling = isPolling;
			isPolling = TRUE;
		}
		
		if (wasPolling) return FALSE;

		// Init the data request frame.
		mhrFrameType(dataRequestFrame) = macCommandFrame;
		mhrIntraPAN(dataRequestFrame) = TRUE;
	}
	
	bool doPoll()
	{
		uint8_t frameLength;
		
		msduCommandFrameIdent(dataRequestFrame) = macCommandDataReq;
		frameLength = mhrLengthFrame(dataRequestFrame) + 1;

		DBG_DUMP(dataRequestFrame, frameLength, 1);

		// Build the txHeader.
		dataRequest.addDsn = TRUE;
		dataRequest.frame = dataRequestFrame;
		dataRequest.length = frameLength;
		dataRequest.isData = FALSE;
		
		// Call cap control to transmit the data request frame.
		call DeviceTx.sendFrame(&dataRequest);
		call DeviceRx.rxOn();
		return TRUE;
	}

	event void DeviceTx.done(txHeader_t *header)
	{
		if (dataRequest.status != IEEE802154_SUCCESS) {
			isPolling = FALSE;
			call DeviceRx.rxOff();
			DBG_STRINT("Poll, could not transmit! ",pendingService,1);
			signal PollService.done[pendingService](dataRequest.status);
		} else {
			// We have to wait for the polled frame.
			call PollEvents.waitForPolledFrame();
			call TimingService.waitForFrame(deviceSuperframe);
		}
	}
	
	async event void TimingService.responseTimeout()
	{
		isPolling = FALSE;
		call PollEvents.pollTimedOut();
		// No data was available.
		call DeviceRx.rxOff();
		DBG_STRINT("Poll, timeout! ",pendingService,1);
		signal PollService.done[pendingService](IEEE802154_NO_DATA);
	}
	
	async event void PollEvents.noDataAvailable()
	{
		isPolling = FALSE;
		// No data was available.
		call DeviceRx.rxOff();
		DBG_STRINT("Poll, no data!",pendingService,1);
		signal PollService.done[pendingService](IEEE802154_NO_DATA);
	}
	
	async event void PollEvents.gotPolledFrame()
	{
		isPolling = FALSE;
		call TimingService.stopTimer();
		// Everything is good.
		call DeviceRx.rxOff();
		DBG_STRINT("Poll, success! ",pendingService, 1);
		signal PollService.done[pendingService](IEEE802154_SUCCESS);
	}
	
	default event void PollService.done[uint8_t service](Ieee_Status status)
	{
		DBG_STRINT("PollService.done not connected for service:",service,1);
	}
}

--- NEW FILE: PollM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

module PollM
{
	provides
	{
		interface IeeeRequestConfirm<Mlme_PollRequestConfirm> as MlmeRequestConfirmPoll;
	}
	uses
	{
		interface Debug;
		interface PollService;
	}

}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"
	
	Mlme_PollRequestConfirm confirm;
	
	task void pollDone();
	
	command result_t MlmeRequestConfirmPoll.request(Mlme_PollRequestConfirm request)
	{
		confirm = request;
		if (SUCCESS != call PollService.pollAddress(&(request->msg.request.coordAddr))) {
			confirm->msg.confirm.status = IEEE802154_CHANNEL_ACCESS_FAILURE;
			return FAIL;
		}
		return SUCCESS;
	}

	event void PollService.done(Ieee_Status status)
	{
		confirm->msg.confirm.status = status;
		post pollDone();
	}

	task void pollDone()
	{
		signal MlmeRequestConfirmPoll.confirm(confirm);
	}

}

--- NEW FILE: MacConst.h ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

#ifndef _CONST_H_
#define _CONST_H_

#define aAclEntryDescriptorSetMaxSize 1

// Scan module
#define Ieee_Num_PAN_Desc      5

// CAP module
#define NUMCOORDCAPSLOTS       4
#define NUMDEVICECAPSLOTS      4
#define NUMCAPDONESLOTS        4

// Indirect transmission module
#define NUMINDIRECTSLOTS       5
#define NUMINDIRECTDONESLOTS   2

// Associate module
#define ASSOCQUEUESIZE         4

// RxEnable module
#define RXENABLEQUEUESIZE      3

// CFP module
#define CFPTXQUEUESIZE         5
#define NUMCFPDONESLOTS        4

#endif


--- NEW FILE: BeaconGeneratorM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

#include "mac.h"
#include "MacSuperframes.h"
#include "MacPib.h"

module BeaconGeneratorM
{
	provides
	{
		interface IeeeIndication<Mlme_SyncLossIndication> as MlmeIndicationSyncLoss;
		interface BeaconGenerator;
		interface CapEvents as CoordinatorCap;
		//interface Reset;
	}
	uses
	{
		interface CapTx as CoordinatorTx;
		interface RxFrame as BeaconReqFrame;
		interface IeeeBufferManagement as BufferMng;
		interface AsyncAlarm<time_t> as BeaconAlarm;
		interface AsyncAlarm<time_t> as CfpAlarm;
		interface BeaconDataService;
		interface FrameTx;
		interface LocalTime;
		interface Superframe;
		//interface PanConflict;
		interface MacAddress;
		interface Debug;
	}
}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"
	
	uint8_t *myBeacon;
	uint8_t msduLength = 0;
	msduSuperframeSpec_t *sfSpec;
	
	time_t nextCommence;
	time_t capEnd;
	time_t cfpEnd;
	bool waitingForCapEnd = FALSE;
	bool waitingForCfpEnd = FALSE;
	
	txdata_t myTxData;
	bool firstBeacon = FALSE;
	
	void generateBeacon();
	void transmitBeacon();
	
	command result_t BeaconGenerator.start()
	{
		if (macPanCoordinator) {
			firstBeacon = TRUE;
			generateBeacon();
			transmitBeacon();
		} else {
			// Align beacon to PAN Coordinator beacon.
		}
		return SUCCESS;
	}
	
	command result_t BeaconGenerator.stop()
	{
		return SUCCESS;
	}
	
	async event uint8_t *BeaconReqFrame.received(rxdata_t *data)
	{
		if (!macBeaconEnabled) {
			// Transmit beacon in CAP.
			txHeader_t *myTxHeader;
			
			generateBeacon();
			
			// Allocate the txHeader.
			if (SUCCESS != call BufferMng.claim(sizeof(txHeader_t), (uint8_t**)&myTxHeader)) {
				DBG_STR("FATAL: Associate, could not claim memory for transmission header",1);
			}
			
			// Build the txHeader.
			myTxHeader->addDsn = TRUE;
			myTxHeader->frame = myBeacon;
			myTxHeader->length = mhrLengthFrame(myBeacon) + msduLength;
			myTxHeader->isData = FALSE;

			call CoordinatorTx.sendFrame(myTxHeader);
		}
		return data->frame;
	}
	
	event void CoordinatorTx.done(txHeader_t *header)
	{
		// Release frame and tx header.
		call BufferMng.release(126, header->frame);
		call BufferMng.release(sizeof(txHeader_t), (uint8_t*)header);
	}
	
	void generateBeacon()
	{
		// Here we generate a beacon msg.
		msduGTSSpec_t *gtsSpec;
		msduPendingAddrSpec_t *pendingSpec;
		uint8_t numShortAddrs;
		uint8_t numExtAddrs;
		
		// Allocate memory for the beacon frame.
		if (SUCCESS != call BufferMng.claim(126,&myBeacon)) {
			DBG_STR("WARNING: BeaconGenerator, Unable to claim buffer for beacon frame!",1);
			return;
		}
		
		// First we clear the first two bytes. Only the src addressing mode needs to be set
		// there! (Beacon frame = 0x00).
		myBeacon[0] = 0;
		myBeacon[1] = 0;
		// Set source address.
		call MacAddress.setSrcLocal(myBeacon, FALSE);
		// Set sequence number
		mhrSeqNumber(myBeacon) = macBsn;
		macBsn++;
		// Fill in superframe spec.
		msduLength = 2;
		sfSpec = msduGetSuperframeSpec(myBeacon);
		sfSpec->BeaconOrder = macBeaconOrder;
		sfSpec->SuperframeOrder = macSuperframeOrder;
		sfSpec->FinalCAPSlot = 15;
		sfSpec->BatteryLifeExtension = macBattLifeExt;
		sfSpec->PANCoordinator = macPanCoordinator;
		sfSpec->AssociationPermit = macAssociationPermit;
		// Fill GTS spec.
		// TODO: Fill in the right GTS count, direction mask and GTS list.
		gtsSpec = msduGetGTSSpec(myBeacon);
		gtsSpec->GTSDescriptorCount = 0;
		gtsSpec->GTSPermit = macGtsPermit;
		msduLength += 1;
		// Fill pending addresses.
		pendingSpec = msduPendingAddrSpec(myBeacon);
		call BeaconDataService.getPendingAddrs(&(numShortAddrs),
		                                       &(numExtAddrs),
		                                       msduPendingAddrList(myBeacon));
		pendingSpec->NumShortAddrsPending = numShortAddrs;
		pendingSpec->NumExtAddrsPending = numExtAddrs;
		msduLength += 1 + 2*numShortAddrs + 8*numExtAddrs;
		// TODO: Append beacon payload.
	}
	
	void transmitBeacon()
	{
		// Transmit the frame.
		myTxData.frame = myBeacon;
		myTxData.length = mhrLengthFrame(myBeacon) + msduLength;
		myTxData.cca = FALSE;
		myTxData.immediateCommence = FALSE;
		// If first beacon, commence 100 symbol periods from now.
		if (firstBeacon) {
			firstBeacon = FALSE;
			myTxData.commenceTime = call LocalTime.getTime() + 100;
		} else {
			myTxData.commenceTime = nextCommence;
		}
		
		if (PHY_SUCCESS != call FrameTx.tx(&myTxData)) {
			DBG_STR("WARNING: BeaconGenerator, could not transmit beacon!",1);
			// Release the memory for the beacon frame.
			call BufferMng.release(126, myBeacon);
			return;
		}		
		// Update coordinator superframe.
		call Superframe.updateFromSpec(&coordinatorSuperframe, sfSpec,
		                               myTxData.commenceTime, myTxData.length);
		
		macBeaconTxTime = myTxData.commenceTime;
		
		nextCommence = call Superframe.getNextStart(&coordinatorSuperframe);
		
		// Set up the beacon alarm to fire just before next beacon transmission
		call BeaconAlarm.armAlarmClock(nextCommence-100);
	}
	
	async event void FrameTx.txDone(phy_error_t error)
	{
		// Release the memory for the beacon frame.
		call BufferMng.release(126, myBeacon);
		if (error == PHY_SUCCESS) {
			coordCapActive = TRUE;
			signal CoordinatorCap.startNotification();

			capEnd = call Superframe.getCapEnd(&coordinatorSuperframe);
			// We end the cap 82 symbols before real cap end.
			// This is due to the fact, that the shortest tx packet takes
			// 30 symbols to transmit. Including both 2*CCA + SIFS makes 82 symbols.
			if (capEnd < nextCommence) {
				// We need to activate CFP or idle period at CAP end.
				call CfpAlarm.armAlarmClock(capEnd-82);
				waitingForCapEnd = TRUE;
			}
			// Expire old indirect tx slots.
			call BeaconDataService.expireSlots();
		}
	}
	
	async event result_t BeaconAlarm.alarm()
	{
		// Time to transmit beacon.
		coordCapActive = FALSE;
		generateBeacon();
		transmitBeacon();
		return SUCCESS;
	}

	async event result_t CfpAlarm.alarm()
	{
		if (waitingForCapEnd) {
			// CAP has ended.
			coordCapActive = FALSE;
			if (call Superframe.cfpExists(&coordinatorSuperframe)) {
				// We start up the device CFP.
				//signal CoordinatorCfp.startNotification();
				cfpEnd = call Superframe.getCfpEnd(&coordinatorSuperframe);
				if (cfpEnd < nextCommence) {
					call CfpAlarm.armAlarmClock(cfpEnd-82);
					waitingForCfpEnd = TRUE;
				}
			} else {
				// TODO: Below note could be a problem.
				// NOTE: Coordinator CAP and CFP can be active in the idle period.
				// Idle period.
			}
			waitingForCapEnd = FALSE;
		} else if (waitingForCfpEnd) {
			// TODO: Below note could be a problem.
			// NOTE: Coordinator CAP and CFP can be active in the idle period.
			// Idle period.
			waitingForCfpEnd = FALSE;
		}
		return SUCCESS;
	}
}


--- NEW FILE: todo.txt ---

TODO:
-------
 - Only wait for frame response timeouts while in CAP!
 - Beacon tracker needs to handle beacon payload
 - Disassociate (Should be easy!)
 - Indirect tx module..
 - CFP & GTS (including gts support in beacons)
 - Data transmission (direct, indirect, GTS) and reception
 - Beacon generation (including the start primitive and coordinator CAP)
 - Associate functions for coordinator! (Handling indication & response)
 - RxEnable (should be easy when we have CAP control in place)
 - Reset?
 - Orphan handling
 - PAN conflict handling

--- NEW FILE: IndirectTxM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

module IndirectTxM
{
	provides
	{
		interface IeeeRequestConfirm<Mcps_PurgeRequestConfirm> as McpsRequestConfirmPurge;
		interface IndirectTx as IndirectTx[uint8_t token];
		interface BeaconDataService;
	}
	uses
	{
		interface IeeeBufferManagement as BufferMng;
		interface RxFrame as DataReqFrame;
		interface CapTx as CoordinatorTx;
		interface MacAddress;
		interface Debug;
	}
}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"

	Mcps_PurgeRequestConfirm purgePrimitive;

	indirectTxQueue_t myQueue[NUMINDIRECTSLOTS];
	txDoneEntry_t doneQueue[NUMINDIRECTDONESLOTS];
	uint8_t doneQueueCount = 0;
	bool donePosted = FALSE;
	
	void checkQueue(uint8_t mode, uint8_t *address);
	bool matchEntry(uint8_t entry, uint8_t *address);
	uint8_t getAddresses(uint8_t mode, uint8_t *dest);
	task void txDoneTask();
	task void confirmPurge();
	
	command result_t McpsRequestConfirmPurge.request(Mcps_PurgeRequestConfirm request)
	{
		uint8_t i;
		uint8_t myHandle = request->msg.request.msduHandle;
		// This is called once each superframe.
		for (i=0;i<NUMINDIRECTSLOTS;i++) {
			if (myQueue[i].status == SLOT_PENDING && myQueue[i].data->isData &&
			    myQueue[i].data->msduHandle == myHandle) {
				// We purge this entry.
				// Release frame and tx header.
				call BufferMng.release(myQueue[i].data->length, myQueue[i].data->frame);
				call BufferMng.release(sizeof(txHeader_t), (uint8_t*)myQueue[i].data);
				myQueue[i].status = SLOT_EMPTY;
				request->msg.confirm.status = IEEE802154_SUCCESS;
				purgePrimitive = request;
				post confirmPurge();
				return SUCCESS;
			}
		}
		request->msg.confirm.status = IEEE802154_INVALID_HANDLE;
		return FAIL;
	}
	
	command void IndirectTx.send[uint8_t token](txHeader_t *header)
	{
		uint8_t i;
		// Find an empty slot.
		for (i=0;i<NUMINDIRECTSLOTS;i++) {
			if (myQueue[i].status == SLOT_EMPTY) {
				// This slot is empty and ready for use.
				myQueue[i].status = SLOT_PENDING;
				myQueue[i].token = token;
				myQueue[i].data = header;
				myQueue[i].address = mhrDestAddr(header->frame);
				myQueue[i].expiryCount = macTransactionPersistenceTime;
				myQueue[i].addrMode = mhrDestAddrMode(header->frame);
				return;
			}
		}
		// If we get here, no slots are available!
		header->status = IEEE802154_TRANSACTION_OVERFLOW;
		doneQueue[doneQueueCount].header = header;
		doneQueue[doneQueueCount++].doneToken = token;
		if (!donePosted) {
			donePosted = post txDoneTask();
		}
	}
	
	command void BeaconDataService.getPendingAddrs(uint8_t *shortCnt, uint8_t *extCnt, uint8_t *data)
	{
		// This command extracts the pending addresses into the "data" pointer,
		// indicating the number of pending addresses of each type in shortCnt and extCnt.
		
		// TODO: When more than 7 pending addresses, the addresses should be
		//       published on a first-come-first-served basis!
		*shortCnt = getAddresses(2, data);
		if (*shortCnt < 7) {
			data += (*shortCnt)*2;
			*extCnt = getAddresses(3, data);
			if (*extCnt + *shortCnt > 7) {
				*extCnt = 7 - *shortCnt;
			}
		} else {
			*shortCnt = 7;
			*extCnt = 0;
		}
	}
	
	command void BeaconDataService.expireSlots()
	{
		uint8_t i;
		// This is called once each superframe.
		for (i=0;i<NUMINDIRECTSLOTS;i++) {
			if (myQueue[i].status == SLOT_PENDING) {
				myQueue[i].expiryCount--;
				if (!(myQueue[i].expiryCount)) {
					// Expire this entry.
					myQueue[i].data->status = IEEE802154_TRANSACTION_EXPIRED;
					signal IndirectTx.done[myQueue[i].token](myQueue[i].data);
					myQueue[i].status = SLOT_EMPTY;
				}
			}
		}
	}
	
	uint8_t getAddresses(uint8_t mode, uint8_t *dest)
	{
		uint8_t i;
		uint8_t count = 0;
		uint8_t addrLen = (((mode)&1)?8:(mode));
		for (i=0;i<NUMINDIRECTSLOTS;i++) {
			if (myQueue[i].status == SLOT_PENDING && myQueue[i].addrMode == mode) {
				memcpy(dest, myQueue[i].address, addrLen);
				dest += addrLen;
				count++;
			}
		}
		return count;
	}
	
	bool matchEntry(uint8_t entry, uint8_t *address)
	{
		if (myQueue[entry].addrMode == 3) {
			if (int64Compare(address, myQueue[entry].address)) return TRUE;
		} else {
			// Assume mode == 2.
			if (*((uint16_t*)myQueue[entry].address) == *((uint16_t*)address)) return TRUE;
		}
		return FALSE;
	}
	
	void checkQueue(uint8_t mode, uint8_t *address)
	{
		uint8_t best, i;
		bool found = FALSE;
		bool multiple = FALSE;
		for (i=0;i<NUMINDIRECTSLOTS;i++) {
			if (myQueue[i].status == SLOT_PENDING && myQueue[i].addrMode == mode) {
				// We have an entry matching the addressing mode.
				if (matchEntry(i, address)) {
					// We have a match.
					if (found) {
						multiple = TRUE;
						if (myQueue[best].expiryCount > myQueue[i].expiryCount) {
							// We pick the oldest entry.
							best = i;
						}
					} else {
						found = TRUE;
						best = i;
					}
				}
			}
		}
		if (found) {
			if (multiple) {
				// There is more than one pending frame for the requesting device
				// Set frame pending bit in frame control.
				mhrFramePending(myQueue[best].data->frame) = TRUE;
			}
			// Send frame in cap.
			call CoordinatorTx.sendFrame(myQueue[best].data);
		}
	}
	
	event void CoordinatorTx.done(txHeader_t *header)
	{
		if (header->status == IEEE802154_SUCCESS) {
			// Make slot available and signal tx done.
			uint8_t i;
			for (i=0;i<NUMINDIRECTSLOTS;i++) {
				if (myQueue[i].status == SLOT_PENDING && myQueue[i].data == header) {
					signal IndirectTx.done[myQueue[i].token](header);
					myQueue[i].status = SLOT_EMPTY;
					return;
				}
			}
		}
	}
	
	async event uint8_t *DataReqFrame.received(rxdata_t *data)
	{
		ieeeAddress_t requester;
		call MacAddress.getSrcAddr(data->frame, &requester);
		checkQueue(requester.mode, requester.address);
		return data->frame;
	}
	
	task void txDoneTask()
	{
		while(doneQueueCount) {
			signal IndirectTx.done[doneQueue[--doneQueueCount].doneToken](doneQueue[doneQueueCount].header);
		}
		donePosted = FALSE;
	}
	
	task void confirmPurge()
	{
		signal McpsRequestConfirmPurge.confirm(purgePrimitive);
	}
	
	default event void IndirectTx.done[uint8_t token](txHeader_t *header)
	{
		DBG_STRINT("IndirectTx done not connected for module:",token,1);
	}
	
	default event void McpsRequestConfirmPurge.confirm(Mcps_PurgeRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled McpsRequestConfirmPurge.confirm",1);
	}
}

--- NEW FILE: OrphanHandlerM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

module OrphanHandlerM
{
	provides
	{
		interface IeeeIndicationResponse<Mlme_OrphanIndicationResponse> as MlmeIndicationResponseOrphan;
		interface IeeeIndication<Mlme_CommStatusIndication> as MlmeIndicationCommStatus;
		interface Realignment;
	}
	uses
	{
		interface MacAddress;
		interface CapTx as CoordinatorTx;
		interface RxFrame as OrphanNotFrame;
		interface IeeeBufferManagement as BufferMng;
		interface Debug;
	}
}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"

	command void Realignment.create(uint8_t *frame, bool broadcast, uint8_t *address)
	{
		mhrFramePending(frame) = FALSE;
		mhrAckRequest(frame) = !broadcast;
		mhrIntraPAN(frame) = FALSE;

		if (broadcast) {
			mhrDestAddrMode(frame) = 2;
			*((uint16_t*)mhrDestAddr(frame)) = aBcastShortAddr;
		} else {
			mhrDestAddrMode(frame) = 3;	
			NTOUH64(address, mhrDestAddr(frame));
		}
		*((uint16_t*)mhrDestPANId(frame)) = aBcastPANId;
		
		call MacAddress.setSrcLocal(frame, TRUE);
		
		mhrSecurityEnabled(frame) = FALSE;
		
		mhrFrameType(frame) = macCommandFrame;
		msduCommandFrameIdent(frame) = macCommandCoordRealign;
		*((uint16_t*)msduCoordRealignPANId(frame)) = macPanId;
		*((uint16_t*)msduCoordRealignCoordShortAddr(frame)) = macShortAddress;
		// TODO: Where to fetch the current channel?
		msduCoordRealignLogicalChannel(frame) = 0x0B;
		if (broadcast) {
			// Set short address to broadcast short address.
			*((uint16_t*)msduCoordRealignShortAddr(frame)) = aBcastShortAddr;
		}
	}

	command result_t MlmeIndicationResponseOrphan.response( Mlme_OrphanIndicationResponse response )
	{
		txHeader_t *myTxHeader;
		
		// Allocate the txHeader.
		if (SUCCESS != call BufferMng.claim(sizeof(txHeader_t), (uint8_t**)&myTxHeader)) {
			DBG_STR("FATAL: Associate, could not claim memory for transmission header",1);
		}
		
		// Build the txHeader.
		myTxHeader->addDsn = TRUE;
		myTxHeader->frame = response->msg.response.coordRealignFrame;
		myTxHeader->length = mhrLengthFrame(myTxHeader->frame) + 8;
		myTxHeader->isData = FALSE;

		// Destroy primitive.
		call BufferMng.release(sizeof(mlmeAssociateIndicationResponse_t), (uint8_t*)response);
		//DBG_DUMP(myTxHeader->frame, myTxHeader->length, 1);
		call CoordinatorTx.sendFrame(myTxHeader);
		return SUCCESS;
	}

	event void CoordinatorTx.done(txHeader_t *header)
	{
		// Transmission completed. Signal comm status with tx status.
		mlmeCommStatusIndication_t *commStatusIndication;
		
		DBG_STRINT("Tx status was:",header->status,1);
		
		// Allocate space for a comm status indication
		if (SUCCESS != call BufferMng.claim(sizeof(mlmeCommStatusIndication_t), (uint8_t**)&commStatusIndication)) {
			DBG_STR("FATAL: OrphanHandler, could not claim memory for comm status indication",1);
		}
		// NOTE: Notification frames are always reused for response frames, meaning that
		//       the frame length in the comm status indication must be the max frame length.
		commStatusIndication->msg.indication.responseFrame = header->frame;
		commStatusIndication->msg.indication.frameLength = 126;
		commStatusIndication->msg.indication.status = header->status;
		
		// Deallocate txHeader.
		call BufferMng.release(sizeof(txHeader_t), (uint8_t*)header);
		signal MlmeIndicationCommStatus.indication(commStatusIndication);
	}
	
	async event uint8_t *OrphanNotFrame.received(rxdata_t *data)
	{
		// NOTE: This is signalled to the upper layer in async context.
		uint8_t *newBuffer;
		mlmeOrphanIndicationResponse_t *orphanIndication;
		
		if (SUCCESS != call BufferMng.claim(sizeof(mlmeOrphanIndicationResponse_t), (uint8_t**)&orphanIndication)) {
			DBG_STR("FATAL: Associate, could not claim memory for Disassociate Indication",1);
		}

		orphanIndication->msg.indication.orphanNotificationFrame = data->frame;
		signal MlmeIndicationResponseOrphan.indication(orphanIndication);
		
		// Frame buffer is reused for association response.
		if (SUCCESS != call BufferMng.claim(126, &newBuffer)) {
			DBG_STR("FATAL: Associate, could not claim memory for new receive buffer",1);
		}
		
		return newBuffer;
	}

	default event void MlmeIndicationCommStatus.indication(Mlme_CommStatusIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationCommStatus.indication",1);
	}
	
	default async event void MlmeIndicationResponseOrphan.indication(Mlme_OrphanIndicationResponse indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationResponseOrphan.indication",1);
	}
}

--- NEW FILE: CfpControlM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

module CfpControlM
{
	provides
	{
		interface IeeeIndication<Mlme_GtsIndication> as MlmeIndicationGts;		
		interface IeeeRequestConfirm<Mlme_GtsRequestConfirm> as MlmeRequestConfirmGts;
		interface BeaconGtsService;
	}
	uses
	{
		interface CapTx as DeviceTx;
		interface IeeeBufferManagement as BufferMng;
		interface Debug;
	}
}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"

	// Only one GTS request can be processed at a time.
	Mlme_GtsRequestConfirm gtsConfirm;

	// First two descriptors are for device operation.
	// Descriptor 0 = device receive
	// Descriptor 1 = device transmit
	// Descriptor 2-8 = coordinator GTS's
	gtsDescriptor_t descriptorSlots[9];

	cfpTx_t dataQueue[CFPTXQUEUESIZE];
	txDoneEntry_t doneQueue[NUMCFPDONESLOTS];
	uint8_t doneQueueCount = 0;
	bool donePosted = FALSE;
	txdata_t myTxData;

	// Timeout variables.
	bool waitingForGtsUpdate = FALSE;
	uint8_t waitCount;

	task void txDoneTask();

	command void BeaconGtsService.gtsUpdate(uint8_t start, uint8_t length, bool deviceTxSlot)
	{
		uint8_t mySlot = (deviceTxSlot?1:0);
		
		if (start != 0) {
			// If start != 0 this is either an allocation or reallocation.
			// Just update the slot.
			descriptorSlots[mySlot].startSlot = start;
			descriptorSlots[mySlot].duration = length;
			descriptorSlots[mySlot].valid = TRUE;
			if (waitingForGtsUpdate) {
				waitingForGtsUpdate = FALSE;
				gtsConfirm->msg.confirm.status = IEEE802154_SUCCESS;
				signal MlmeRequestConfirmGts.confirm(gtsConfirm);
			}
		} else {
			// Else we have a failed allocation or a deallocation.
			// Just invalidate the entry.
			descriptorSlots[mySlot].valid = FALSE;
			// TODO: if deviceTxSlot, fail all entries in the data queue.
			if (waitingForGtsUpdate) {
				gtsConfirm->msg.confirm.status = IEEE802154_DENIED;
				signal MlmeRequestConfirmGts.confirm(gtsConfirm);
			} else {
				// TODO: signal GTS indication.
			}
		}
	}

	command void GtsTx.sendFrame(txHeader_t *header, uint16_t shortAddr)
	{
		uint8_t myDescriptor;
		bool descriptorFound = FALSE;
		if (shortAddr == macCoordShortAddress) {
			// Check if we have a valid device GTS
			if (descriptorSlots[1].valid) {
				// We have a valid descriptor.
				myDescriptor = 1;
				descriptorFound = TRUE;
			}
		} else if (macCoordinator) {
			uint8_t i;
			// Check if we have a valid coordinator GTS
			for (i=2;i<9;i++) {
				if (descriptorSlots[i].valid && descriptorSlots[i].shortAddr == shortAddr
				    && descriptorSlots[i].direction == 1) {
					// We have a valid descriptor.
					myDescriptor = i;
					descriptorFound = TRUE;
					break;
				}
			}
		} else {
			// Invalid request. No available GTS.
			header->status = IEEE802154_INVALID_GTS;
		}
		
		if (descriptorFound) {
			// Enqueue header.
			uint8_t i;
			for (i=0;i<CFPTXQUEUESIZE;i++) {
				if (dataQueue[i].status == SLOT_EMPTY) {
					dataQueue[i].status = SLOT_PENDING;
					dataQueue[i].header = header;
					dataQueue[i].gtsIndex = myDescriptor;
					return;
				}
			}
			// If this point is reached, no queue space is left.
			header->status = IEEE802154_TRANSACTION_OVERFLOW;
		}
		// If we get here, we need to report an error back.
		doneQueue[doneQueueCount++].header = header;
		if (!donePosted) {
			donePosted = post txDoneTask();
		}
	}

	event void CoordinatorCfp.startNotification()
	{
	
	}
	
	event void DeviceCfp.startNotification()
	{
		
	}
	
	command result_t MlmeRequestConfirmGts.request(Mlme_GtsRequestConfirm request)
	{
		// We just transmit the gts request.
		txHeader_t *myTxHeader;
		
		// If no short address is assigned, we fail.
		if (macShortAddr == aBcastShortAddr || macShortAddr == aNoShortAddr) {
			request->msg.confirm.status = IEEE802154_NO_SHORT_ADDRESS;
			return FAIL;
		}
		
		gtsConfirm = request;
		
		// Allocate the txHeader.
		if (SUCCESS != call BufferMng.claim(sizeof(txHeader_t), (uint8_t**)&myTxHeader)) {
			DBG_STR("FATAL: Data, could not claim memory for transmission header",1);
			return FAIL;
		}
		
		// Build the txHeader.
		myTxHeader->addDsn = TRUE;
		myTxHeader->frame = frame;
		myTxHeader->length = 9;
		myTxHeader->isData = FALSE;
		
		// Direct transfer.
		call DeviceTx.sendFrame(myTxHeader);
		return SUCCESS;
	}
	
	event void DeviceTx.done(txHeader_t *header)
	{
		// Set status and frame.
		// NOTE: GTS request is deallocated with the confirm primitive.
		gtsConfirm->msg.confirm.status = header->status;
		gtsConfirm->msg.confirm.GTSRequestFrame = header->frame;
		
		// Deallocate the tx header.
		if (SUCCESS != call BufferMng.release(sizeof(txHeader_t), (uint8_t*)header)) {
			DBG_STR("WARNING: Data, could not release memory for transmission header",1);
		}
		
		if (gtsConfirm->msg.confirm.status == IEEE802154_SUCCESS) {
			waitingForGtsUpdate = TRUE;
			waitCount = aGTSDescPersistenceTime;
		} else {
			// An error was encountered while sending the GTS request.
			signal MlmeRequestConfirmGts.confirm(gtsConfirm);
		}
	}
	
	command void BeaconGtsService.beaconReceived()
	{
		// Check if we were waiting for a GTS update.
		if (waitingForGtsUpdate) {
			waitCount--;
			if (--waitCount == 0) {
				// Timeout!
				waitingForGtsUpdate = FALSE;
				gtsConfirm->msg.confirm.status = IEEE802154_NO_DATA;
				signal MlmeRequestConfirmGts.confirm(gtsConfirm);
			}
		}
	}
	
	async event uint8_t *GtsReqFrame.received(rxdata_t *data)
	{
		msduGtsCharacteristics_t *myGtsChar = msduGtsRequestGtsCharacteristics(data->frame);
		uint16_t deviceAddr = *((uint16_t*)mhrSrcAddr(data->frame));
		if (myGtsChar->CharType == 1) {
			// Try to allocate GTS.
			uint8_t myDescriptor;
			bool descriptorFound = FALSE;
			uint8_t i;
			// Find an available descriptor slot.
			for (i=2;i<9;i++) {
				if (!(descriptorSlots[i].valid) && !(descriptorSlots[i].beaconPublishCount)) {
					// We have a available descriptor slot.
					myDescriptor = i;
					descriptorFound = TRUE;
					break;
				}
			}
			if (!descriptorFound) {
				// We have no free descriptors...
				// TODO: Can we just ignore this and let the requesting device fail
				//       with status NO_DATA?
				return data->frame;
			}
			if ((coordinatorSuperframe.capLength - myGtsChar->GTSLength)*coordinatorSuperframe.slotLength
			    < aMinCAPLength) {
				// We can't allocate this GTS without making the CAP too small.
				descriptorSlots[i].valid = FALSE;
				descriptorSlots[i].startSlot = 0;
				descriptorSlots[i].duration = aNumSuperframeSlots;
				descriptorSlots[i].direction = myGtsChar->GTSDirection;
				descriptorSlots[i].shortAddr = deviceAddr;
				descriptorSlots[i].beaconPublishCount = aGTSDescPersistenceTime;
			} else {
				// Update the coordinator superframe cap.
				coordinatorSuperframe.capLength -= myGtsChar->GTSLength;
				// Just go ahead and allocate the GTS
				descriptorSlots[i].valid = TRUE;
				// We count superframe slots from 0. So CapLength is actually equal to
				// the slot index of the start of the CFP.
				descriptorSlots[i].startSlot = coordinatorSuperframe.capLength;
				descriptorSlots[i].duration = myGtsChar->GTSLength;
				descriptorSlots[i].direction = myGtsChar->GTSDirection;
				descriptorSlots[i].shortAddr = deviceAddr;
				descriptorSlots[i].beaconPublishCount = aGTSDescPersistenceTime;
				// TODO: Notify upper layer
			}
		} else {
			// Try to deallocate GTS.
			uint8_t i;
			// Find GTS to deallocate.
			for (i=2;i<9;i++) {
				if (descriptorSlots[i].valid && descriptorSlots[i].shortAddr == deviceAddr
				    && descriptorSlots[i].direction == myGtsChar->GTSDirection) {
					// We have match. Invalidate descriptor.
					descriptorSlots[i].valid = FALSE;
					// TODO: Notify upper layer
					// Publish in beacon.
					descriptorSlots[i].beaconPublishCount = aGTSDescPersistenceTime;
					break;
				}
			}
		}
		return data->frame;
	}
	
	task void txDoneTask()
	{
		while(doneQueueCount) {
			signal GtsTx.done(doneQueue[--doneQueueCount].header);
		}
		donePosted = FALSE;
	}
	
	void tendDeviceSlots(uint8_t sfSlot)
	{
		time_t slotStart = call Superframe.getSlotStartTime(&deviceSuperframe, sfSlot);
		// Device is easy
		if (descriptorSlots[0].valid && descriptorSlots[0].startSlot == sfSlot) {
			// Start the receiver at the slot boundary.
			if (PHY_SUCCESS != call FrameRx.rxOn(slotStart)) {
				DBG_STR("Warning: CfpControl, could not enable receiver!",1);
			}
		} else if (descriptorSlots[1].valid &&
		           descriptorSlots[1].startSlot <= sfSlot &&
		           (descriptorSlots[1].startSlot + descriptorSlots[1].duration - 1) >= sfSlot) {
			// Check if we have something to send.
			uint8_t i;
			for (i=0; i<CFPTXQUEUESIZE;i++) {
				if (dataQueue[i].gtsIndex == 1 && dataQueue[i].status == TX_PENDING) {
					// We send the data if it fits in the current gts.
					myTxData.frame = dataQueue[i].header->frame;
					myTxData.length = dataQueue[i].header->length;
					myTxData.cca = FALSE;
					
					// Check time.
					if (slotStart < call LocalTime.getTime()) {
						myTxData.immediateCommence = TRUE;
					} else {
						myTxData.immediateCommence = FALSE;
						myTxData.commenceTime = slotStart;
					}
				}
			}
		}
	}
	
	default event void MlmeRequestConfirmGts.confirm(Mlme_GtsRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmGts.confirm",1);
	}
	
	default event void MlmeIndicationGts.indication(Mlme_GtsIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationGts.indication",1);
	}
}
--- NEW FILE: TimingServiceM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

#include "MacSuperframes.h"

module TimingServiceM
{	
	provides
	{
		interface TimingService[uint8_t service];
	}
	uses
	{
		interface AsyncAlarm<time_t> as ResponseWaitAlarm;
		interface AsyncAlarm<time_t> as FrameResponseAlarm;
		interface Debug;
	}
	
}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"
	
	typedef struct
	{
		bool active;
		uint8_t service;
		time_t waitTime;
		
	} waitEntry_t;
	
	waitEntry_t waitState[2];
	
	uint8_t responseWaitService;
	uint8_t frameResponseService;
	
	command void TimingService.waitForResponse[uint8_t service]()
	{
		waitState[0].active = TRUE;
		waitState[0].
		responseWaitService = service;
		call ResponseWaitAlarm.armCountdown(aResponseWaitTime);
	}

	command void TimingService.waitForFrame[uint8_t service](superframe_t sf)
	{
		frameResponseService = service;
		call FrameResponseAlarm.armCountdown(aMaxFrameResponseTime);
	}

	command void TimingService.stopTimer[uint8_t service]()
	{
		if (responseWaitService == service) {
			call ResponseWaitAlarm.stop();
		}
		if (frameResponseService == service) {
			call FrameResponseAlarm.stop();
		}
	}

	async event result_t ResponseWaitAlarm.alarm()
	{
		signal TimingService.responseTimeout[responseWaitService]();
		return SUCCESS;
	}
	
	async event result_t FrameResponseAlarm.alarm()
	{
		signal TimingService.responseTimeout[frameResponseService]();
		return SUCCESS;
	}
	
	default async event void TimingService.responseTimeout[uint8_t service]()
	{
		DBG_STRINT("TimingService.responseTimeout not wired for service:",service,1);
	}
	
}

--- NEW FILE: DummyM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

// Provide all the interfaces not implemented yet.
module DummyM
{
	provides
	{
		interface IeeeIndication<Mcps_DataIndication> as McpsIndicationData;
		interface IeeeRequestConfirm<Mcps_DataRequestConfirm> as McpsRequestConfirmData;
		interface IeeeRequestConfirm<Mcps_PurgeRequestConfirm> as McpsRequestConfirmPurge;
		// MLME
		interface IeeeIndicationResponse<Mlme_AssociateIndicationResponse> as MlmeIndicationResponseAssociate;
		interface IeeeRequestConfirm<Mlme_AssociateRequestConfirm> as MlmeRequestConfirmAssociate;
		interface IeeeIndication<Mlme_BeaconNotifyIndication> as MlmeIndicationBeaconNotify;
		interface IeeeIndication<Mlme_CommStatusIndication> as MlmeIndicationCommStatus;
		interface IeeeIndication<Mlme_DisassociateIndication> as MlmeIndicationDisassociate;
		interface IeeeRequestConfirm<Mlme_DisassociateRequestConfirm> as MlmeRequestConfirmDisassociate;						
		interface IeeeRequestConfirm<Mlme_GetRequestConfirm> as MlmeRequestConfirmGet;
		interface IeeeIndication<Mlme_GtsIndication> as MlmeIndicationGts;		
		interface IeeeRequestConfirm<Mlme_GtsRequestConfirm> as MlmeRequestConfirmGts;
		interface IeeeIndicationResponse<Mlme_OrphanIndicationResponse> as MlmeIndicationResponseOrphan;
		interface IeeeRequestConfirm<Mlme_PollRequestConfirm> as MlmeRequestConfirmPoll;
		interface IeeeRequestConfirm<Mlme_ResetRequestConfirm> as MlmeRequestConfirmReset;
		interface IeeeRequestConfirm<Mlme_RxEnableRequestConfirm> as MlmeRequestConfirmRxEnable;
//		interface IeeeRequestConfirm<Mlme_ScanRequestConfirm> as MlmeRequestConfirmScan;
		interface IeeeRequestConfirm<Mlme_SetRequestConfirm> as MlmeRequestConfirmSet;
		interface IeeeRequestConfirm<Mlme_StartRequestConfirm> as MlmeRequestConfirmStart;
		interface IeeeIndication<Mlme_SyncLossIndication> as MlmeIndicationSyncLoss;
		interface IeeeRequest<Mlme_SyncRequest> as MlmeRequestSync;
	}
	uses
	{
		interface Debug;
	}
}
implementation
{
	#define DBG_LEVEL 1
	#include "Debug.h"

	command result_t McpsRequestConfirmData.request(Mcps_DataRequestConfirm request)
	{
		return FAIL;
	}

	command result_t McpsRequestConfirmPurge.request(Mcps_PurgeRequestConfirm request)
	{
		return FAIL;
	}
	
	/***************************
	 *   Default MCPS events   *
	 ***************************/

	default event void McpsRequestConfirmData.confirm(Mcps_DataRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled McpsRequestConfirmData.confirm",1);
	}

	default event void McpsRequestConfirmPurge.confirm(Mcps_PurgeRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled McpsRequestConfirmPurge.confirm",1);
	}	
	
	/**********************************************************
	** MLME
	***********************************************************/
	
	inline command result_t MlmeRequestConfirmAssociate.request(Mlme_AssociateRequestConfirm request)
	{
		return FAIL;
	}

	inline command result_t MlmeIndicationResponseAssociate.response( Mlme_AssociateIndicationResponse response )
	{
		return FAIL;
	}
	
	command result_t MlmeRequestConfirmDisassociate.request(Mlme_DisassociateRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeRequestConfirmGet.request(Mlme_GetRequestConfirm request)
	{
		return FAIL;
	}
	
	command result_t MlmeRequestConfirmGts.request(Mlme_GtsRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeIndicationResponseOrphan.response( Mlme_OrphanIndicationResponse response )
	{
		return FAIL;
	}
		
	command result_t MlmeRequestConfirmPoll.request(Mlme_PollRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeRequestConfirmReset.request(Mlme_ResetRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeRequestConfirmRxEnable.request(Mlme_RxEnableRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeRequestConfirmSet.request(Mlme_SetRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeRequestConfirmStart.request(Mlme_StartRequestConfirm request)
	{
		return FAIL;
	}

	command result_t MlmeRequestSync.request(Mlme_SyncRequest request)
	{
		return FAIL;
	}
	
	default event void McpsIndicationData.indication(Mcps_DataIndication indication)
	{
		DBG_STR("WARNING: Unhandled McpsIndicationData.indication",1);
	}

	/***************************
	 *   Default MLME events   *
	 ***************************/

	default event void MlmeRequestConfirmAssociate.confirm(Mlme_AssociateRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmAssociate.confirm",1);
	}
	
	default async event void MlmeIndicationResponseAssociate.indication(Mlme_AssociateIndicationResponse indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationResponseAssociate.indication",1);
	}

	default event void MlmeIndicationBeaconNotify.indication(Mlme_BeaconNotifyIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationBeaconNotify.indication",1);
	}
	
	default event void MlmeIndicationCommStatus.indication(Mlme_CommStatusIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationCommStatus.indication",1);
	}

	default event void MlmeRequestConfirmDisassociate.confirm(Mlme_DisassociateRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmDisassociate.confirm",1);
	}
	
	default event void MlmeIndicationDisassociate.indication(Mlme_DisassociateIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationDisassociate.indication",1);
	}

	default event void MlmeRequestConfirmGts.confirm(Mlme_GtsRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmGts.confirm",1);
	}
	
	default event void MlmeIndicationGts.indication(Mlme_GtsIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationGts.indication",1);
	}
	
	default async event void MlmeIndicationResponseOrphan.indication(Mlme_OrphanIndicationResponse indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationResponseOrphan.indication",1);
	}

	default event void MlmeRequestConfirmPoll.confirm(Mlme_PollRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmPoll.confirm",1);
	}

	default event void MlmeRequestConfirmReset.confirm(Mlme_ResetRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmReset.confirm",1);
	}

	default event void MlmeRequestConfirmRxEnable.confirm(Mlme_RxEnableRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmRxEnable.confirm",1);
	}

	default event void MlmeRequestConfirmSet.confirm(Mlme_SetRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmSet.confirm",1);
	}

	default event void MlmeRequestConfirmStart.confirm(Mlme_StartRequestConfirm confirm)
	{
		DBG_STR("WARNING: Unhandled MlmeRequestConfirmStart.confirm",1);
	}

	default event void MlmeIndicationSyncLoss.indication(Mlme_SyncLossIndication indication)
	{
		DBG_STR("WARNING: Unhandled MlmeIndicationSyncLoss.indication",1);
	}
}

--- NEW FILE: MacAddressM.nc ---
/* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
 * 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 University of Copenhagen 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.
 */

/*
  @author Jan Flora <janflora at diku.dk>
*/

#include "macFrame.h"
#include "Ieee802154Adts.h"

module MacAddressM
{
	provides
	{
		interface MacAddress;
	}
	uses
	{		
		interface Debug;
	}

}
implementation
{
	#define DBG_LEVEL 3
	#include "Debug.h"
	
	command void MacAddress.getSrcAddr(uint8_t *frame, ieeeAddress_t *myAddress)
	{
		myAddress->mode = mhrSrcAddrMode(frame);
		if (myAddress->mode == 0) return;
		if (mhrIntraPAN(frame)) {
			myAddress->panId = *((uint16_t*)mhrDestPANId(frame));
		} else {
			myAddress->panId = *((uint16_t*)mhrSrcPANId(frame));
		}
		memcpy(myAddress->address, mhrSrcAddr(frame), 8);
	}
	
	command void MacAddress.getDstAddr(uint8_t *frame, ieeeAddress_t *myAddress)
	{
		myAddress->mode = mhrDestAddrMode(frame);
		if (myAddress->mode == 0) return;
		
		myAddress->panId = *((uint16_t*)mhrDestPANId(frame));
		memcpy(myAddress->address, mhrDestAddr(frame), 8);
	}
	
	command void MacAddress.setSrcAddr(uint8_t *frame, ieeeAddress_t *myAddress)
	{
		mhrSrcAddrMode(frame) = myAddress->mode;
		if (myAddress->mode == 0) return;
		
		if (!mhrIntraPAN(frame)) {
			*((uint16_t*)mhrSrcPANId(frame)) = myAddress->panId;
		}
		if (myAddress->mode == 3) {
			memcpy(mhrSrcAddr(frame), myAddress->address, 8);
		} else {
			memcpy(mhrSrcAddr(frame), myAddress->address, 2);
		}
	}
	
	command void MacAddress.setDstAddr(uint8_t *frame, ieeeAddress_t *myAddress)
	{
		mhrDestAddrMode(frame) = myAddress->mode;
		if (myAddress->mode == 0) return;

		*((uint16_t*)mhrDestPANId(frame)) = myAddress->panId;
		if (myAddress->mode == 3) {
			memcpy(mhrDestAddr(frame), myAddress->address, 8);
		} else {
			memcpy(mhrDestAddr(frame), myAddress->address, 2);
		}
	}
	
	command void MacAddress.setDstCoordinator(uint8_t *frame)
	{
		*((uint16_t*)mhrDestPANId(frame)) = macPanId;
		if (macCoordShortAddress == 0xFFFF || macCoordShortAddress == 0xFEFF) {
			mhrDestAddrMode(frame) = 3;
			memcpy(mhrDestAddr(frame), macCoordExtendedAddress, 8);
		} else {
			mhrDestAddrMode(frame) = 2;
			memcpy(mhrDestAddr(frame), &(macCoordShortAddress), 2);
		}
	}
	
	command void MacAddress.setSrcLocal(uint8_t *frame, bool preferExt)
	{		
		if (!mhrIntraPAN(frame)) {
			*((uint16_t*)mhrSrcPANId(frame)) = macPanId;
		}
		if (preferExt || macShortAddress == 0xFFFF || macShortAddress == 0xFEFF) {
			// Use extended addressing.
			mhrSrcAddrMode(frame) = 3;
			memcpy(mhrSrcAddr(frame), aExtendedAddress, 8);
		} else {
			// Use short addressing.
			mhrSrcAddrMode(frame) = 2;
			memcpy(mhrSrcAddr(frame), &(macShortAddress), 2);
		}
	}
}


Index: CsmaM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac/CsmaM.nc,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** CsmaM.nc	22 Feb 2006 01:41:55 -0000	1.12
--- CsmaM.nc	23 Aug 2006 09:54:56 -0000	1.13
***************
*** 1,10 ****
! /* 
! Handles slotted and unslotted CSMA-CA.
  
! @author Jan Flora <janflora at diku.dk>
! @author Esben Zeuthen <zept at diku.dk>
  */
  
  #include "MacPib.h"
  
  module CsmaM
--- 1,34 ----
! /* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
!  * 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 University of Copenhagen 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.
!  */
  
! /*
!   @author Jan Flora <janflora at diku.dk>
  */
  
  #include "MacPib.h"
+ #include "PhyTypes.h"
  
  module CsmaM
***************
*** 16,26 ****
  	uses
  	{	
- 		interface Cca;
  		interface FrameTx;
! 		interface AsyncAlarm<time_t> as Alarm;
! 		interface RadioAccess;
  		interface Random;
- 		interface RTScheduler;
- 		interface RxFilter; // TODO: deny receptions during cca+tx??
  		interface Superframe;
  		interface Debug;
--- 40,46 ----
  	uses
  	{	
  		interface FrameTx;
! 		interface LocalTime;
  		interface Random;
  		interface Superframe;
  		interface Debug;
***************
*** 31,53 ****
  	#define DBG_LEVEL 3
  	#include "Debug.h"
! 	
! 	// CW = Contention Window
! 	uint8_t CW;
! 	uint32_t ccaStartTime;
! 	
  	capTx_t *pendingTx;
  
! 	result_t performIteration();
! 	result_t unslottedBackoff();
! 	void unslottedCSMA_CA_CCA();
! 	void unslottedCSMA_CA_CCA_Done(bool channelClear);
! 	result_t slottedBackoff();
! 	void slottedCSMA_CA_CCA();
! 	void slottedCSMA_CA_CCA_Done(bool channelClear);
! 	void csmaDone();
! 	
  	uint8_t getBackoffPeriods();
  	
! 	command result_t Csma.send( capTx_t *capTx )
  	{
  		// Perform CSMA-CA
--- 51,62 ----
  	#define DBG_LEVEL 3
  	#include "Debug.h"
! 
  	capTx_t *pendingTx;
+ 	txdata_t myTxData;
  
! 	void performIteration();
  	uint8_t getBackoffPeriods();
  	
! 	command void Csma.send( capTx_t *capTx )
  	{
  		// Perform CSMA-CA
***************
*** 55,63 ****
  		// TODO: perhaps ensure unique access
  		pendingTx = capTx;
! 		
! 		return performIteration();	
! 	}
! 	
! 	result_t performIteration(){
  		if (pendingTx->status != CSMA_DEFERRED){
  			// this a new csma request, initialize parameters
--- 64,70 ----
  		// TODO: perhaps ensure unique access
  		pendingTx = capTx;
! 		myTxData.frame = pendingTx->header->frame;
! 		myTxData.length = pendingTx->header->length;
! 		myTxData.cca = TRUE;
  		if (pendingTx->status != CSMA_DEFERRED){
  			// this a new csma request, initialize parameters
***************
*** 65,267 ****
  			pendingTx->NB = 0;
  			pendingTx->BE = macMinBE;
- 			pendingTx->backoffPeriods = 0;
- 		} 
- 				
- 		// calculate a backoff if not set already
- 		if (pendingTx->backoffPeriods == 0) {
  			pendingTx->backoffPeriods = getBackoffPeriods();
- 		}
- 		
- 		if ( call Superframe.isBeaconEnabled(pendingTx->header.superframe) ) {
- 			return slottedBackoff();
  		} else {
! 			return unslottedBackoff();
! 		}
! 	}
! 	
! 	/** Calculates a random backoff period in symbol periods **/
! 	uint8_t getBackoffPeriods() {
! 		uint8_t backoff = (1<<pendingTx->BE)-1;
! 		if ( backoff > 0 )
! 		{
! 			backoff = (call Random.rand() % (backoff+1));
! 		}
! 		return backoff;
! 	}
! 	
! 	void csmaDone()
! 	{
! 		// unlock and pass on the event
! 		call RadioAccess.unlock(LOCK_EXCLUSIVE);
! 		
! 		if ( pendingTx->status == CSMA_FAIL ) {
! 			pendingTx->header->status = TX_CHANNEL_ACCESS_FAILURE;
! 		}			
! 		
! 		signal Csma.done();
! 	}
! 	
! 	/* UNSLOTTED CSMA-CA */
! 	result_t unslottedBackoff()
! 	{
! 		// calculate backoff time and set the alarm as a countdown
! 		uint32_t backoffDuration = pendingTx->backoffPeriods;
! 		backoffDuration *= aUnitBackoffPeriod;
! 		backoffDuration *= macInvSymbolRate;
! 		
! 		if ( backoffDuration > 0) {
! 			if (SUCCESS != call Alarm.armCountdown(backoffDuration) ){
! 				// TODO: debug output
! 				pendingTx->status = CSMA_FAIL;
! 				return FAIL;
! 			}
! 		} else {
! 			// commence cca ASAP
! 			if (SUCCESS != call RTScheduler.deferExec(unslottedCSMA_CA_CCA)){
! 				// TODO: debug output
! 				pendingTx->status = CSMA_FAIL;
! 				return FAIL;
! 			};
! 		}
! 		return SUCCESS;
! 	}
! 	
! 	void unslottedCSMA_CA_CCA()
! 	{
! 		if (SUCCESS != call RadioAccess.lock(LOCK_EXCLUSIVE)) {
! 			unslottedCSMA_CA_CCA_Done(FALSE);
! 		}
! 		if ( SUCCESS != call Cca.perform() ) {
! 			DBG_STR("SERIOUS ERROR: CCA operation could not start!",1);
! 			unslottedCSMA_CA_CCA_Done(FALSE);
  		}
  	}
  	
! 	void unslottedCSMA_CA_CCA_Done(bool channelClear)
  	{
! 	
! 		if ( channelClear ) {
! 			// CSMA-CA was successful, try tx
! 			if (call FrameTx.tx(&pendingTx->header, FALSE, csmaDone) != SUCCESS) {
! 				// TODO: make sure FrameTx sets the error status???
! 				csmaDone();
  			}
  		} else {
! 			pendingTx->backoffPeriods = 0;
! 			pendingTx->NB++;
! 			pendingTx->BE = pendingTx->BE+1 > aMaxBE ? aMaxBE : pendingTx->BE+1;
! 			if ( pendingTx->NB <= macMaxCSMABackoffs) {				
! 				// attempt another CSMA iteration
! 				if (performIteration() != SUCCESS) {
! 					csmaDone();
! 				}
  			} else {
! 				// CSMA has failed
! 				pendingTx->status = CSMA_FAIL;	
! 				csmaDone();
! 			}
! 		}		
! 	}
! 	
! 	/*
! 		SLOTTED CSMA-CA
! 	*/
! 	
! 	result_t slottedBackoff()
! 	{
! 		CW = 2; // initialize contention window
! 		// check if we need to defer the backoff to the next cap
! 		// we expect the superframe module to update number of backoffs
! 		// if the frame does not fit
! 		
! 		if (!call Superframe.fitsInCurCap(pendingTx)){
! 			// defer transaction to next CAP
! 			if (SUCCESS != call RTScheduler.deferExec(csmaDone)){
! 				pendingTx->status = CSMA_FAIL;
! 				return FAIL;
  			}
- 			return SUCCESS;
  		}
  		
! 		// pad to next backoff slot boundary inside current CAP
! 		ccaStartTime = call Superframe.alignBackoff(pendingTx->header.superframe,pendingTx->backoffPeriods);
! 				
! 		// TODO: account for idle2cca latency MARGIN
! 		if ( SUCCESS != call Alarm.armAlarmClock(ccaStartTime) ) {
! 			DBG_STR("FATAL ERROR: Unable to set Alarm!",1);
! 			pendingTx->status = CSMA_FAIL;
! 			return FAIL;
  		}
  	}
  	
! 	void slottedCSMA_CA_CCA()
! 	{
! 		// lock
! 		if (SUCCESS != call RadioAccess.lock(LOCK_EXCLUSIVE)) {
! 			slottedCSMA_CA_CCA_Done(FALSE);
! 		}
! 		// immediate cca
! 		if ( SUCCESS != call Cca.perform() ){
! 			slottedCSMA_CA_CCA_Done(FALSE);
  		}
  	}
! 	
! 	void slottedCSMA_CA_CCA_Done(bool channelClear)
  	{
! 		CW = CW - 1	;
! 		if ( channelClear ) // channel clear
! 		{
! 			if ( CW > 0 ) {
! 				// schedule next CCA at next backoff boundary
! 				ccaStartTime += aUnitBackoffPeriod*macInvSymbolRate;
! 				if ( SUCCESS != call Cca.performDeferred(ccaStartTime) ){
! 					DBG_STR("FATAL ERROR: Unable to request second CCA",1);
! 					pendingTx->status = CSMA_FAIL;
! 					csmaDone();
! 					return;
! 				}
! 			} else {
! 				// request transmission
! 				if (call FrameTx.tx(&pendingTx->header, FALSE, csmaDone) != SUCCESS) {
! 					// TODO: make sure FrameTx sets the error status!!!
! 					csmaDone();
! 					return;
! 				}
! 			}
  		} else {
  			pendingTx->backoffPeriods = 0;
  			pendingTx->NB++;
! 			pendingTx->BE = pendingTx->BE+1 > aMaxBE ? aMaxBE : pendingTx->BE+1;
  			if ( pendingTx->NB <= macMaxCSMABackoffs) {				
  				// attempt another CSMA iteration
! 				if (performIteration() != SUCCESS) {
! 					csmaDone();
! 				}
  			} else {
  				// CSMA has failed
! 				pendingTx->status = CSMA_FAIL;	
! 				csmaDone();
  			}
  		}
  	}
! 	
! 	async event result_t Alarm.alarm() {
! 		if ( call Superframe.isBeaconEnabled(pendingTx->header.superframe) ) {
! 			slottedCSMA_CA_CCA();
! 		} else {
! 			unslottedCSMA_CA_CCA();
! 		}
! 		return SUCCESS;
! 	}
! 	
! 	async event void Cca.done(bool channelClear)
! 	{
! 		if ( call Superframe.isBeaconEnabled(pendingTx->header.superframe) ) {
! 			slottedCSMA_CA_CCA_Done(channelClear);
! 		} else {
! 			unslottedCSMA_CA_CCA_Done(channelClear);
! 		}
! 	}
! 	
  	default async event void Csma.done()
  	{
--- 72,164 ----
  			pendingTx->NB = 0;
  			pendingTx->BE = macMinBE;
  			pendingTx->backoffPeriods = getBackoffPeriods();
  		} else {
! 			DBG_STR("Deferred entry",3);
  		}
+ 		// TODO: We need to be able to handle backoff periods < 3 slots.
+ 		pendingTx->backoffPeriods = (pendingTx->backoffPeriods < 3)?3 : pendingTx->backoffPeriods;
+ 		//DBG_STRINT("Backoff is:",pendingTx->backoffPeriods,1);
+ 		performIteration();	
  	}
  	
! 	void performIteration()
  	{
! 		time_t myNow;
! 		if (macBeaconEnabled) {
! 			// check if we need to defer the backoff to the next cap
! 			// we expect the superframe module to update number of backoffs
! 			// if the frame does not fit
! 			if (!call Superframe.fitsInCurCap(pendingTx)) {
! 				DBG_STR("Transmission does not fit in current CAP!",1);
! 				// defer transaction to next CAP
! 				signal Csma.done();
! 				return;
  			}
+ 			
+ 			// pad to next backoff slot boundary inside current CAP
+ 			myTxData.immediateCommence = FALSE;
+ 			myTxData.commenceTime = pendingTx->commenceTime;
  		} else {
! 			// Unslottet CSMA.
! 			// calculate backoff time
! 			uint32_t backoffDuration = pendingTx->backoffPeriods * aUnitBackoffPeriod;
! 			if (backoffDuration > 0) {
! 				// Calculate commence time.
! 				myTxData.immediateCommence = FALSE;
! 				myTxData.commenceTime = call LocalTime.getTime()+backoffDuration;
  			} else {
! 				// commence ASAP
! 				myTxData.immediateCommence = TRUE;
  			}
  		}
  		
! 		// Add dsn if needed.
! 		if (pendingTx->header->addDsn) {
! 			mhrSeqNumber(myTxData.frame) = macDsn++;
! 		}
! 
! 		if (PHY_SUCCESS != call FrameTx.tx(&myTxData)) {
! 			// TODO: debug output
! 			pendingTx->header->status = TX_CHANNEL_ACCESS_FAILURE;
! 			signal Csma.done();
  		}
+ 		//myNow = call LocalTime.getTime();
+ 		//DBG_STRINT("CommenceTime:",myTxData.commenceTime,1);
+ 		//DBG_STRINT("Time now is:",myNow,1);
  	}
  	
! 	/** Calculates a random backoff period in symbol periods **/
! 	uint8_t getBackoffPeriods() {
! 		uint8_t backoff = (1<<pendingTx->BE)-1;
! 		if ( backoff > 0 ) {
! 			backoff = (call Random.rand() % (backoff+1));
  		}
+ 		return backoff;
  	}
! 
! 	async event void FrameTx.txDone(phy_error_t error)
  	{
! 		if (error == PHY_SUCCESS) {
! 			pendingTx->header->status = TX_SUCCESS;
! 		} else if (error == PHY_ACK_FAIL) {
! 			pendingTx->header->status = TX_NO_ACK;
! 			pendingTx->header->txRetries--;
  		} else {
+ 			// CCA must have failed.
  			pendingTx->backoffPeriods = 0;
  			pendingTx->NB++;
! 			pendingTx->BE = (pendingTx->BE+1 > aMaxBE) ? aMaxBE : pendingTx->BE+1;
  			if ( pendingTx->NB <= macMaxCSMABackoffs) {				
  				// attempt another CSMA iteration
! 				performIteration();
! 				return;
  			} else {
  				// CSMA has failed
! 				pendingTx->header->status = TX_CHANNEL_ACCESS_FAILURE;
  			}
  		}
+ 		signal Csma.done();
  	}
! 
  	default async event void Csma.done()
  	{

Index: MacPib.h
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac/MacPib.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** MacPib.h	27 Feb 2006 22:13:01 -0000	1.6
--- MacPib.h	23 Aug 2006 09:54:56 -0000	1.7
***************
*** 1,8 ****
! #include <Ieee802154Adts.h>
! #include <const.h>
  
  #ifndef _MACPIB_H_
  #define _MACPIB_H_
  	// Everything radio frame related in here is in little endian format.
  	uint8_t macAckWaitDuration;
  	bool macAssociationPermit;
--- 1,46 ----
! /* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
!  * 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 University of Copenhagen 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.
!  */
! 
! /*
!   @author Jan Flora <janflora at diku.dk>
! */
  
  #ifndef _MACPIB_H_
  #define _MACPIB_H_
+ 	#include <Ieee802154Adts.h>
+ 	#include <MacConst.h>
+ 
  	// Everything radio frame related in here is in little endian format.
+ 	// This is done to avoid converting endianness more than necessary.
+ 	// LITTLE ENDIAN
+ 	uint8_t macCoordExtendedAddress[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ 	uint16_t macCoordShortAddress;
+ 	uint16_t macPanId;
+ 	uint16_t macShortAddress;
+ 	
+ 	// ARCHITECTURE ENDIANNESS
  	uint8_t macAckWaitDuration;
  	bool macAssociationPermit;
***************
*** 15,31 ****
  	uint32_t macBeaconTxTime;
  	uint8_t macBsn;
- 	uint8_t macCoordExtendedAddress[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- 	uint16_t macCoordShortAddress;
  	uint8_t macDsn;
  	bool macGtsPermit;
  	uint8_t macMaxCSMABackoffs;
  	uint8_t macMinBE;
- 	uint16_t macPanId;
  	bool macPromiscuousMode;
  	bool macRxOnWhenIdle;
- 	uint16_t macShortAddress;
  	uint8_t macSuperframeOrder;
  	uint16_t macTransactionPersistenceTime;
  	
  	// Security attributes.
  	ieeeAclEntry macAclEntryDescriptorSet[aAclEntryDescriptorSetMaxSize];
--- 53,70 ----
  	uint32_t macBeaconTxTime;
  	uint8_t macBsn;
  	uint8_t macDsn;
  	bool macGtsPermit;
  	uint8_t macMaxCSMABackoffs;
  	uint8_t macMinBE;
  	bool macPromiscuousMode;
  	bool macRxOnWhenIdle;
  	uint8_t macSuperframeOrder;
  	uint16_t macTransactionPersistenceTime;
  	
+ 	// Implementation specific attributes
+ 	bool macPanCoordinator;
+ 	bool macCoordinator;
+ 	bool macBeaconEnabled;
+ 	
  	// Security attributes.
  	ieeeAclEntry macAclEntryDescriptorSet[aAclEntryDescriptorSetMaxSize];

Index: MacPibDatabaseM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac/MacPibDatabaseM.nc,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** MacPibDatabaseM.nc	17 Feb 2006 11:14:20 -0000	1.9
--- MacPibDatabaseM.nc	23 Aug 2006 09:54:56 -0000	1.10
***************
*** 1,2 ****
--- 1,31 ----
+ /* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
+  * 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 University of Copenhagen 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.
+  */
+ 
+ /*
+   @author Jan Flora <janflora at diku.dk>
+ */
  
  module MacPibDatabaseM
***************
*** 9,19 ****
  	uses
  	{
  		interface Random;
  	}
  }
  implementation
  {
! 
! 	command result_t StdControl.init()
  	{
  		call Random.init();
--- 38,52 ----
  	uses
  	{
+ 		interface CapRx as PibChange;
  		interface Random;
+ 		interface Debug;
  	}
  }
  implementation
  {
! 	#define DBG_LEVEL 1
! 	#include "Debug.h"
! 	
! 	void reset()
  	{
  		call Random.init();
***************
*** 40,43 ****
--- 73,81 ----
  		macTransactionPersistenceTime = 0x01f4;
  	
+ 		// Implementation specific attributes
+ 		macPanCoordinator = FALSE;
+ 		macCoordinator = FALSE;
+ 		macBeaconEnabled = FALSE;
+ 	
  		// Security attributes.
  		macAclEntryDescriptorSetSize = 0;
***************
*** 46,49 ****
--- 84,92 ----
  		macDefaultSecuritySuite = 0;
  		macSecurityMode = 0;
+ 	}
+ 	
+ 	command result_t StdControl.init()
+ 	{
+ 		reset();
  		return SUCCESS;
  	}
***************
*** 57,60 ****
--- 100,108 ----
  	}
  
+ 	command void PibDatabase.reset()
+ 	{
+ 		reset();
+ 	}
+ 
  	command bool PibDatabase.isPanCoordinator(Ieee_Address coordAddr)
  	{
***************
*** 125,133 ****
  		}
  		if (identifier == IEEE802154_macCoordExtendedAddress) {
! 			memcpy(target, macCoordExtendedAddress, 8);
  			return IEEE802154_SUCCESS;
  		}
  		if (identifier == IEEE802154_macCoordShortAddress) {
! 			*((uint16_t*)target) = macCoordShortAddress;
  			return IEEE802154_SUCCESS;
  		}
--- 173,183 ----
  		}
  		if (identifier == IEEE802154_macCoordExtendedAddress) {
! 			// This attribute is stored in little endian!
! 			NTOUH64(macCoordExtendedAddress, target);
  			return IEEE802154_SUCCESS;
  		}
  		if (identifier == IEEE802154_macCoordShortAddress) {
! 			// This attribute is stored in little endian!
! 			NTOUH16((uint8_t*)&macCoordShortAddress, target);
  			return IEEE802154_SUCCESS;
  		}
***************
*** 149,153 ****
  		}
  		if (identifier == IEEE802154_macPANId) {
! 			*((uint16_t*)target) = macPanId;
  			return IEEE802154_SUCCESS;
  		}
--- 199,204 ----
  		}
  		if (identifier == IEEE802154_macPANId) {
! 			// This attribute is stored in little endian!
! 			NTOUH16((uint8_t*)&macPanId, target);
  			return IEEE802154_SUCCESS;
  		}
***************
*** 161,165 ****
  		}
  		if (identifier == IEEE802154_macShortAddress) {
! 			*((uint16_t*)target) = macShortAddress;
  			return IEEE802154_SUCCESS;
  		}
--- 212,217 ----
  		}
  		if (identifier == IEEE802154_macShortAddress) {
! 			// This attribute is stored in little endian!
! 			NTOUH16((uint8_t*)&macShortAddress, target);
  			return IEEE802154_SUCCESS;
  		}
***************
*** 269,277 ****
  		}
  		if (identifier == IEEE802154_macCoordExtendedAddress) {
! 			memcpy(macCoordExtendedAddress, source, 8);
  			return IEEE802154_SUCCESS;
  		}
  		if (identifier == IEEE802154_macCoordShortAddress) {
! 			macCoordShortAddress = *((uint16_t*)source);
  			return IEEE802154_SUCCESS;
  		}
--- 321,329 ----
  		}
  		if (identifier == IEEE802154_macCoordExtendedAddress) {
! 			NTOUH64(source, macCoordExtendedAddress);
  			return IEEE802154_SUCCESS;
  		}
  		if (identifier == IEEE802154_macCoordShortAddress) {
! 			NTOUH16(source, (uint8_t*)&macCoordShortAddress);
  			return IEEE802154_SUCCESS;
  		}
***************
*** 301,305 ****
  		}
  		if (identifier == IEEE802154_macPANId) {
! 			macPanId = *((uint16_t*)source);
  			return IEEE802154_SUCCESS;
  		}
--- 353,357 ----
  		}
  		if (identifier == IEEE802154_macPANId) {
! 			NTOUH16(source, (uint8_t*)&macPanId);
  			return IEEE802154_SUCCESS;
  		}
***************
*** 310,317 ****
  		if (identifier == IEEE802154_macRxOnWhenIdle) {
  			macRxOnWhenIdle = *((bool*)source);
  			return IEEE802154_SUCCESS;
  		}
  		if (identifier == IEEE802154_macShortAddress) {
! 			macShortAddress = *((uint16_t*)source);
  			return IEEE802154_SUCCESS;
  		}
--- 362,374 ----
  		if (identifier == IEEE802154_macRxOnWhenIdle) {
  			macRxOnWhenIdle = *((bool*)source);
+ 			if (macRxOnWhenIdle) {
+ 				call PibChange.rxOn();
+ 			} else {
+ 				call PibChange.rxOff();
+ 			}
  			return IEEE802154_SUCCESS;
  		}
  		if (identifier == IEEE802154_macShortAddress) {
! 			NTOUH16(source, (uint8_t*)&macShortAddress);
  			return IEEE802154_SUCCESS;
  		}

Index: CapControlM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac/CapControlM.nc,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** CapControlM.nc	23 Feb 2006 17:15:24 -0000	1.6
--- CapControlM.nc	23 Aug 2006 09:54:56 -0000	1.7
***************
*** 1,5 ****
  /*
! @author Jan Flora <janflora at diku.dk>
! @author Esben Zeuthen <zept at diku.dk>
  */
  
--- 1,30 ----
+ /* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
+  * 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 University of Copenhagen 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.
+  */
+ 
  /*
!   @author Jan Flora <janflora at diku.dk>
  */
  
***************
*** 11,16 ****
  	{
  		// TODO:
! 		interface CapTx[uint8_t] as CoordinatorTx[uint8_t];
! 		interface CapTx[uint8_t] as DeviceTx[uint8_t];
  	}
  	uses
--- 36,46 ----
  	{
  		// TODO:
! 		interface CapTx as CoordinatorTx[uint8_t token];
! 		interface CapTx as DeviceTx[uint8_t token];
! 		interface CapRx as DeviceRx;
! 		interface CapRx as CoordinatorRx;
! 		interface CapRx as PibChange;
! 		interface Reset;
! 		interface StdControl;
  	}
  	uses
***************
*** 18,24 ****
  		interface CapEvents as CoordinatorCap;
  		interface CapEvents as DeviceCap;
! 		interface RadioIdleControl;
  		interface Superframe;
  		interface Csma;
  		interface Debug;
  	}
--- 48,55 ----
  		interface CapEvents as CoordinatorCap;
  		interface CapEvents as DeviceCap;
! 		interface FrameRx;
  		interface Superframe;
  		interface Csma;
+ 		interface LocalTime;
  		interface Debug;
  	}
***************
*** 30,112 ****
  	#include "Debug.h"
  
! 	// Global variables.
! 	enum {
! 		COORDSLOT,
! 		COORDINDIRECTSLOT,
! 		DEVICESLOT,
! 		NONE
! 	};
  	
! 	capTx_t slots[3]; // TODO: initialize slots
  	uint8_t nextSlot;
! 	uint8_t txPending = NONE;
  	
  	task void sendDone();	
! 	void tendOperationQueue(uint8_t startSlot);
  
  	event void CoordinatorCap.startNotification()
  	{
! 		
! 		// Unlock coordinator TX slot and indirect TX slot for service.
! 		tendOperationQueue(nextSlot%2); // activate COORDSLOT or COORDINDIRECTSLOT first
  	}
! 		
  	event void DeviceCap.startNotification()
  	{
! 		// Unlock device TX slot for service.
! 		tendOperationQueue(DEVICESLOT);
  	}
  	
  	async event void Csma.done()
  	{
! 		// Find out what to do with the frame based on status and retry info
! 		if (    slots[txPending].header->txRetries == 0
! 		     || slots[txPending].header->status == TX_SUCCESS
! 		     || slots[txPending].header->status == TX_CHANNEL_ACCESS_FAILURE ) {
! 			slots[txPending].status = SEND_DONE;
! 			post sendDone();
  		}
  		
! 		atomic txPending = NONE;		
! 		tendOperationQueue(nextSlot%3); // activate any slot first
  	}
  	
! 	command result_t CoordinatorTx.sendFrame[uint8_t token]( txHeader_t *header, bool indirect )
  	{
! 		uint8_t slot = indirect ? COORDINDIRECTSLOT : COORDSLOT;
! 		if (slots[slot].status != SLOT_EMPTY) {
! 			return FAIL;
  		}
  		
! 		// prepare the header		
! 		slots[slot].status = SLOT_PENDING;
! 		slots[slot].header = header;
! 		slots[slot].doneToken = token;
! 		// TODO: retryTx should be set by upper layers
! 		// TODO: perhaps apply the superframe here?
! 		// TODO: check if the frame fits in the CAP
! 		// NOTE: header->status should be TX_PENDING at this point
  		
! 		tendOperationQueue(slot);
! 		return SUCCESS;
  	}
  	
! 	command result_t DeviceTx.sendFrame[uint8_t token]( txHeader_t *header, bool indirect )
  	{
! 		if (slots[DEVICESLOT].status != SLOT_EMPTY) {
! 			return FAIL;
! 		}
! 		
! 		// prepare the header		
! 		slots[slot].status = SLOT_PENDING;
! 		slots[slot].header = header;
! 		slots[slot].doneToken = token;
! 		// TODO: retryTx should be set by upper layers
! 		// TODO: perhaps apply the superframe here?
! 		// TODO: check if the frame fits in the CAP
! 		// NOTE: header->status should be TX_PENDING at this point
! 		
! 		tendOperationQueue(DEVICESLOT);
! 		return SUCCESS;
  	}
  	
--- 61,265 ----
  	#include "Debug.h"
  
! 	// Global variables.	
! 	#define COORDCAP    1
! 	#define DEVICECAP   2
! 
! 	// Rx control.
! 	uint8_t coordCapRxOnCount = 0;
! 	uint8_t deviceCapRxOnCount = 0;
  	
! 	// Tx control.
! 	capTx_t coordSlots[NUMCOORDCAPSLOTS];
! 	capTx_t deviceSlots[NUMDEVICECAPSLOTS];
! 	txDoneEntry_t doneQueue[NUMCAPDONESLOTS];
! 	uint8_t doneQueueCount = 0;
! 	bool donePosted = FALSE;
! 
  	uint8_t nextSlot;
! 	bool isPending = FALSE;
! 	uint8_t txPending;
! 	uint8_t pendingCap;
  	
  	task void sendDone();	
! 	void enqueueTx(txHeader_t *header, uint8_t cap, uint8_t token);
! 	void tendOperationQueue(uint8_t slot, uint8_t cap);
! 	bool prepareTxHeader(txHeader_t *header);
! 	void moveToDoneQueue(txHeader_t *header, uint8_t token);
! 	void tryRxOff();
! 	void tryRxOn();
! 	
! 	command result_t StdControl.init()
! 	{
! 		uint8_t i;
! 		for (i=0;i<NUMDEVICECAPSLOTS;i++) {
! 			deviceSlots[i].status = SLOT_EMPTY;
! 		}
! 		for (i=0;i<NUMCOORDCAPSLOTS;i++) {
! 			coordSlots[i].status = SLOT_EMPTY;
! 		}
! 		return SUCCESS;
! 	}
! 	
! 	command result_t StdControl.start()
! 	{
! 		return SUCCESS;
! 	}
! 	
! 	command result_t StdControl.stop()
! 	{
! 		return SUCCESS;
! 	}
! 	
! 	command void Reset.reset()
! 	{
! 		coordCapRxOnCount = 0;
! 		deviceCapRxOnCount = 0;
! 	}
! 	
! 	command void CoordinatorRx.rxOn()
! 	{
! 		coordCapRxOnCount++;
! 		tryRxOn();
! 	}
! 
! 	command void CoordinatorRx.rxOff()
! 	{
! 		if (coordCapRxOnCount > 0) {
! 			coordCapRxOnCount--;
! 			tryRxOff();
! 		}
! 	}
! 
! 	command void DeviceRx.rxOn()
! 	{
! 		deviceCapRxOnCount++;
! 		tryRxOn();
! 	}
! 	
! 	command void DeviceRx.rxOff()
! 	{
! 		if (deviceCapRxOnCount > 0) {
! 			deviceCapRxOnCount--;
! 			tryRxOff();
! 		}
! 	}
! 	
! 	command void PibChange.rxOn()
! 	{
! 		tryRxOn();
! 	}
! 	
! 	command void PibChange.rxOff()
! 	{
! 		tryRxOff();
! 	}
  
  	event void CoordinatorCap.startNotification()
  	{
! //		time_t temp = call LocalTime.getTime();
! //		DBG_STRINT("CAP started at:",temp,1);
! 		tendOperationQueue(0, COORDCAP);
  	}
! 	
  	event void DeviceCap.startNotification()
  	{
! 		//time_t temp = call LocalTime.getTime();
! 		//DBG_STRINT("CAP started at:",temp,1);
! 
! 		tendOperationQueue(0, DEVICECAP);
  	}
  	
  	async event void Csma.done()
  	{
! 		capTx_t *pendingEntry;
! 		
! 		if (pendingCap == DEVICECAP) {
! 			pendingEntry = &deviceSlots[txPending];
! 		} else {
! 			pendingEntry = &coordSlots[txPending];
  		}
  		
! 		if (pendingEntry->header->status == TX_NO_ACK &&
! 		    pendingEntry->header->txRetries) {
! 			DBG_STR("No ack was received!",1);
! 			// No ack was received. We just retry the frame.
! 			pendingEntry->status = SLOT_PENDING;
! 		}
! 		// Find out what to do with the frame based on status and retry info
! 		if (!(pendingEntry->header->txRetries) ||
! 		    pendingEntry->header->status == TX_SUCCESS ||
! 		    pendingEntry->header->status == TX_CHANNEL_ACCESS_FAILURE ) {
! 			
! 			// Move to done queue.
! 			moveToDoneQueue(pendingEntry->header, pendingEntry->doneToken);
! 			pendingEntry->status = SLOT_EMPTY;
! 			//DBG_STRINT("Transmission was done, slot:",txPending,1);
! 		}
! 		atomic isPending = FALSE;
! 
! 		if (call Superframe.capActive(pendingEntry->header->superframe)) {
! 			// Serve next slot.
! 			tendOperationQueue(nextSlot, pendingCap);
! 		}
  	}
  	
! 	void enqueueTx(txHeader_t *header, uint8_t cap, uint8_t token)
  	{
! 		uint8_t mySlot, i;
! 		bool emptySlotFound = FALSE;
! 		uint8_t maxSlots;
! 		capTx_t *queue;
! 		
! 		if (cap == DEVICECAP) {
! 			maxSlots = NUMDEVICECAPSLOTS;
! 			queue = deviceSlots;
! 		} else {
! 			maxSlots = NUMCOORDCAPSLOTS;
! 			queue = coordSlots;
  		}
  		
! 		// Find available transmission slot
! 		for (i=0;i<maxSlots;i++) {
! 			if (queue[i].status == SLOT_EMPTY) {
! 				// We have an empty slot!
! 				mySlot = i;
! 				emptySlotFound = TRUE;
! 				break;
! 			}
! 		}
! 		if (!emptySlotFound) {
! 			header->status = TX_CHANNEL_ACCESS_FAILURE;
! 			// Move to done queue.
! 			moveToDoneQueue(header, token);
! 			return;
! 		}
  		
! 		// prepare the header	
! 		if (!prepareTxHeader(header)) {
! 			// The transmission does not fit in CAP!
! 			header->status = TX_FRAME_TOO_LONG;
! 			// Move to done queue.
! 			moveToDoneQueue(header, token);
! 			return;
! 		}
! 		queue[mySlot].status = SLOT_PENDING;
! 		queue[mySlot].header = header;
! 		queue[mySlot].doneToken = token;
! 		
! 		if (!isPending && call Superframe.capActive(header->superframe)) {
! 			tendOperationQueue(mySlot, cap);
! 		}
  	}
  	
! 	command void CoordinatorTx.sendFrame[uint8_t token]( txHeader_t *header )
  	{
! 		header->superframe = &coordinatorSuperframe;
! 		enqueueTx(header, COORDCAP, token);
! 	}
! 	
! 	command void DeviceTx.sendFrame[uint8_t token]( txHeader_t *header )
! 	{
! 		header->superframe = &deviceSuperframe;
! 		enqueueTx(header, DEVICECAP, token);
  	}
  	
***************
*** 114,170 ****
  	{
  		uint8_t i;
! 		// go through the slots and clean up the ones that have SEND_DONE status
! 		for (i = COORDSLOT; i < NONE; i++) {
! 			if ( slots[i].status = SEND_DONE ) {
! 				if ( i == DEVICESLOT ) {
! 					signal DeviceTx.done[slots[i].doneToken]();
! 				} else {
! 					// Must be coordinator tx.
! 					signal CoordinatorTx.done[slots[i].doneToken]();
! 				}
! 				slots[i].status = SLOT_EMPTY;
  			}
  		}
  	}
  	
! 	void tendOperationQueue(uint8_t slot)
  	{
  		uint8_t i,s;
! 		bool wasPending = TRUE;
  		
! 		atomic {
! 			if (txPending == NONE) {
! 				txPending = slot;
! 				wasPending = FALSE;
! 			}					
  		}
  		
! 		if (wasPending) {
  			return;
  		}
  		
! 		for ( i = 0; i <= 3; i++ ) {
! 			s = (slot+i)%3;
! 			if (slots[s].status == SLOT_PENDING || slots[s].status == CSMA_DEFERRED) {
! 				if (call Csma.send(&slots[s]) != SUCCESS) {
! 					atomic txPending = NONE;
! 				} // TODO: error handling
! 				nextSlot = s+1;
! 				break;
  			}
! 		}		
  	}
! 	
! 	default event result_t CoordinatorTx.done[uint8_t token]()
  	{
  		DBG_STRINT("WARNING: CapControl, event CoordinatorTx.done not connected for token ",token,1);
- 		return SUCCESS;
  	}
  	
! 	default event result_t DeviceTx.done[uint8_t token]()
  	{
  		DBG_STRINT("WARNING: CapControl, event DeviceTx.done not connected for token ",token,1);
! 		return SUCCESS;
! 	}
! 	
  }
--- 267,402 ----
  	{
  		uint8_t i;
! 		txHeader_t *header;
! 		uint8_t token;
! 		
! 		// We empty the done queue.
! 		while (doneQueueCount) {
! 			atomic {
! 				doneQueueCount--;
! 				header = doneQueue[doneQueueCount].header;
! 				token = doneQueue[doneQueueCount].doneToken;
! 			}
! 			if (header->superframe == &deviceSuperframe) {
! 				signal DeviceTx.done[token](header);
! 			} else {
! 				signal CoordinatorTx.done[token](header);
  			}
  		}
+ 		atomic donePosted = FALSE;
  	}
  	
! 	void tendOperationQueue(uint8_t slot, uint8_t cap)
  	{
  		uint8_t i,s;
! 		uint8_t maxSlots;
! 		capTx_t *queue;
  		
! 		if (cap == DEVICECAP) {
! 			maxSlots = NUMDEVICECAPSLOTS;
! 			queue = deviceSlots;
! 		} else {
! 			maxSlots = NUMCOORDCAPSLOTS;
! 			queue = coordSlots;
  		}
  		
! 		for (i=0;i<maxSlots;i++) {
! 			s = (slot+i)%maxSlots;
! 			if (queue[s].status == SLOT_PENDING || queue[s].status == CSMA_DEFERRED) {
! 				atomic {
! 					isPending = TRUE;
! 					txPending = s;
! 					pendingCap = cap;
! 				}
! 				DBG_STRINT("Sending data in slot:",s,1);
! 				call Csma.send(&queue[s]);
! 				nextSlot = (s+1)%maxSlots;
! 				return;
! 			}
! 		}
! 		
! 		// Nothing to be sent. We are idle!
! 		// Now try to enable the receiver.
! 		tryRxOn();
! 	}
! 
! 	void tryRxOff()
! 	{
! 		// First we check if the receiver is really on.
! 		if (!phyIsReceiving) {
! 			// Can't turn it off if it ain't on ;-)
! 			return;
! 		}
! 		// Check each of the CAPs
! 		// NOTE: We do not allow both CAPs to be active at the same time!
! 		if (deviceCapActive && (deviceCapRxOnCount || macRxOnWhenIdle)) {
! 			// Receiver should in fact be on.
! 			return;
! 		}
! 		if (coordCapActive && (coordCapRxOnCount || macRxOnWhenIdle)) {
! 			// Receiver should in fact be on.
  			return;
  		}
  		
! 		// Else we can safely turn off the receiver.
! 		call FrameRx.trxOff(FALSE);
! 		DBG_STR("Receiver disabled",1);
! 	}
! 
! 	void tryRxOn()
! 	{
! 		// First we check that we are not already receiving
! 		if (phyIsReceiving || phyIsTransmitting) return;
! 		
! 		// Check each of the CAPs
! 		// NOTE: We do not allow both CAPs to be active at the same time!
! 		// NOTE: If we operate as a coordinator in a cluster-tree network,
! 		//       macRxOnWhenIdle only applies to the coordinator superframe.
! 		if (deviceCapActive && (deviceCapRxOnCount || (macRxOnWhenIdle && !macCoordinator))) {
! 			// Turn on receiver.
! 			if (PHY_SUCCESS != call FrameRx.rxOnNow()) {
! 				DBG_STR("Warning: CapControl, could not enable receiver!",1);
  			}
! 			return;
! 		}
! 		if (coordCapActive && (coordCapRxOnCount || macRxOnWhenIdle)) {
! 			// Turn on receiver.
! 			if (PHY_SUCCESS != call FrameRx.rxOnNow()) {
! 				DBG_STR("Warning: CapControl, could not enable receiver!",1);
! 			}
! 			return;
! 		}
  	}
! 
! 	bool prepareTxHeader(txHeader_t *header)
! 	{
! 		header->txRetries = aMaxFrameRetries;
! 		header->status = TX_PENDING;
! 		return call Superframe.fitsInCap(header);
! 	}
! 
! 	void moveToDoneQueue(txHeader_t *header, uint8_t token)
! 	{
! 		bool wasPosted;
! 		
! 		atomic {
! 			doneQueue[doneQueueCount].header = header;
! 			doneQueue[doneQueueCount].doneToken = token;
! 			doneQueueCount++;
! 			wasPosted = donePosted;
! 			donePosted = TRUE;
! 		}
! 		if (!wasPosted) {
! 			post sendDone();
! 		}
! 	}
! 
! 	default event void CoordinatorTx.done[uint8_t token](txHeader_t *header)
  	{
  		DBG_STRINT("WARNING: CapControl, event CoordinatorTx.done not connected for token ",token,1);
  	}
  	
! 	default event void DeviceTx.done[uint8_t token](txHeader_t *header)
  	{
  		DBG_STRINT("WARNING: CapControl, event DeviceTx.done not connected for token ",token,1);
! 	}	
  }

Index: FrameTxM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac/FrameTxM.nc,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** FrameTxM.nc	1 Mar 2006 12:59:10 -0000	1.5
--- FrameTxM.nc	23 Aug 2006 09:54:56 -0000	1.6
***************
*** 1,2 ****
--- 1,32 ----
+ /* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
+  * 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 University of Copenhagen 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.
+  */
+ 
+ /*
+   @author Jan Flora <janflora at diku.dk>
+ */
+ 
  #include "MacPib.h"
  
***************
*** 5,17 ****
  	provides
  	{
! 		interface FrameTx;
  	}
  	uses
  	{	
! 		interface RawTx;	
! 		interface AckRx;
! 		interface RadioAccess;
  		interface Debug;
- 		interface LocalTime;
  	}
  }
--- 35,45 ----
  	provides
  	{
! 		interface FrameTx[uint8_t service];
! 		interface Reset;
  	}
  	uses
  	{	
! 		interface PhyTransmit;
  		interface Debug;
  	}
  }
***************
*** 21,119 ****
  	#include "Debug.h"
  	
! 	bool locked = FALSE;
! 	bool waitForAck = FALSE;
! 	void (*callbackFunc)() = NULL;
! 	txHeader_t *txFrame;
! 	uint32_t waitDuration;
! 	
! 	uint32_t time1;
! 	uint32_t time2;
! 
! 	// Forward declarations
! 	inline void prepareTx(txHeader_t *frame, bool lock, void (*txDoneFunc)());
! 	void txDone(PhyStatus_t result);
  
! 	command result_t FrameTx.tx( txHeader_t *frame, bool lock, void (*txDoneFunc)() )
  	{
! 		prepareTx(frame, lock, txDoneFunc);
! 		
! 		// Now transmit the frame.
! 		return call RawTx.tx( frame->frame, frame->frameLength, txDone);
  	}
  	
! 	command result_t FrameTx.txDeferred( time_t timestamp, txHeader_t *frame, bool lock, void (*txDoneFunc)() )
! 	{
! 		prepareTx(frame, lock, txDoneFunc);
! 		
! 		// Now transmit the frame.
! 		return call RawTx.txDeferred( timestamp, frame->frame, frame->frameLength, txDone);
! 	}
! 
! 	async event void AckRx.done(bool ackResult, bool framePending)
  	{
! 		time2 = call LocalTime.getTimeL();
! 		DBG_INT(time1,1);
! 		DBG_INT(time2,1);
! 		if (!ackResult) {
! 			txFrame->txRetries--;
! 			txFrame->status = TX_NO_ACK;
! 		} else {
! 			txFrame->status = TX_SUCCESS;
! 		}
! 		txFrame->framePending = framePending;
! 		if (locked) {
! 			call RadioAccess.unlock(LOCK_EXCLUSIVE);
  		}
! 		callbackFunc();
  	}
  	
! 	inline void prepareTx(txHeader_t *frame, bool lock, void (*txDoneFunc)())
! 	{
! 		if (lock) {
! 			// We lock the radio layer.
! 			locked = TRUE;
! 			call RadioAccess.lock(LOCK_EXCLUSIVE);
! 		}
! 		// Store callback and frame.
! 		callbackFunc = txDoneFunc;
! 		txFrame = frame;
! 
! 		// Find out, if we need to set the DSN.
! 		if (frame->addDsn) {
! 			mhrSeqNumber(frame->frame) = macDsn++;
! 		} 
! 
! 		// Find out if we listen for an ack prior to transmitting.
! 		if (mhrAckRequest(frame->frame)) {
! 			waitForAck = TRUE;
! 			waitDuration = macInvSymbolRate;
! 			waitDuration *= macAckWaitDuration;
! 			call AckRx.prepare(mhrSeqNumber(frame->frame));
! 			waitDuration *= 1000;
! 			//DBG_INT(waitDuration,1);
! 		} else {
! 			waitForAck = FALSE;
! 		}
! 	}
! 
! 	void txDone(PhyStatus_t result)
  	{
! 		if (result == PHY_SUCCESS) {
! 			if (waitForAck) {
! 				time1 = call LocalTime.getTimeL();
! 				// Wait for an ack.
! 				call AckRx.wait(waitDuration);
! 				return;
! 			} else {
! 				txFrame->status = TX_SUCCESS;
! 			}
! 		} else {
! 			txFrame->status = TX_CHANNEL_ACCESS_FAILURE;
! 		}
! 		if (locked) {
! 			call RadioAccess.unlock(LOCK_EXCLUSIVE);
! 		}
! 		callbackFunc();
  	}
  
  }
--- 49,83 ----
  	#include "Debug.h"
  	
! 	uint8_t txQueue[2];
! 	uint8_t nextDone = 0;
! 	uint8_t nextFree = 0;
  
! 	command void Reset.reset()
  	{
! 		nextDone = 0;
! 		nextFree = 0;
  	}
  	
! 	command phy_error_t FrameTx.tx[uint8_t service](txdata_t *data)
  	{
! 		phy_error_t myError;
! 		phyIsReceiving = FALSE;
! 		phyIsTransmitting = TRUE;
! 		myError = call PhyTransmit.tx(data);
! 		if (myError == PHY_SUCCESS) {
! 			// Wait for txDone.
! 			txQueue[nextFree] = service;
! 			nextFree = (nextFree+1)%2;
  		}
! 		return myError;
  	}
  	
! 	async event void PhyTransmit.txDone(phy_error_t error)
  	{
! 		phyIsTransmitting = FALSE;
! 		signal FrameTx.txDone[txQueue[nextDone]](error);
! 		nextDone = (nextDone+1)%2;
  	}
  
+ 	default async event void FrameTx.txDone[uint8_t service](phy_error_t error) {}
  }

Index: SuperframeM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/lib/ieee802154/mac/SuperframeM.nc,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** SuperframeM.nc	9 Mar 2006 16:45:59 -0000	1.7
--- SuperframeM.nc	23 Aug 2006 09:54:56 -0000	1.8
***************
*** 1,10 ****
! /* 
! Superframe convenience functions.
  
! @author Jan Flora <janflora at diku.dk>
! @author Esben Zeuthen <zept at diku.dk>
  */
  
! #include <PhyTypes.h>
  
  module SuperframeM
--- 1,35 ----
! /* Copyright (c) 2006, Jan Flora <janflora at diku.dk>
!  * 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 University of Copenhagen 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.
!  */
  
! /*
!   @author Jan Flora <janflora at diku.dk>
  */
  
! /* 
! Superframe convenience functions.
! */
  
  module SuperframeM
***************
*** 25,41 ****
  	#include "Debug.h"
  	
! 	inline uint16_t requiredBackoffPeriods(symboltime_t duration);
! 	inline symboltime_t getElapsedSymbols(superframe_t *superframe);
! 	inline uint16_t getElapsedBackoffs(superframe_t *superframe);
! 	inline uint16_t getCapBackoffs(superframe_t *superframe);
! 	inline uint16_t getBeaconBackoffs(superframe_t *superframe);
  
! 	command bool Superframe.fitsInCap(capTx_t *frame)
  	{
! 		superframe_t *sf = frame->header->superframe;
! 		// TODO: this might be a good place to initialize the
! 		// transactionTime property of the txheader
! 		return frame->header->transactionTime + 
! 		       getBeaconBackoffs(sf)*aUnitBackoffPeriod
  		       < sf->capLength*sf->slotLength;
  	}
--- 50,71 ----
  	#include "Debug.h"
  	
! 	inline uint16_t requiredBackoffPeriods(time_t duration);
! 	inline time_t getElapsedSymbols(superframe_t *superframe);
! 	inline uint32_t getElapsedBackoffs(superframe_t *superframe);
! 	inline uint32_t getCapBackoffs(superframe_t *superframe);
! 	void calculateTransactionTime(txHeader_t *txOp);
  
! 	command bool Superframe.fitsInCap(txHeader_t *header)
  	{
! 		superframe_t *sf = header->superframe;
! 		// This is always called before transmission. Just calculate
! 		// transaction time in here.
! 		if (!macBeaconEnabled) {
! 			// Always fits if not beacon enabled.
! 			return TRUE;
! 		}
! 		calculateTransactionTime(header);
! 		return header->transactionTime + 
! 		       sf->beaconLength*aUnitBackoffPeriod
  		       < sf->capLength*sf->slotLength;
  	}
***************
*** 43,57 ****
  	command bool Superframe.fitsInGts(cfpTx_t *frame, gtsDescriptor_t *gts)
  	{
  	}
  	
  	command bool Superframe.fitsInCurGts(cfpTx_t *frame, gtsDescriptor_t *gts)
  	{
  	}
  	
! 	command time_t Superframe.getGtsStart()
  	{
  	}
  	
! 	// For CSMA-CA use.
  	// updates frame backoff
  	// when true, frame backoffs are the number of backoff periods since CAP start
--- 73,112 ----
  	command bool Superframe.fitsInGts(cfpTx_t *frame, gtsDescriptor_t *gts)
  	{
+ 		return (frame->header->transactionTime <
  	}
  	
  	command bool Superframe.fitsInCurGts(cfpTx_t *frame, gtsDescriptor_t *gts)
  	{
+ 		superframe_t *sf = frame->header->superframe;
+ 		time_t endTime = sf->startTime + (sf->slotLength*(gts->startSlot+gts->duration-1));
+ 		return ((call LocalTime.getTime() + frame->header->transactionTime) < endTime); 
  	}
  	
! 	command time_t Superframe.getSlotStartTime(superframe_t *sf, uint8_t slot)
! 	{
! 		return sf->startTime + (sf->slotLength*(slot-1));
! 	}
! 	
! 	command bool Superframe.cfpExists(superframe_t *superframe)
  	{
+ 		if (superframe->capLength == aNumSuperframeSlots) {
+ 			return FALSE;
+ 		}
+ 		return TRUE;
  	}
  	
! 	// Checks if a timeout (wait for frame or response) fits inside the current cap.
! 	// Returns 0 if we just wait in the current cap or returns remaining time otherwise.
! 	command time_t Superframe.timeoutFitsInCurCap(time_t timeout, superframe_t *sf)
! 	{
! 		time_t timeLeft = (sf->capLength*sf->slotLength) - getElapsedSymbols(sf);
! 		if (timeLeft < timeout) {
! 			return timeout - timeLeft;
! 		} else {
! 			return 0;
! 		}
! 	}
! 	
! 	// For slotted CSMA-CA use.
  	// updates frame backoff
  	// when true, frame backoffs are the number of backoff periods since CAP start
***************
*** 61,68 ****
  	{
  		superframe_t* sf = frame->header->superframe;
! 		uint16_t elapsedBackoffs, capBackoffs, countedBackoffs, txBackoffs;
  		elapsedBackoffs = getElapsedBackoffs(sf);
  		capBackoffs = getCapBackoffs(sf);
! 		txBackoffs = frame->header->transactionTime / aUnitBackoffPeriod + 1;
  
  		// first, check if the backoff fits in the current CAP
--- 116,124 ----
  	{
  		superframe_t* sf = frame->header->superframe;
! 		uint32_t elapsedBackoffs, capBackoffs, countedBackoffs, txBackoffs;
  		elapsedBackoffs = getElapsedBackoffs(sf);
  		capBackoffs = getCapBackoffs(sf);
! 		// Remember to add two backoff periods for doing the CCA's.
! 		txBackoffs = frame->header->transactionTime / aUnitBackoffPeriod + 3;
  
  		// first, check if the backoff fits in the current CAP
***************
*** 70,119 ****
  		// although the description in 7.5.1.3 does not state this directly
  		countedBackoffs = sf->battLifeExt
! 		                ? macBattLifeExtPeriods + getBeaconBackoffs(sf)
  		                : capBackoffs;
  
! 		if ( elapsedBackoffs > countedBackoffs ) {
  			// no backoff time left in this CAP at all
  			return FALSE;
! 		} else if ( elapsedBackoffs+frame->backoffPeriods > countedBackoffs ) {
! 			// count down backoffs in this CAP, continue in next CAP
  			frame->backoffPeriods -= (countedBackoffs - elapsedBackoffs);
  			return FALSE;
! 		} else if ( elapsedBackoffs+frame->backoffPeriods+txBackoffs > capBackoffs) {
  			// cannot fit transaction into this CAP
  			// create new backoff in next CAP
  			frame->backoffPeriods = 0;
  			return FALSE;
  		} else {
  			// all the checks passed, the backoff+tx fits in this CAP
! 			// update backoffPeriods to be relative to superframe start
! 			frame->backoffPeriods += elapsedBackoffs; 
  			return TRUE;
  		}
  	}
  	
! 	// finds next backoff slot boundary after backoffs are elapsed relative to superframe start
! 	command time_t Superframe.alignBackoff(superframe_t *superframe, uint8_t backoffs)
  	{
! 		time_t t = backoffs;
! 		t *= aUnitBackoffPeriod;
! 		t *= macInvSymbolRate;
! 		t += superframe->startTime;
! 		return t;
  	}
  	
  	command time_t Superframe.getCapEnd(superframe_t *superframe)
  	{
  	}
  	
! 	// General.
! 	command bool Superframe.isBeaconEnabled(superframe_t *superframe)
  	{
! 		return superframe->beaconEnabled;
  	}
  	
! 	command symboltime_t Superframe.getNextStart(superframe_t *superframe)
  	{
! 		symboltime_t bt = superframe->beaconInterval;
  		bt += superframe->startTime;
  		return bt;
--- 126,191 ----
  		// although the description in 7.5.1.3 does not state this directly
  		countedBackoffs = sf->battLifeExt
! 		                ? macBattLifeExtPeriods + sf->beaconLength
  		                : capBackoffs;
  
! 		if ( elapsedBackoffs >= countedBackoffs ) {
  			// no backoff time left in this CAP at all
+ 			DBG_STR("No backoff time left at all in CAP.",1);
+ 			DBG_STRINT("Elapsed Backoffs:",elapsedBackoffs,1);
+ 			DBG_STRINT("Counted Backoffs:",countedBackoffs,1);
+ 			DBG_STRINT("Counted Backoffs:",capBackoffs,1);
  			return FALSE;
! 		} else if ( elapsedBackoffs+frame->backoffPeriods >= countedBackoffs ) {
! 			// Count down backoffs in this CAP, continue in next CAP.
! 			// Don't count the backoffs all the way to zero!
  			frame->backoffPeriods -= (countedBackoffs - elapsedBackoffs);
+ 			DBG_STR("Backoff period does not fit in CAP.",1);
  			return FALSE;
! 		} else if ( elapsedBackoffs+frame->backoffPeriods+txBackoffs > countedBackoffs) {
  			// cannot fit transaction into this CAP
  			// create new backoff in next CAP
  			frame->backoffPeriods = 0;
+ 			DBG_STR("Backoff period fits in CAP, but tx does not.",1);
  			return