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

📄 marshallerm.nc

📁 无线通信的主要编程软件,是无线通信工作人员的必备工具,关天相关教程我会在后续传上.
💻 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;  }}

⌨️ 快捷键说明

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