[Tinyos-commits] CVS: tinyos-1.x/tos/lib/Hood Hood.nc, NONE, 1.1 HoodM.nc, NONE, 1.1 HoodManager.nc, NONE, 1.1 HoodTransport.h, NONE, 1.1 HoodTransport.nc, NONE, 1.1 HoodTransportC.nc, NONE, 1.1 HoodTransportM.nc, NONE, 1.1 Marshall.nc, NONE, 1.1 Marshaller.h, NONE, 1.1 MarshallerM.nc, NONE, 1.1 README, NONE, 1.1 ReflBackend.nc, NONE, 1.1 Reflection.nc, NONE, 1.1 ReflectionM.nc, NONE, 1.1 Unmarshall.nc, NONE, 1.1

Kamin Whitehouse kaminw at users.sourceforge.net
Fri Sep 23 03:13:57 PDT 2005


Update of /cvsroot/tinyos/tinyos-1.x/tos/lib/Hood
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4228/Hood

Added Files:
	Hood.nc HoodM.nc HoodManager.nc HoodTransport.h 
	HoodTransport.nc HoodTransportC.nc HoodTransportM.nc 
	Marshall.nc Marshaller.h MarshallerM.nc README ReflBackend.nc 
	Reflection.nc ReflectionM.nc Unmarshall.nc 
Log Message:
These are 5 new tinyos libraries to: 1) automatically define a namespace of node attributes such as location, sensor values, etc, which is exposed through a central 'registry' 2) store these attributes to flash 3) expand that namespace to attributes of neighbors (hood) 4) expose arbitrary functions, including the get/set functions of registry attributes to other nodes and/or the pc through an rpc interface 5) expose arbitrary module variables through the same rpc interface.  These libraries require code generation and must be used with nesc 1.2 or later. the code generation scripts are in tinyos-1.x/tools/scripts/codeGeneration.

--- NEW FILE: Hood.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface Hood
{
  command uint8_t numNeighbors();
  command uint8_t numSlots();
  command bool getNeighborID ( uint8_t p_index, uint16_t *neighborID );
  command bool isNeighbor( uint16_t id );
  event void addedNeighbor(uint16_t nodeID);
  event void removedNeighbor(uint16_t nodeID);
}

--- NEW FILE: HoodM.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

