Пример #1
0
/*-------------------- Power_Desc_store_req --------------------
	2.4.3.1.16 Power_Desc_store_req. (ClusterID=0x0018)

	The Power_Desc_store_req is provided to enable ZigBee end devices on the
	network to request storage of their Power Descriptor on a Primary Discovery
	Cache device which has previously received a SUCCESS status from a
	Discovery_store_req to the same Primary Discovery Cache device. Included in
	this request is the Power Descriptor the Local Device wishes to cache.

	IN/OUT: The destination address where to send the request.

	OUT: The size in bytes of the request payload.
*/
zbSize_t Power_Desc_store_req
(
	zbNwkAddr_t  aNwkAddress  /* IN/OUT: The destination address where to send the request. */
)
{
	if (gDiscoveryCacheResponse)
				Copy2Bytes(aNwkAddress, gDiscoveryCacheSuccess.aNwkAddress);
	
	return sizeof(zbPowerDescriptorStoreRequest_t);
}
Пример #2
0
/*-------------------- Node_Desc_store_req --------------------
	2.4.3.1.15 Node_Desc_store_req. (ClusterID=0x0017)

	The Node_Desc_store_req is provided to enable ZigBee end devices on the
	network to request storage of their Node Descriptor on a Primary Discovery
	Cache device which has previously received a SUCCESS status from a
	Discovery_store_req to the same Primary Discovery Cache device. Included in
	this request is the Node Descriptor the Local Device wishes to cache.

	IN/OUT: The destination address where to send the request.

	OUT: The size in bytes of the request payload.
*/
zbStatus_t Node_Desc_store_req
(
	uint8_t *pAddress  /* IN/OUT: The destination address where to send the request. */
)
{
	if (gDiscoveryCacheResponse)
			Copy2Bytes(pAddress, gDiscoveryCacheSuccess.aNwkAddress);

	return sizeof(zbNodeDescriptorStoreRequest_t);
}
Пример #3
0
/*-------------------- Active_EP_store_req --------------------
	2.4.3.1.17 Active_EP_store_req. (ClusterID=0x0019)

	The Active_EP_store_req is provided to enable ZigBee end devices on the
	network to request storage of their list of Active Endpoints on a Primary
	Discovery Cache device which has previously received a SUCCESS status from a
	Discovery_store_req to the same Primary Discovery Cache device. Included in
	this request is the count of Active Endpoints the Local Device wishes to cache and
	the endpoint list itself.

	IN/OUT: The destination address where to send the request.
	IN: The package with the request information.

	OUT: The size in bytes of the request payload.
*/
zbSize_t Active_EP_store_req
(
	zbNwkAddr_t  aAddress,                       /* IN/OUT: The destination address where to send the request. */
	zbActiveEPStoreRequest_t  *pMessageGoingOut  /* IN: The package with the request information. */
)
{
	if (gDiscoveryCacheResponse)
				Copy2Bytes(aAddress, gDiscoveryCacheSuccess.aNwkAddress);

	return (MbrOfs(zbActiveEPStoreRequest_t, activeEPList[0]) + pMessageGoingOut->activeEPCount);
}
Пример #4
0
void OnOffLight_AppSetLightState
  (
  zbEndPoint_t endPoint,    /* IN: APP endpoint */
  zclCmd_t command          /* IN: */
  )
{
  zclOnOffReq_t req;

  /* set up address info for a unicast to ourselves */
  req.addrInfo.dstAddrMode = gZbAddrMode16Bit_c;
  Copy2Bytes(req.addrInfo.dstAddr.aNwkAddr, NlmeGetRequest(gNwkShortAddress_c));
  req.addrInfo.dstEndPoint = endPoint;
  Set2Bytes(req.addrInfo.aClusterId, gZclClusterOnOff_c);
  req.addrInfo.srcEndPoint = endPoint;
  req.addrInfo.txOptions = gZclTxOptions;
  req.addrInfo.radiusCounter = afDefaultRadius_c;

  /* send the command */
  req.command = command;

  (void)ASL_ZclOnOffReq(&req);
}
Пример #5
0
/*-------------------- Simple_Desc_store_req --------------------
	2.4.3.1.18 Simple_Desc_store_req. (ClusterID=0x001a)

	The Simple_desc_store_req is provided to enable ZigBee end devices on the
	network to request storage of their list of Simple Descriptors on a Primary
	Discovery Cache device which has previously received a SUCCESS status from a
	Discovery_store_req to the same Primary Discovery Cache device. Note that each
	Simple Descriptor for every active endpoint on the Local Device must be
	individually uploaded to the Primary Discovery Cache device via this command
	to enable cached discovery. Included in this request is the length of the Simple
	Descriptor the Local Device wishes to cache and the Simple Descriptor itself. The
	endpoint is a field within the Simple Descriptor and is accessed by the Remote
	Device to manage the discovery cache information for the Local Device.

	IN/OUT: The buffer where the request data will be filled in.
	IN: The package with the request information.
	IN: The destination address where to send the request.

	OUT: The size in bytes of the request payload.
*/
zbSize_t Simple_Desc_store_req
(
	uint8_t *pkgPayload,                                 /* IN/OUT: The buffer where the request data will be filled in. */
	zbSimpleDescriptorStoreRequest_t *pMessageComingIn,  /* IN: The package with the request information. */
	zbNwkAddr_t aDestAddr                                /* IN: The destination address where to send the request. */
)
{
	zbSize_t  payloadLength;

	if (gDiscoveryCacheResponse)
			Copy2Bytes(aDestAddr, gDiscoveryCacheSuccess.aNwkAddress);

	FLib_MemCpy(pkgPayload, pMessageComingIn,MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters));

	payloadLength = MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters) + 
									ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters), 
									&(pMessageComingIn->simpleDescriptor.inputClusters));

	Zdp_GenerateDataReq(gSimple_Desc_store_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet) , payloadLength );

	return gZdpAlreadyHanlded_c;
}
Пример #6
0
/*******************************************************************************
* State machine to send the next report. If it can't get the memory, tries
* again later.
*
* This will concatinate all of the reportable attributes in a single cluster
*******************************************************************************/
void ZCL_SendReport(void)
{
  afDeviceDef_t   *pDevice;
  uint8_t payloadLen;
  uint8_t reportLen;
  afToApsdeMessage_t *pMsg; /* a message for sending the report */
  afAddrInfo_t addrInfo;
  afClusterDef_t *pCluster;
  zclFrame_t  *pFrame;
  uint8_t i;
  zclReportAttr_t *pReportList;
  
  BeeUtilZeroMemory(&addrInfo, sizeof(addrInfo));
  /* starting over? reset indexes */
  if(gfZclReportRestart) {
    gZclReportDeviceIndex = gZclReportClusterIndex = gAsynchronousClusterIndex = 0;
    gfZclReportRestart = FALSE;
  }

  /* get a buffer to build the next report */
  pMsg = AF_MsgAlloc();
  if(!pMsg) {
    gfZclReportRestart = FALSE;
    ZLC_StartShortReportingTimer();
    return;
  }

  /* walk through all devices */
  while(gZclReportDeviceIndex < gNum_EndPoints_c) {

    /* make sure this app endpoint is a ZCL device */
    pDevice = (afDeviceDef_t *) endPointList[gZclReportDeviceIndex].pDevice;
    
    /* report list */
    pReportList = pDevice->pReportList;
    
    if(!pDevice || !pDevice->pfnZCL) {
      ++gZclReportDeviceIndex;
      continue;
    }

    /* Find if any attribute are a asynchronous, then update the attribute */ 
    do
    {
      for(i=0; i<pDevice->reportCount; ++i)
      {
        zclAttrDef_t *pAttrDef;
        zclReportAttr_t *pCurrentReportList = &pReportList[i];
        /* only looking for this one cluster, to see if it's in the reportinglist */
        if(!IsEqual2Bytes(pCurrentReportList->aClusterId, pDevice->pClusterDef[gAsynchronousClusterIndex].aClusterId))
          continue;            
               
        // If the cluster is on the reporting list, find the reporting attribute
        pAttrDef = ZCL_FindAttr(&pDevice->pClusterDef[gAsynchronousClusterIndex], pCurrentReportList->attrId);
        if(pAttrDef)
        {
          /* It's a asynchronous attribute, update before reporting */
          if(ZclAttrIsAsynchronous_c(pAttrDef->flags))
          {
            ++gAsynchronousClusterIndex;
            BeeAppUpdateDevice(0, gZclUI_SendReportingAttributeRequest_c, pAttrDef->id, pCurrentReportList->aClusterId, NULL);
            //Free the message, because we return from here
            MSG_Free(pMsg);
            return;
          }
        }
        
      }
      ++gAsynchronousClusterIndex;
    }while(gAsynchronousClusterIndex < pDevice->clusterCount);

    /* check each cluster for reporting attributes */
    while(gZclReportClusterIndex < pDevice->clusterCount) {

      pCluster = &pDevice->pClusterDef[gZclReportClusterIndex];

      pFrame = (void *)(&((uint8_t *)pMsg)[ApsmeGetAsduOffset()]);

      /* build the report for the next cluster */
      reportLen = ZCL_BuildAttrReport(
        (zclCmdReportAttr_t *)(pFrame + 1),   /* ptr to report frame */
        pDevice,                              /* ptr to device */
        pCluster
        );            

      /* no reporting attributes this cluster */
      if(!reportLen) {
        ++gZclReportClusterIndex;
        continue;
      }

      /* set up the address info */
      addrInfo.dstAddrMode = gZbAddrModeIndirect_c;
      addrInfo.srcEndPoint = endPointList[gZclReportDeviceIndex].pEndpointDesc->pSimpleDesc->endPoint;
      addrInfo.txOptions = gZclTxOptions;
      addrInfo.radiusCounter = afDefaultRadius_c;

      /* determine which cluster to send it to */
      Copy2Bytes(addrInfo.aClusterId, pCluster->aClusterId);

      /* set up frame */
      pFrame->frameControl = gZclFrameControl_FrameTypeGeneral | gZclFrameControl_DisableDefaultRsp;
      pFrame->transactionId = gZclTransactionId++;
      pFrame->command = gZclCmdReportAttr_c;

      /* send the report */
      payloadLen = sizeof(zclFrame_t) + reportLen;
      (void)ZCL_DataRequestNoCopy(&addrInfo, payloadLen, pMsg);

      ++gZclReportClusterIndex;

      /* start a short timer between reporting clusters */
      gfZclReportRestart = FALSE;
      ZLC_StartShortReportingTimer();
      return;
    }
    
    /* try next device */
    ++gZclReportDeviceIndex;
    gZclReportClusterIndex=0;
    gAsynchronousClusterIndex=0;
  } /* end of while(gZclReportDeviceIndex < gNum_EndPoints_c) */

  if(pMsg)
    MSG_Free(pMsg);

  /* start up a new timer if needed */
  if(gZclReportingSetup.reportTimeout != 0 && gZclReportingSetup.reportTimeout != 0xFFFF)
  {
      gZclReportingSetup.reportCounter = gZclReportingSetup.reportTimeout;
      ZLC_StartReportingTimer();
  }
}
Пример #7
0
void HcOutgoingZtcTaskEventMonitor(OepOutgoingMessage_t *message) {
  
  
  hcZtcMessage_t* pMsgFromSAPHandler;
  
  /* cleaner access to the 11073 apdu */   
  oepGenericApdu_t *pApdu = (oepGenericApdu_t *)message->pApdu;
  
  uint8_t* pSrcDataPtr;
  uint8_t* pDstDataPtr;
  
  /* first fragment flag is initially set to True */   
  uint8_t firstFragment = TRUE;
  uint16_t apduLen = message->length - MbrSizeof(oepGenericApdu_t, apduLen);
  
  uint8_t dataCopyLen;

  /* iterate the fragments */   
  do
  {
    /* allocate a new buffer as the ZTC frames are quite different from the actual
       11073 frames */   
    pMsgFromSAPHandler = (hcZtcMessage_t *) MSG_Alloc(mSapHandlerMsgTotalLen_c);    

    if (firstFragment) {
    
      oepMsgType_t oepMsgType; 
    
      firstFragment = FALSE;
      
      /* is it a cfg, prst, other kind of frame? */ 
      oepMsgType = GetOepMsgType(pApdu);
    
      /* get ZTC opcode id for the frame */ 
      pMsgFromSAPHandler->msgType = GetMsgZtcOpCode(pApdu);
      
      
      /* frame is an object configuration frame */ 
      if (oepMsgType == msgType_ObjCfgMsg) {
      
        hcZtcObjCfgFrame_t* pHcZtcObjCfgFrame = (hcZtcObjCfgFrame_t *)pMsgFromSAPHandler->data;
        
        apduLen -= MbrSizeof(oepGenericApdu_t, choice);
        
        if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame)) {
        
          dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame);
          apduLen -= dataCopyLen;
          pHcZtcObjCfgFrame->nextFragmentPresent = TRUE;
          
        }
        else {
        
          dataCopyLen = (uint8_t)apduLen;
          apduLen = 0;
          pHcZtcObjCfgFrame->nextFragmentPresent = FALSE;
          
        }
      
        pMsgFromSAPHandler->msgLen = dataCopyLen + MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame);
                                     
        pSrcDataPtr = (uint8_t *)pApdu->payload;
        
        pDstDataPtr = (uint8_t *)pHcZtcObjCfgFrame->objCfgFrame; 
        
        pHcZtcObjCfgFrame->endPoint = message->srcEndPoint;
        
      }
      else {
        /* Aarq, Aars, Prst, etc type of frame */
        hcZtcFrame_t* pZtcFrameGeneric = (hcZtcFrame_t *)pMsgFromSAPHandler->data;
        
        if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFrame_t, apdu)) {
        
          dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFrame_t, apdu);
          apduLen -= dataCopyLen;
          pZtcFrameGeneric->nextFragmentPresent = TRUE;
          
        } 
        else {

          dataCopyLen = (uint8_t)apduLen;
          apduLen = 0;
          pZtcFrameGeneric->nextFragmentPresent = FALSE;
          
        }
        
        pMsgFromSAPHandler->msgLen = dataCopyLen + MbrOfs(hcZtcFrame_t, apdu);
        
        pSrcDataPtr = (uint8_t *)&pApdu->choice;
        
        pDstDataPtr = (uint8_t *)pZtcFrameGeneric->apdu;
                                
        Copy2Bytes(pZtcFrameGeneric->aSrcDstAddr, message->aDstAddr);
        pZtcFrameGeneric->dstEndPoint = message->dstEndPoint;
        pZtcFrameGeneric->srcEndPoint = message->srcEndPoint;
      }
    }
    else 
    {
      /* this is not the first fragment; */
      
      hcZtcFragmentContinuationFrame_t* pZtcFragmentCont = 
                          (hcZtcFragmentContinuationFrame_t *)pMsgFromSAPHandler->data;
                          
      /* set fragment continuation opcode */
      pMsgFromSAPHandler->msgType = gHcZtcOpcode_FragmentContinuation_d;
      
      if (apduLen > mSapHandlerMsgTotalLen_c - 
          MbrOfs(hcZtcFragmentContinuationFrame_t, fragmentData)) {
        
        dataCopyLen = mSapHandlerMsgTotalLen_c -  
                      MbrOfs(hcZtcFragmentContinuationFrame_t, fragmentData);
        apduLen -= dataCopyLen;
        pZtcFragmentCont->nextFragmentPresent = TRUE;
        
      } 
      else {

        dataCopyLen = (uint8_t)apduLen;
        apduLen = 0;
        pZtcFragmentCont->nextFragmentPresent = FALSE;
        
      }
      
      pMsgFromSAPHandler->msgLen = dataCopyLen +
                           MbrSizeof(hcZtcFragmentContinuationFrame_t, fragmentData);

      pDstDataPtr = (uint8_t *)pZtcFragmentCont->fragmentData;
    }
    
    FLib_MemCpy(pDstDataPtr, pSrcDataPtr, dataCopyLen);
    
    pSrcDataPtr += dataCopyLen;
    
    /* send message to ZTC */