generic module HoodM (uint8_t hoodID, uint8_t numSlots){
  provides{
    interface StdControl;
    interface Hood;
    interface HoodManager;
    interface GenericBackend;
  }
  uses{
    interface ReflBackend[AttrID_t reflID];
    interface HoodTransport;
  }
}
implementation {
  uint16_t neighbor[numSlots];
  bool isvalid[numSlots];
  bool candidate[numSlots];
  bool completeCandidate[numSlots];
  uint8_t numNeighbors;

  command result_t StdControl.init() {
    uint8_t i;
    for( i=0; i>numSlots; i++){
      isvalid[i] = FALSE;
      candidate[i] = FALSE;
      completeCandidate[i] = FALSE;
    }
    numNeighbors = 0;
    return SUCCESS;
  }

  command result_t StdControl.start() {
    return SUCCESS;
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }

  bool isInTable(uint16_t nodeID, uint8_t *slot){
    uint8_t i;
    for (i=0;i<numSlots;i++){
      if (isvalid[i] && (nodeID==neighbor[i]) ){
	*slot = i;
	return TRUE;
      }
    }
    return FALSE;
  }    

  command uint8_t Hood.numNeighbors(){
    return numNeighbors;
  }

  command uint8_t Hood.numSlots(){
    return numSlots;
  }

  command bool Hood.getNeighborID ( uint8_t p_index, uint16_t *neighborID ){
    uint8_t i, count=0;
    for (i=0;i<numSlots;i++){
      if ( isvalid[i] && !candidate[i] ){
	count++;
	if (count > p_index){
	  return TRUE;
	}
      }
    }
    return FALSE;
  }

  command bool Hood.isNeighbor( uint16_t nodeID ){
    uint8_t slot;
    if (isInTable(nodeID, &slot) && !candidate[slot] ){
      return TRUE;
    }
    return FALSE;
  }

  command result_t HoodManager.removeNeighbor(uint16_t nodeID ){
    uint8_t slot, i;
    AttrID_t reflID;
    if (isInTable(nodeID, &slot) ){

      //first, make the neighbor invalid
      isvalid[slot]=FALSE;
      numNeighbors--;

      //now go through and invalidate all refls
      for ( i=0 ; i < numReflections[hoodID-HOOD_ID_OFFSET] ; i++ ){
	reflID = reflections[hoodID-HOOD_ID_OFFSET][i];
	call ReflBackend.clear[reflID](slot);
      }

      //      dbg(DBG_USR1, "Hood: removed node %d from slot %d\n", nodeID, slot); 
      signal Hood.removedNeighbor(nodeID);
      return SUCCESS;
    }
    return FAIL;
  }

  command result_t HoodManager.acceptCandidate(uint16_t nodeID){
    uint8_t slot, i;
    ReflID_t reflID;
    if (numNeighbors < numSlots && isInTable(nodeID, &slot) && candidate[slot]){
      candidate[slot]=FALSE;
      numNeighbors++;
      //      dbg(DBG_USR1, "Hood: accepted node %d into table in slot %d\n", nodeID, slot); 
      
      // signal new neighbor event
      signal Hood.addedNeighbor(nodeID);

      // signal updated events for all valid reflections
      for ( i=0 ; i <  numReflections[hoodID-HOOD_ID_OFFSET] ; i++ ){
	reflID = reflections[hoodID-HOOD_ID_OFFSET][i];
	//for now, there's no better way to signal updated events than this:
	call ReflBackend.set[reflID]( slot, 
				      call ReflBackend.get[reflID](slot), 
				      nodeID);
      }

      return SUCCESS;
    }
    return FAIL;
  }

  command result_t HoodManager.replaceNeighborWithCandidate(uint16_t neighborID, uint16_t candidateID){
    if (neighborID==candidateID){
      return call HoodManager.acceptCandidate(candidateID);
    }
    else{
      if (call Hood.isNeighbor(candidateID) ){
	if (call HoodManager.removeNeighbor(neighborID)){
	  return call HoodManager.acceptCandidate(candidateID);
	}
      }
    }
    return FAIL;
  }

  event result_t ReflBackend.updateRequest[AttrID_t reflID](uint16_t nodeID){
    return call HoodTransport.attrPull(reflID, nodeID);
  }

  event bool ReflBackend.isCandidate[AttrID_t reflID](uint8_t slot){
    return candidate[slot];
  }

  event bool ReflBackend.isNeighbor[AttrID_t reflID](uint16_t nodeID, uint8_t *slot){
    return isInTable(nodeID, slot);
  }

  result_t addCandidate(uint16_t nodeID, uint8_t slot ){
    uint8_t i;
    AttrID_t reflID;
    if (!isvalid[slot]){
      
      //invalidate all refls in this slot
      for ( i=0 ; i <  numReflections[hoodID-HOOD_ID_OFFSET] ; i++ ){
	reflID = reflections[hoodID-HOOD_ID_OFFSET][i];
	call ReflBackend.clear[reflID](slot);
      }

      //now add the candidate
      completeCandidate[slot] = FALSE;
      candidate[slot] = TRUE;
      neighbor[slot] = nodeID;
      isvalid[slot] = TRUE;
      return SUCCESS;
    }
    return FAIL;
  }


  /**********
   * set: a new attribute has arrived.  This is where the action is:
   * Here, we update the node with the new reflection.
   * There is always at least one slot reserved for candidates, so the
   * data being passed into this function is guaranteed to fit, although
   * one of the old candidates might be booted out to make space.  After
   * the data is updated, a newCandidate event is fired if there is now a
   * complete candidate that was not there before.
   **********/
  command result_t GenericBackend.set(const void* itemID, const void* data){
    uint8_t slot,i;

    //if this node is not already in the neighbor table, add it.
    //    dbg(DBG_USR1, "Hood: new value for refl %d of node %d\n", ((ReflBackend_t*)itemID)->reflID, 
    //							       ((ReflBackend_t*)itemID)->nodeID);
    if (!isInTable(((ReflBackend_t*)itemID)->nodeID, &slot) ){
      //    dbg(DBG_USR1, "Hood: node %d not in table\n", ((ReflBackend_t*)itemID)->nodeID);

      //first, try to add it in an empty slot.  
      if (numNeighbors < numSlots) {
	for ( slot=0 ; slot < numSlots ; slot++ ){
	  if (!isvalid[slot]){
	    if ( addCandidate(((ReflBackend_t*)itemID)->nodeID, slot) ){
	      //	      dbg(DBG_USR1, "Hood: added node %d as candidate in empty slot %d\n", ((ReflBackend_t*)itemID)->nodeID, slot);
	      break;
	    }
	  }
	}
      }
      //otherwise, replace the first existing candidate.
      else {
	for ( slot=0 ; slot < numSlots ; slot++ ){
	  if (candidate[slot]){
	    if (call HoodManager.removeNeighbor(neighbor[slot])){
	      if (addCandidate(((ReflBackend_t*)itemID)->nodeID, slot)) {
		//dbg(DBG_USR1, "Hood: added node %d as candidate by replacing node %d in slot %d\n", 
		//		    ((ReflBackend_t*)itemID)->nodeID, neighbor[slot], slot);
		break;
	      }
	    }
	  }
	}
      }
    }

    //at this point, we know the node is in the table.  find and update it.
    if (isInTable(((ReflBackend_t*)itemID)->nodeID, &slot) ){
      if ( call ReflBackend.set[((ReflBackend_t*)itemID)->reflID](slot, data, 
								  ((ReflBackend_t*)itemID)->nodeID) ){
	//	dbg(DBG_USR1, "Hood: set value of refl %d for node %d\n", 
	//	    ((ReflBackend_t*)itemID)->reflID, 
	//	    ((ReflBackend_t*)itemID)->nodeID);
      }

      //now, check if it just became a complete candidate.
      if ( candidate[slot] && !completeCandidate[slot] ){
	AttrID_t reflID;
	bool complete=TRUE;

	// see if we have all required fields for this candidate.
	for ( i=0 ; i <  numRequired[hoodID-HOOD_ID_OFFSET] ; i++ ){
	  reflID = requiredAttrs[hoodID-HOOD_ID_OFFSET][i];
	  complete &= call ReflBackend.get[reflID](slot)==NULL ? 
	    FALSE : TRUE;
	}

	// if so, signal that there is a new candidate to evaluate.
	if (complete) {
	  // dbg(DBG_USR1, "Hood: node %d is a new completed candidate\n", ((ReflBackend_t*)itemID)->nodeID);
	  completeCandidate[slot]=TRUE;
	  signal HoodManager.newCandidate(neighbor[slot]);
	}
      }
    }

    return SUCCESS;
  }



  /*******************
   * the rest just translates from the runtime parameter used by
   * GenericBackend to the compile time parameter used by ReflBackend.
   *****************/

  command uint8_t GenericBackend.size(const void* itemID){
    return call ReflBackend.size[((ReflBackend_t*)itemID)->reflID](0);
  }

  command const void* GenericBackend.get(const void* itemID){
    uint8_t slot;
    if (isInTable(((ReflBackend_t*)itemID)->nodeID, &slot)){
      return call ReflBackend.get[((ReflBackend_t*)itemID)->reflID](slot);
    }
    return NULL;
  }

  command result_t GenericBackend.update(const void* itemID){
    //Reflections should not be updated through the backend query
    //system; this is due to overloading of the term "update" between
    //attributes and reflections.  Update for attributes means
    //"generate a new value".  Update for reflections means get a new
    //version of the neighbor attribute over the network.  
    return FAIL;
  }

  default event void GenericBackend.updated(const void* itemID, const void* newvalue){
  }

  default event void Hood.addedNeighbor(uint16_t nodeID){
  }
  default event void Hood.removedNeighbor(uint16_t nodeID){
  }
  default event void HoodManager.newCandidate(uint16_t nodeID){
  }

  default command uint8_t ReflBackend.size[AttrID_t reflID](uint8_t slot){
    return 0;
  }
  default command const void* ReflBackend.get[AttrID_t reflID](uint8_t slot){
    return NULL;
  }
  default command result_t ReflBackend.set[AttrID_t reflID](uint8_t slot, const void* val, uint16_t nodeID){
    return FALSE;
  }
  default command result_t ReflBackend.clear[AttrID_t reflID](uint8_t slot){
    return FALSE;
  }

}


--- NEW FILE: HoodManager.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface HoodManager  
{
  command result_t removeNeighbor(uint16_t nodeID);
  command result_t acceptCandidate(uint16_t nodeID);
  command result_t replaceNeighborWithCandidate(uint16_t neighborID, uint16_t candidateID);
  event void newCandidate(uint16_t nodeID);
}

--- NEW FILE: HoodTransport.h ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

#ifndef __HOODTRANSPORT_H__
#define __HOODTRANSPORT_H__


enum {
  HOODTRANSPORT_BUFFER_LENGTH = 28,
  HOODTRANSPORT_MAX_ITEMS = 10,
  HOOD_TRANSPORT_QUEUEING_DELAY = 50 //the number of msecs to wait for
				   //additional attrs to send or query for
};

enum {
  AM_HOODDATAMSG         = 111,
  AM_HOODQUERYMSG        = 112
};

enum {
  HOOD_TRANSPORT = 4
};

typedef struct HoodDataMsg {
  uint8_t length;
  uint8_t data[0];
} HoodDataMsg;

typedef struct HoodQueryMsg {
  uint8_t      numItems;        
  AttrID_t     itemList[0];
} HoodQueryMsg;

#endif 

--- NEW FILE: HoodTransport.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface HoodTransport
{
    command result_t attrPush(uint8_t attrID);
    command result_t attrPull(uint8_t attrID, uint16_t nodeID);
}

--- NEW FILE: HoodTransportC.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

includes HoodTransport;

configuration HoodTransportC {
  provides {
    interface StdControl;
    interface HoodTransport;
  }
  uses{
    interface GenericBackend[HoodID_t hoodID];
  }
}
implementation {

  components 
    HoodTransportM,
    RegistryC,
    MarshallerM,
    GenericComm,
    TimerC;

  StdControl = HoodTransportM;
  HoodTransport = HoodTransportM;

  HoodTransportM.SubControl -> MarshallerM;
  HoodTransportM.SubControl -> GenericComm;

  HoodTransportM.AttrBackend -> RegistryC;
  
  //Marshaller wiring
  GenericBackend = MarshallerM;
  HoodTransportM.Marshall->MarshallerM.Marshall[HOOD_TRANSPORT];
  HoodTransportM.Unmarshall->MarshallerM.Unmarshall[HOOD_TRANSPORT];
  MarshallerM.GenericBackend[MARSHALL_REGISTRY]->RegistryC;

  //Timer wiring
  HoodTransportM.sendListTimer -> TimerC.Timer[unique("Timer")];
  HoodTransportM.queryListTimer -> TimerC.Timer[unique("Timer")];

  //genericComm wiring
  HoodTransportM.DataReceive -> GenericComm.ReceiveMsg[AM_HOODDATAMSG];
  HoodTransportM.QueryReceive -> GenericComm.ReceiveMsg[AM_HOODQUERYMSG];

  HoodTransportM.DataSend -> GenericComm.SendMsg[AM_HOODDATAMSG];
  HoodTransportM.QuerySend -> GenericComm.SendMsg[AM_HOODQUERYMSG];

}

--- NEW FILE: HoodTransportM.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

includes Registry;
includes Hood;