#ifndef gHostApp_d        
    ZTC_TaskEventMonitor(gHcApp_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c);
#else
    ZTC_TaskEventMonitor(gpHostAppUart, gHcApp_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c);
#endif     

    /* free the message if ZTC hasn't already done that */
    if (pMsgFromSAPHandler)
      MSG_Free(pMsgFromSAPHandler);
    
  } while (apduLen > 0);
}
Пример #8
0
void HcIncomingZtcTaskEventMonitor(OepFragmentedApdu_t *message) {
  
  hcZtcMessage_t* pMsgFromSAPHandler;
  
  /* pCurrentFragment points initially to the fragment in OepFragmentedApdu_t */   
  OepApduFragment_t* pCurrentFragment = &message->fragment;
  
  /* cleaner access to the 11073 apdu */   
  oepGenericApdu_t *pApdu = (oepGenericApdu_t *)pCurrentFragment->data;
  
  
  /* first fragment flag is initially set to True */   
  uint8_t firstFragment = TRUE;

  /* iterate the fragments */   
  do {
  
    uint8_t srcOffset, dstOffset, dataCopyLen;
  
    /* allocate a new buffer as the ZTC frames are quite different from the actual
       11073 frames */   
    pMsgFromSAPHandler = (hcZtcMessage_t *) MSG_Alloc(mSapHandlerMsgTotalLen_c);    

    /* set default values for mem copy offsets and length */
    
    /* by default copy data beginning with the choice member in the apdu */      
    srcOffset = MbrOfs(oepGenericApdu_t, choice);
    
    /* by default copy data to the apdu member in the ztc frame*/          
    dstOffset = MbrOfs(hcZtcFrame_t, apdu);    
    
    /* data copy length adjusted to omit apduLen field */              
    dataCopyLen = pCurrentFragment->len - MbrOfs(oepGenericApdu_t, choice);
    
    if (firstFragment) {
      oepMsgType_t oepMsgType; 
    
      firstFragment = FALSE;
    
      /* is it a cfg, prst, other kind of frame? */ 
      oepMsgType = GetOepMsgType(pApdu);
    
      /* get ZTC opcode id for the frame */ 
      pMsgFromSAPHandler->msgType = GetMsgZtcOpCode(pApdu);
      
      /* frame is an object configuration frame */ 
      if (oepMsgType == msgType_ObjCfgMsg) {
      
        /* msgLen is the length of the ZTC payload; this includes the actual
           apdu payload, without the choice and apduLen as well as the src/dstEndPoint
           and nextFragmentPresent bytes */
        pMsgFromSAPHandler->msgLen = (uint8_t)(pCurrentFragment->len - 
                                     MbrOfs(oepGenericApdu_t, payload) +
                                     MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame));
                                     
        /* adjust source offset for data copy to not include choice */ 
        srcOffset = MbrOfs(oepGenericApdu_t, payload);
        
        /* adjust dst offset for data copy as srcAddress and an endpoint are no longer included */
        dstOffset = MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame);
        
        /* adjust data length for data copy as choice is no longer included */
        dataCopyLen -= MbrSizeof(oepGenericApdu_t, choice);
        
        /* set destination endpoint as second byte in the ZTC
           packet based on frame direction */
        pMsgFromSAPHandler->data[1] = message->dstEndPoint;
                                     
      }
      else {
        /* Aarq, Aars, Prst, etc type of frame */
        hcZtcFrame_t* pZtcFrameGeneric = (hcZtcFrame_t *)pMsgFromSAPHandler->data;
        
        /* msgLen is the length of the ZTC payload; this includes the actual
           apdu payload, without the apduLen as well as the addressing information
           and nextFragmentPresent bytes */
        pMsgFromSAPHandler->msgLen = pCurrentFragment->len -
                                     MbrOfs(oepGenericApdu_t, choice) +
                                     MbrOfs(hcZtcFrame_t, apdu);
                                     
        /* copy addressing info */
        Copy2Bytes(pZtcFrameGeneric->aSrcDstAddr, message->aSrcAddr);
        pZtcFrameGeneric->dstEndPoint = message->dstEndPoint;
        pZtcFrameGeneric->srcEndPoint = message->srcEndPoint;
      }
    }
    else 
    {
      /* this is not the first fragment; */
      
      /* set data copy and copy size accordingly */ 
      srcOffset = 0;
      dstOffset = 1;
      dataCopyLen = pCurrentFragment->len;
      
      pApdu =  (oepGenericApdu_t *)pCurrentFragment->data;
      
      /* set fragment continuation opcode */
      pMsgFromSAPHandler->msgType = gHcZtcOpcode_FragmentContinuation_d;
      
        /* msgLen includes the actualapdu payload and the nextFragmentPresent byte */      
      pMsgFromSAPHandler->msgLen = pCurrentFragment->len +
                                   MbrSizeof(hcZtcFrame_t, nextFragmentPresent);
    }
    
    /* nextFragmentPresent */
    pMsgFromSAPHandler->data[0] = FALSE;
    
    /* set nextFramgentPresent byte in ZTC frame to 1 if there is
       another fragment to be processed */
    if (pCurrentFragment->nextFragment != NULL)
      pMsgFromSAPHandler->data[0] = TRUE;
    
    /* do the fragment iteration */
    pCurrentFragment = pCurrentFragment->nextFragment;

    /* copy payload data */
    FLib_MemCpy((uint8_t*)pMsgFromSAPHandler->data + dstOffset,
                (uint8_t*)pApdu + srcOffset,
                dataCopyLen);
    
    /* send message to ZTC */