module HoodTransportM {
  provides {
    interface StdControl;
    interface HoodTransport;
  }
  uses {
    interface StdControl as SubControl;

    interface AttrBackend[AttrID_t attrID];
    
    interface Marshall;
    interface Unmarshall;
    
    interface Timer as sendListTimer; 
    interface Timer as queryListTimer;

    interface ReceiveMsg as DataReceive;
    interface SendMsg as DataSend;

    interface ReceiveMsg as QueryReceive;
    interface SendMsg as QuerySend;
  }
}
implementation {

  /*******************
   *  This module handles two types of things: 1) requests to send out an
   *  attribute to neighbors and 2) requests to query a neighbor for it's
   *  attributes.  All requests are an AttrID_t which identifies the
   *  attribute.  When this module receives a request of either kind, it
   *  adds it to the sendList or queryList, respectively.  It also sends
   *  all attributes which are "grouped" with the requested attribute
   *  (attributes are grouped by Hoods which need the entire group of
   *  attributes to make a membership decision).  The sendList and
   *  queueList are processed when they get full or when
   *  HOOD_TRANSPORT_QUEUEING_DELAY milliseconds pass since the last item
   *  was added to the list, whichever comes first.  Most of this work is
   *  done by the following four functions, all other functions in this
   *  module simply handle events:
   *
   * add an attr and it's group to the send list
   *     result_t addToSendList(AttrID_t attrID);
   *
   * add an attr and it's group to the query list
   *     void addToQueryList(AttrID_t attrID, uint16_t nodeID);
   *
   * process the send list
   *     result_t marshallUpSendList();
   *
   * process the query list
   *     result_t sendOffQueryList();
   *
   ******************/

  //two msg data buffers: one for sending queries, one for sending data
  TOS_Msg queryMsg;                         
  TOS_Msg dataMsg;
  TOS_MsgPtr pQueryMsg = &queryMsg;
  TOS_MsgPtr pDataMsg = &dataMsg;

  //two more buffers: one for attrs to send, one for attrs to query for
  AttrID_t sendList[HOODTRANSPORT_MAX_ITEMS];    //for collecting ids of attrs to send
  uint8_t sendListPos;
  AttrID_t queryList[HOODTRANSPORT_MAX_ITEMS];   //for collecting ids of nbr's attrs to query for
  uint8_t queryListPos;
  uint16_t nbrToQuery;
  
  //a few state variables
  bool queryMsgSending;
  bool dataMsgSending;

  command result_t StdControl.init() {
    queryMsgSending = FALSE;
    dataMsgSending = FALSE;
    sendListPos=0;
    queryListPos=0;
    return call SubControl.init();
  }

  command result_t StdControl.start() {
    return call SubControl.start();
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }

  bool addToList(AttrID_t attrID, AttrID_t list[], uint8_t *currentPos){
    uint8_t i;

    //make sure this attrID isn't already in the list
    for ( i=0; i< *currentPos; i++ ) {
      if (attrID == list[i]) {
	return FALSE; //did not add anything
      }
    }

    //then add it to the end of the list
    list[*currentPos] = attrID;
    *currentPos = *currentPos + 1;
    return TRUE; //did add something
  }


  result_t marshallUpSendList(){
    ReflBackend_t header[HOODTRANSPORT_MAX_ITEMS];
    uint8_t i;

    //build the headers for packing
    for(i=0;i<sendListPos;i++){
      header[i].reflID = sendList[i];
      header[i].nodeID = TOS_LOCAL_ADDRESS;
    }

    //make sure we are not marshalling an empty list
    if (sendListPos == 0){
      dbg(DBG_USR1, "HoodTransport: nothing in sendList to marshall\n");
      return FAIL;
    }

    //now marshall it up
    //    dbg(DBG_USR1, "HoodTransport: requesting sendList to be marshalled\n");
    if (call Marshall.marshall(MARSHALL_REGISTRY,  
			       (void*)sendList, sizeof(AttrID_t),
			       (void*)&header, sizeof(ReflBackend_t),
			       sendListPos, HOODTRANSPORT_BUFFER_LENGTH) ){
      sendListPos = 0;
      return SUCCESS;
    }
    return FAIL;
  }

  result_t addToSendList(AttrID_t attrID){
    uint8_t i;
    bool needToSetTimer = FALSE;

    //add all attrs that are grouped with this one
    for( i=0; i<groupSize[attrID]; i++ ){
      needToSetTimer &= 
	addToList ( attrGroup[attrID][i], sendList, &sendListPos );
      
      //clear the sendList buffer if it gets full
      if (sendListPos >= HOODTRANSPORT_MAX_ITEMS) {
	if (marshallUpSendList() == FAIL){
	  //not robust: data can be lost here!!! 
	  sendListPos = 0;
	  return FAIL;
	}
	needToSetTimer = FALSE;
      }
    }

    if (needToSetTimer){
      call sendListTimer.stop();
      return call sendListTimer.start(TIMER_ONE_SHOT, HOOD_TRANSPORT_QUEUEING_DELAY);
    }
    else{
      return SUCCESS;
    }
  }

  result_t sendOffQueryList(){
    HoodQueryMsg* msg = (HoodQueryMsg*)pQueryMsg->data;
    
    //if msg is busy, forget the data.  hopefully, this will never
    //happen. it might happen if a node queries multiple nbrs simultaneosly
    if (queryMsgSending) {
      dbg(DBG_USR1, "HoodTransport: query msg buffer busy... data lost!\n");
      queryListPos = 0;
      return FAIL; 
    }

    //make sure we are not sending an empty message
    if (queryListPos == 0){
      dbg(DBG_USR1, "HoodTransport: nothing in queryList to send\n");
      return FAIL;
    }

    //otherwise, set up the query msg
    msg->numItems = queryListPos;
    memcpy ( msg->itemList, queryList, queryListPos * sizeof(AttrID_t) );
    
    //and send it off
    if (call QuerySend.send(nbrToQuery,
			    sizeof(HoodQueryMsg) + (sizeof(AttrID_t)*queryListPos), 
			    pQueryMsg)) {
      //      dbg(DBG_USR1, "HoodTransport: query msg sent\n");
      queryListPos = 0;
      queryMsgSending = TRUE;
      return SUCCESS;
    }
    return FAIL;
  }

  result_t addToQueryList(AttrID_t attrID, uint16_t nodeID){
    uint8_t i;
    bool needToSetTimer=FALSE;

    //if this is a different node than we are currently queueing for,
    //then send off the current query
    if ( queryListPos > 0 && nbrToQuery != nodeID ) {
      if (sendOffQueryList() == FAIL ){
	return FAIL;
      }
    }
    nbrToQuery = nodeID;

    //add all attrs that are grouped with this one
    for( i=0; i<groupSize[attrID]; i++ ){
      needToSetTimer &= 
	addToList ( attrGroup[attrID][i], queryList, &queryListPos );
      
      //clear the queryList buffer if it gets full
      if (queryListPos > HOODTRANSPORT_MAX_ITEMS) {
	if (sendOffQueryList() == FAIL) {
	  return FAIL;
	}
	needToSetTimer = FALSE;
      }
    }

    if (needToSetTimer) {
      call queryListTimer.stop();
      return call queryListTimer.start(TIMER_ONE_SHOT, HOOD_TRANSPORT_QUEUEING_DELAY);
    }
    else {
      return SUCCESS;
    }
  }

  event result_t sendListTimer.fired() {
    marshallUpSendList();
    return SUCCESS;
  }

  event result_t queryListTimer.fired() {
    sendOffQueryList();
    return SUCCESS;
  }

  command result_t HoodTransport.attrPush(AttrID_t attrID){
    //    dbg(DBG_USR1, "HoodTransport: attr Pushed: %d\n", attrID);
    return addToSendList(attrID);
  }

  command result_t HoodTransport.attrPull(AttrID_t attrID, uint16_t nodeID){
    //    dbg(DBG_USR1, "HoodTransport: attr pulled: %d\n", attrID);
    return addToQueryList(attrID, nodeID);
  }


  event void Marshall.marshalledDataReady(const void* data, uint8_t length){
    HoodDataMsg* msg = (HoodDataMsg*)pDataMsg->data;
    //    dbg(DBG_USR1, "HoodTransport: marshalled data ready\n");
    if (!dataMsgSending){
      msg->length = length;
      memcpy(msg->data, data, length);
      if (call DataSend.send(TOS_BCAST_ADDR, sizeof(HoodDataMsg) + length, pDataMsg)){
	//	dbg(DBG_USR1, "HoodTransport: marshalled data sent \n");
	dataMsgSending = TRUE;
      }
    }
    else{
          dbg(DBG_USR1, "HoodTransport: send buffer busy... data lost!\n");
    }
  }

  event void AttrBackend.updated[AttrID_t attrID](const void* val){
    //    dbg(DBG_USR1, "HoodTransport: AttrBackend updated: %d\n", attrID);
    addToSendList(attrID);
  }

  event result_t DataSend.sendDone(TOS_MsgPtr msg, result_t success){
    dataMsgSending = FALSE;
    pDataMsg = msg;
    return SUCCESS;
  }
  event result_t QuerySend.sendDone(TOS_MsgPtr msg, result_t success){
    queryMsgSending = FALSE;
    pQueryMsg = msg;
    return SUCCESS;
  }

  event TOS_MsgPtr DataReceive.receive(TOS_MsgPtr m){
    HoodDataMsg* msg = (HoodDataMsg*)m->data;
    //    dbg(DBG_USR1, "HoodTransport: data message received and being unmarshalled\n");
    call Unmarshall.unmarshall(ALL_HOODS, msg->data, sizeof(ReflBackend_t), msg->length);
    return m;
  }

  event TOS_MsgPtr QueryReceive.receive(TOS_MsgPtr m){
    HoodQueryMsg* msg = (HoodQueryMsg*)m->data;
    uint8_t i;
    //    dbg(DBG_USR1, "HoodTransport: query message received and being added to sendList\n");
    for ( i=0; i<msg->numItems; i++ ){
      addToSendList(msg->itemList[i]);
    }
    return m;
  }
  
}

--- NEW FILE: Marshall.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface Marshall
{
  command result_t marshall(uint8_t dataSource, 
			    const void* itemID[],
			    uint8_t itemIDLength,
			    const void* itemHeader[],
			    uint8_t itemHeaderLength,
			    uint8_t numItems,
			    uint8_t maxAllowableBufferLength);

  event void marshalledDataReady(const void* data, uint8_t length);
}



--- NEW FILE: Marshaller.h ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

#ifndef __MARSHALLER_H__
#define __MARSHALLER_H__

enum {
  MARSHALL_MAX_ITEMS = 10,
  MARSHALL_ITEM_ID_MAX_LENGTH = 3,
  MARSHALL_ITEM_HEADER_MAX_LENGTH = 3,
  MARSHALL_BUFFER_LENGTH = 28
};

#endif 

--- NEW FILE: MarshallerM.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

includes Marshaller;

module MarshallerM {
  provides {
    interface StdControl;
    interface Marshall[uint8_t marshallClient];
    interface Unmarshall[uint8_t unmarshallClient];
  }
  uses {
    interface GenericBackend[uint8_t backendClient];
  }
}
implementation {

  /********************
   * A marshallClient module is a module that will request marshalling or
   * unmarshalling to be done.  A backendClient is a module that has
   * data.  BackendClients are usually "items" like Registry Attributes or
   * HoodReflections, and they are wired to the GenericBackend interface
   * using the AttrID or HoodID.  The "itemID" is a description of the
   * item.  For Registry attributes, it is just the AttrID.  For Hood
   * reflections, it is the HoodID and the ReflID.  For RAM symbols, it
   * is the memory address and the length.  Etc.  A marshallClient such
   * as the RegisterQuery or RamQuery module usually wants to
   * marshall the data from a backendClient, or send unmarshalled data to
   * a backendClient. 
   *
   * This component keeps it's own buffers of all marshall and
   * unmarshalling requests, ie pointers to data buffers are not 
   * to be exchanged with this component.  Thus, when a message arrives with a
   * marshalling or unmarshalling request, the client module can simply pass the
   * pointer of the incoming message, the data will be copied internal to
   * the marshaller, and the client module can pass the message back to the
   * comm stack immediately.  Likewise, if the client is accumulating a marshall or
   * unmarshall request over time, it can pass the request in when the
   * client's buffer is full, the request is copied internal to the
   * marshaller, and the client can continue using it's own buffer
   * immediately.  The usage model is that all queuing should also
   * happen internal to the marshaller, ie. the client should never have
   * to worry about a marshall or unmarshall request being rejected, or
   * about rejecting a marshallDataReady or GenericBackend.set event; the
   * marshaller should handle queueing. (note that queueing is not
   * implemented yet)
   *
   * Known limitations of the marshaller: 
   *  1.  queueing not implemented yet
   *  2.  does not provide NACKS for marshalling: if a backendClient cannot provide
   * the data, the marshaller will neither notify the marshallClient
   * of the error, nor will it indicate that something is missing in the
   * packed data buffer.  Therefore, if the packed data buffer is sent
   * to another node or the PC, the other node or PC will not know the
   * data is missing.  If the other node or PC knows what data to
   * expect, it will not know if the data will ever arrive or not, so it
   * will have to resort to a timeout/retry mechanism.  The current
   * decision is not to modify the marshaller to provide this info in
   * the packed data buffer, since reliability cannot be provided by
   * the networking layer anyway.  It may be Ok to add the ability to
   * provide nacks to the marshallClient, although currently all
   * marshall clients are "best effort" anyway, so it does not matter.
   * 3.  No error messages on marshalling: if a packed data buffer is
   * to be unmarshalled and the marshaller cannot correctly unpack the
   * data, no error message is provided to the unmarshallClient.
   * Since none of the unmarshallClients would know what to do either,
   * this functionality is not necessary.  
   *********************/

  typedef struct MarshallRequest_t {
    uint8_t itemID[MARSHALL_MAX_ITEMS * MARSHALL_ITEM_ID_MAX_LENGTH];
    uint8_t itemHeader[MARSHALL_MAX_ITEMS * MARSHALL_ITEM_HEADER_MAX_LENGTH];
    uint8_t numItems;
    uint8_t itemIDLength;
    uint8_t itemHeaderLength;
    uint8_t currentItem;
    uint8_t bufferLength;
    uint8_t backendClient;
    uint8_t marshallClient;
  } MarshallRequest_t;
   
  typedef struct UnmarshallRequest_t {
    uint8_t dataDestination;
    uint8_t data[MARSHALL_BUFFER_LENGTH];
    uint8_t dataHeaderLength;
    uint8_t length;
    uint8_t unmarshallClient;
  } UnmarshallRequest_t;
 
  //for now, just one request at a time of each type(no queue)
  MarshallRequest_t request;
  UnmarshallRequest_t unmarshallRequest;

  //even if we use a queue of requests, only allocate one buffer for
  //the *current* marshall request
  uint8_t buffer[MARSHALL_BUFFER_LENGTH];
  uint8_t bufferPosition;

  //a few state variables
  bool isMarshalling;
  bool isUnmarshalling;
  bool waitingForUpdate;
  
  command result_t StdControl.init() {
    isMarshalling=FALSE;
    isUnmarshalling=FALSE;
    waitingForUpdate=FALSE;
    return SUCCESS;
  }

  command result_t StdControl.start() {
    return SUCCESS;
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }

  void advanceToNextItem(){
    request.currentItem++;
  }

  void addToBuffer(const void* newValue, uint8_t length){

    //if this value fits in the buffer, add it (otherwise forget it)
    if (length + request.itemHeaderLength <= request.bufferLength){

      //if the buffer is full, flush it by sending off the data
      if (bufferPosition + length + request.itemHeaderLength > request.bufferLength){
	signal Marshall.marshalledDataReady[request.marshallClient]( buffer, bufferPosition);
	bufferPosition=0;
      }

      //append the item description to the buffer
      memcpy(buffer + bufferPosition, request.itemHeader + (request.currentItem*request.itemHeaderLength), request.itemHeaderLength);
      bufferPosition += request.itemHeaderLength;
      
      //append the new item value to the buffer
      memcpy(buffer + bufferPosition, newValue, length);
      bufferPosition += length;
    }

    advanceToNextItem();
  }

  task void processMarshallRequest(){
    const void* newValue;
    //    dbg(DBG_USR1, "Marshaller: processing request\n");
    while ( request.currentItem < request.numItems  ){
      
      //try getting a cached version
      newValue = call GenericBackend.get[request.backendClient](
				request.itemID + (request.currentItem*request.itemIDLength) );
      //      dbg(DBG_USR1, "Marshaller: tried item #%d:  %d\n",
      //	  request.currentItem, 
      //	  *(uint8_t*)(request.itemID + (request.currentItem*request.itemIDLength) ) );
      if (newValue != NULL){

	//	dbg(DBG_USR1, "Marshaller: adding cached version of item #%d\n", request.currentItem);
	addToBuffer(newValue, 
		    call GenericBackend.size[request.backendClient](request.itemID + (request.currentItem*request.itemIDLength) ) );
      }

      //if cached version doesn't exist, try to get an updated version
      else{

	//if we can get an updated version, wait for the updated event
	if (call GenericBackend.update[request.backendClient](
				 request.itemID + (request.currentItem*request.itemIDLength ) ) ){
	  //	  dbg(DBG_USR1, "Marshaller: waiting for updated version of item #%d\n", request.currentItem);
	  waitingForUpdate = TRUE;
	  return;
	}

	//otherwise, there is no way to get this, so forget about it
	else{
	  dbg(DBG_USR1, "Marshaller: can't get item #%d\n", request.currentItem);
	  advanceToNextItem();
	}
      }
    }

    //if we have finished all the items in the description list,
    //return the data and signal that we are done
    if (bufferPosition > 0){
      signal Marshall.marshalledDataReady[request.marshallClient]( buffer, bufferPosition);
    }
    isMarshalling=FALSE;
  }

  command result_t Marshall.marshall[uint8_t marshallClient](uint8_t dataSource, 
							     const void* itemID[],
							     uint8_t itemIDLength,
							     const void* itemHeader[],
							     uint8_t itemHeaderLength,
							     uint8_t numItems,
							     uint8_t maxAllowableBufferLength){
    /*******************
     * Basic idea of this function: the user passes in a list of item descriptions
     *(e.g attributes, reflections, memory addresses, etc), and this
     * function goes through the list, gets the value of each item,
     * and add the item header and the item value to a
     * buffer. This buffer is then a "packed" version of the items.
     * If the buffer fills up during this process, it is
     * "flushed" by passing it back to the caller, and the process
     * continues.  If the item cannot be gotten, it is ignored.
     * Currently, there is no way to know if something is ignored or slow.
     ******************/
    
    //    dbg(DBG_USR1, "Marshaller: marshall request received\n");
    if (isMarshalling || numItems > MARSHALL_MAX_ITEMS) {
      return FAIL;
    }
    isMarshalling = TRUE;
    bufferPosition=0;

    memcpy(request.itemID, itemID, numItems * itemIDLength);
    request.itemIDLength=itemIDLength;
    memcpy(request.itemHeader, itemHeader, numItems * itemHeaderLength);
    request.itemHeaderLength=itemHeaderLength;
    request.numItems=numItems;
    request.currentItem=0;
    request.bufferLength=maxAllowableBufferLength;
    request.backendClient=dataSource;
    request.marshallClient=marshallClient;
    
    if (post processMarshallRequest()){
      //      dbg(DBG_USR1, "Marshaller: posted request to be processed\n");
      return SUCCESS;
    }
    isMarshalling = FALSE;
    return FAIL;
  }
  
  event void GenericBackend.updated[uint8_t backendClient](const void* itemID, 
							    const void* newValue ) {
    //check if this is the attribute that we requested an update for
    //    dbg(DBG_USR1, "Marshaller: GenericBackend.updated for itemID %d\n", *(uint8_t*)itemID);
    if (waitingForUpdate 
	&& request.backendClient == backendClient){
	// && request.itemID[request.currentItem] == itemID){
      //is there a better way to compare void* values ??
      uint8_t i;
      for ( i = 0; i < request.itemIDLength; i++ ){
	if ( (*(uint8_t*)(request.itemID + (request.currentItem*request.itemIDLength) + i)) != (*(uint8_t*)(&itemID+i)) )
	  return;
      }

      //      dbg(DBG_USR1, "Marshaller: got updated version of item #%d\n", request.currentItem);
      //if it is, add it if it is valid, otherwise skip it
      if (TRUE/*isvalid*/){
	//	dbg(DBG_USR1, "Marshaller: adding updated version of item #%d\n", request.currentItem);
	addToBuffer(newValue, 
		    call GenericBackend.size[request.backendClient](request.itemID + (request.currentItem*request.itemIDLength) ) );
      }
      else{
	advanceToNextItem();
      }
      waitingForUpdate = FALSE;
      if (!post processMarshallRequest()){
	isMarshalling = FALSE;
      }
    }
  }

  task void processUnmarshallRequest(){
    uint8_t dataPosition=0;
	
    //    dbg(DBG_USR1, "Marshaller: processing unmarshall request\n");

    //check for corner case where usUnmarshalling doesn't get cleared
    if (dataPosition == unmarshallRequest.length){
      dbg(DBG_USR1, "Marshaller: nothing to unmarshall\n");
      isUnmarshalling = FALSE;
    }

    //Then unmarshall the whole buffer
    while(dataPosition < unmarshallRequest.length) {
      call GenericBackend.set[unmarshallRequest.dataDestination](unmarshallRequest.data+
								 dataPosition, 
								 unmarshallRequest.data + 
								 dataPosition + 
								 unmarshallRequest.dataHeaderLength);
      dataPosition += 
	call GenericBackend.size[unmarshallRequest.dataDestination]( unmarshallRequest.data+dataPosition )
	+ unmarshallRequest.dataHeaderLength;
    }
    isUnmarshalling = FALSE;
  }


  command result_t Unmarshall.unmarshall[uint8_t unmarshallClient](uint8_t dataDestination, 
								   const void* data,
								   uint8_t dataHeaderLength,
								   uint8_t length){
    /*******************
     * Basic idea of this function: the user passes in a buffer, which
     * is a "packed" version of a number of items.  These items are
     * unpacked and passed up to a data destination, one at a time.
     ******************/

    //    dbg(DBG_USR1, "Marshaller: unmarshall request received\n");
    if (isUnmarshalling || length > MARSHALL_BUFFER_LENGTH) {
      dbg(DBG_USR1, "Marshaller: unmarshall request failed\n");
      return FAIL;
    }
    isUnmarshalling = TRUE;

    unmarshallRequest.dataDestination = dataDestination;
    memcpy(unmarshallRequest.data, data, length);
    unmarshallRequest.dataHeaderLength = dataHeaderLength;
    unmarshallRequest.length = length;
    unmarshallRequest.unmarshallClient = unmarshallClient;

    if (post processUnmarshallRequest()){
      //      dbg(DBG_USR1, "Marshaller: posted unmarshall request to be processed\n");
      return SUCCESS;
    }
    //signal Marshall.doneUnmarshalling[unmarshallRequest.marshallClient]();
    isUnmarshalling = FALSE;
    return FAIL;
  }

  default event void Marshall.marshalledDataReady[uint8_t marshallClient](const void* data, uint8_t length){
  }

  default command uint8_t GenericBackend.size[uint8_t backendClient](const void* itemID){
    return 0;
  }

  default command const void* GenericBackend.get[uint8_t backendClient](const void* itemID){
    return NULL;
  }

  default command result_t GenericBackend.update[uint8_t backendClient](const void* itemID){
    return FALSE;
  }

  default command result_t GenericBackend.set[uint8_t backendClient](const void* itemID, const void* data){
    return FALSE;
  }



}