#ifndef gHostApp_d        
    ZTC_TaskEventMonitor(gAppHc_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c);
#else
    ZTC_TaskEventMonitor(gpHostAppUart, gAppHc_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c);
#endif     
    /* free the message if ZTC hasn't already done that */
    if (pMsgFromSAPHandler)
      MSG_Free(pMsgFromSAPHandler);
    
  } while (pCurrentFragment != NULL);
}
Пример #9
0
/************************************************************************************
* Using the default values of the ApsCahnnelMask and ScandDuration, Generates an
* Nlme command to discover the ZigBee networks that may exist on the current
* channel list.
*
* Interface assumptions:
*   Uses APS channel mask (gApsChannelMask_c)
*
* Return value:
*   NONE.
*
* Revison history:
*   Date   Author  Comments
*  ------  ------  --------
*  280208    MN    Updated
************************************************************************************/
void ZdoNwkMng_GenerateNetworkFormation
(
  void  /*IN: No Input Parameters*/
)
{
  nlmeNetworkFormationReq_t  *pNwkFormationReq;
  zdoNlmeMessage_t *pNwkMsg;
  uint8_t *pChannelList = (uint8_t *)ApsmeGetRequest(gApsChannelMask_c);

#if gComboDeviceCapability_d
  if (NlmeGetRequest(gDevType_c) != gCoordinator_c)
    return;
#endif

  /*
    every single command needs it own buffer to be passed down to next layer.
  */
  pNwkMsg = MSG_AllocType(zdoNlmeMessage_t);
  /*
    If the buffer allocation fails for any reason, that is it, no further
    processing is needed.
  */
  if ( !pNwkMsg )
    return;

  /*
    Create the network formation request and sent to the network Layer.
  */
  pNwkMsg->msgType = gNlmeNetworkFormationRequest_c;

  /*
    Fast access to the memory where the 
  */
  pNwkFormationReq = &pNwkMsg->msgData.networkFormationReq;

#if gComboDeviceCapability_d
  if (NlmeGetRequest(gDevType_c) == gCoordinator_c)
#endif
  {
    /*
      We will use the list from the ED if and only if it is a valid list other wise use
      the current APS channel mask.
    */
    if ((*(uint32_t *)gaScanChannels) != 0)
    {
      /* Use only the channels with the best energy levels for the active scan. */
      pChannelList = gaScanChannels;
    }
  }

  /*
    Using the default channel mask, generate the Formation command.
  */
  FLib_MemCpy(pNwkFormationReq->aScanChannels,
              pChannelList,
              sizeof(ApsmeGetRequest(gApsChannelMask_c)));

  /*
    Get all the parameters neede for this command.
  */
  pNwkFormationReq->scanDuration = gScanDuration_c;
  FLib_MemCpy(&pNwkFormationReq->beaconOrder, &gBeeStackConfig.beaconOrder, 2);
  Copy2Bytes(pNwkFormationReq->aPanId, NlmeGetRequest(gNwkPanId_c));
  pNwkFormationReq->batteryLifeExtension = gBeeStackConfig.batteryLifeExtn;

  if (ZDO_NLME_SapHandler( pNwkMsg ))
  {
    /*
      Catch the error if needed.
    */
  }

}