--- NEW FILE: README ---
directory: tinyos-1.x/tos/lib/Hood
author: kamin whitehouse
date: 9/23/05

Please see the following wiki page for documentation:
http://today.cs.berkeley.edu/nestfe/index.php/Hood

--- NEW FILE: ReflBackend.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface ReflBackend
{
  command uint8_t size(uint8_t slot);
  command const void* get(uint8_t slot); //return NULL if not valid
  command result_t set(uint8_t slot, const void* val, uint16_t nodeID);
  command result_t clear(uint8_t slot);
  event result_t updateRequest(uint16_t nodeID);
  event bool isCandidate(uint8_t slot);
  event bool isNeighbor(uint16_t nodeID, uint8_t *slot);
}


--- NEW FILE: Reflection.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface Reflection<t>
{
  command bool valid(uint16_t nodeID);
  command t get(uint16_t nodeID);
  command result_t scribble(uint16_t nodeID, t val);
  command result_t update(uint16_t nodeID);
  event void updated(uint16_t nodeID,t val);
}


--- NEW FILE: ReflectionM.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

generic module ReflectionM(typedef ReflectionType_t, uint8_t NumNeighbors) {
  provides{
    interface StdControl;
    interface Reflection<ReflectionType_t>;
    interface ReflBackend;
  }
}
implementation {
  ReflectionType_t val[NumNeighbors];
  bool isvalid[NumNeighbors];

  command result_t StdControl.init() {
    uint8_t i;
    for (i=0 ; i < NumNeighbors; i++) {
      isvalid[i]=0;
    }
    return SUCCESS;
  }

  command result_t StdControl.start() {
    return SUCCESS;
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }
  
  command ReflectionType_t Reflection.get(uint16_t nodeID) {
    uint8_t slot;
    if ( signal ReflBackend.isNeighbor(nodeID, &slot) ){
      return val[slot];
    }
    else {
      return val[0];
    }
  }
  command const void* ReflBackend.get(uint8_t slot){
    if (slot >= NumNeighbors){
      return NULL;
    }
    return val+slot;
  }
  
  command bool Reflection.valid(uint16_t nodeID) {
    uint8_t slot;
    return signal ReflBackend.isNeighbor(nodeID, &slot) && isvalid[slot];
  }
  
  command uint8_t ReflBackend.size(uint8_t slot){
    return sizeof(ReflectionType_t);
  }

  command result_t Reflection.update(uint16_t nodeID) {
    return signal ReflBackend.updateRequest(nodeID);
  }

  command result_t Reflection.scribble(uint16_t nodeID, ReflectionType_t newval) {
    uint8_t slot;
    if (signal ReflBackend.isNeighbor(nodeID, &slot) ){
      val[slot]=newval;
      isvalid[slot]=TRUE;
      signal Reflection.updated(nodeID, val[slot]);
      return SUCCESS;
    }
    return FAIL;
  }

  command result_t ReflBackend.set(uint8_t slot, const void* newval, uint16_t nodeID){
    memcpy(val+slot, newval, sizeof(ReflectionType_t));
    isvalid[slot]=TRUE;
    if ( !(signal ReflBackend.isCandidate(slot)) ){
      signal Reflection.updated(nodeID, val[slot]);
    }
    return SUCCESS;     
  }
  
  command result_t ReflBackend.clear(uint8_t slot){
    isvalid[slot]=FALSE;
    return SUCCESS;     
  }
  
  default event void Reflection.updated(uint16_t nodeID, ReflectionType_t newval){
  }

  default event result_t ReflBackend.updateRequest(uint16_t nodeID){
    return FAIL;
  }

}


--- NEW FILE: Unmarshall.nc ---
/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */

/**
 * @author Kamin Whitehouse
 */

interface Unmarshall
{

  command result_t unmarshall(uint8_t dataDestination, 
			      const void* data, 
			      uint8_t dataHeaderLength,
			      uint8_t length);
}




More information about the Tinyos-commits mailing list