Exemple #1
0
/*********************************************************************
 * @fn      MT_NwkCommandProcessing
 *
 * @brief
 *
 *   Process all the NWK commands that are issued by test tool
 *
 * @param   cmd_id - Command ID
 * @param   len    - Length of received SPI data message
 * @param   pData  - pointer to received SPI data message
 *
 * @return  void
 */
void MT_NwkCommandProcessing( uint16 cmd_id , byte len , byte *pData )
{
  byte ret;
#if defined ( MT_NWK_FUNC )
  uint8 dummyExPANID[Z_EXTADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  uint16 dstAddr;
#endif
#if defined ( MT_NWK_FUNC )  //NWK commands
  byte attr;
  byte index;
  byte dataLen;
  byte *dataPtr;
  uint32 channelList;
  byte databuf[SPI_RESP_LEN_NWK_DEFAULT + NWK_DEFAULT_GET_RESPONSE_LEN];
#if defined( ZDO_COORDINATOR )
	uint16 panId;
#else
  byte i,j;
#endif
#endif // MT_NWK_FUNC

  len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_NWK_DEFAULT;
	ret = (byte)ZSuccess;

  switch (cmd_id)
  {
#if defined( RTR_NWK )
    case SPI_CMD_NLME_PERMIT_JOINING_REQ:
      //The only information is PermitDuration
      ret = (byte)NLME_PermitJoiningRequest( *pData );
      break;
#endif

#if defined ( MT_NWK_FUNC )  //NWK commands
    case SPI_CMD_NWK_INIT:
      nwk_init( NWK_TaskID );
      break;

    case SPI_CMD_NLDE_DATA_REQ:
      //First read the DstAddr
      dstAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += sizeof( dstAddr );

      //Get the NSDU details
      dataLen = *pData++;
      dataPtr = pData;

      /* For now, skip a length of ZTEST_DEFAULT_DATA_LEN, instead of dataLen.
         In future ZTOOL releases the data buffer will be only as long as dataLen */

      //pData += dataLen;
      pData += ZTEST_DEFAULT_DATA_LEN;

      /* pData[0] = NSDUHandlde
         pData[1] = NSDUHandleOptions
         pData[3] = SecurityEnable
         pData[4] = DiscoverRoute
         pData[5] = RadiusCounter */

      ret = (byte)MT_Nwk_DataRequest( dstAddr, dataLen, dataPtr, pData[0],
                                      BUILD_UINT16( pData[2], pData[1] ),
                                      pData[3], pData[4], pData[5]);
      break;

#if defined( ZDO_COORDINATOR )
    case SPI_CMD_NLME_INIT_COORD_REQ:
			panId = BUILD_UINT16( pData[1], pData[0] );
			
			MT_ReverseBytes( &pData[2], 4 );
			channelList = osal_build_uint32( &pData[2], 4 );

			ret = (byte)NLME_NetworkFormationRequest( panId, channelList, pData[6], pData[7],
                                                      pData[8], pData[9] );
      break;
#endif  // ZDO

#if defined( RTR_NWK )
    case SPI_CMD_NLME_START_ROUTER_REQ:
      // NOTE: first two parameters are not used, see NLMEDE.h for details
      ret = (byte)NLME_StartRouterRequest( pData[0], pData[1], pData[2] );
    break;
#endif  // RTR

    case SPI_CMD_NLME_JOIN_REQ:
		  ret = (byte)NLME_JoinRequest( dummyExPANID, BUILD_UINT16( pData[1], pData[0] ), pData[2], pData[3] );
      if ( pData[3] & CAPINFO_RCVR_ON_IDLE )
      {
        // The receiver is on, turn network layer polling off.
        NLME_SetPollRate( 0 );
        NLME_SetQueuedPollRate( 0 );
        NLME_SetResponseRate( 0 );
      }
      break;

    case SPI_CMD_NLME_LEAVE_REQ:
      {
        NLME_LeaveReq_t req;
        // if extAddr is all zeros, it means null pointer..
        for( index = 0; ( ( index < Z_EXTADDR_LEN ) &&
                        ( pData[index] == 0 ) ) ; index++ );
        if ( index == Z_EXTADDR_LEN )
        {
          req.extAddr = NULL;
        }
        else
        {
          MT_ReverseBytes( pData, Z_EXTADDR_LEN );
          req.extAddr = pData;
        }
        pData += Z_EXTADDR_LEN;

        req.removeChildren = FALSE;
        req.rejoin         = FALSE;
        req.silent         = FALSE;
        ret = (byte)NLME_LeaveReq( &req );
      }
      break;

    case SPI_CMD_NLME_RESET_REQ:
      //Its a direct call to reset NWK
      ret = (byte)NLME_ResetRequest();
      break;

    case SPI_CMD_NLME_GET_REQ:
      attr = *pData++;
      index = *pData;
			databuf[0] = (byte)NLME_GetRequest( (ZNwkAttributes_t )attr, index, &databuf[1] );
      len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_NWK_DEFAULT + NWK_DEFAULT_GET_RESPONSE_LEN;
      MT_BuildAndSendZToolResponse( len, (SPI_RESPONSE_BIT | SPI_CMD_NLME_GET_REQ),
            (SPI_RESP_LEN_NWK_DEFAULT + NWK_DEFAULT_GET_RESPONSE_LEN), databuf );
      return;   // Don't return to this function

    case SPI_CMD_NLME_SET_REQ:
      ret = (byte)NLME_SetRequest( (ZNwkAttributes_t)pData[0], pData[1], &pData[2] );
      osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 1000 );
      break;

    case SPI_CMD_NLME_NWK_DISC_REQ:
      MT_ReverseBytes( pData, 4 );
      ret = (byte)NLME_NetworkDiscoveryRequest( osal_build_uint32( pData, 4 ), pData[4] );
      break;

#if !defined( ZDO_COORDINATOR )
    case SPI_CMD_NLME_ORPHAN_JOIN_REQ:
      // Channel list bit mask
      MT_ReverseBytes( pData, 4 );
      channelList = osal_build_uint32( pData, 4 );

      // Count number of channels
      j = attr = 0;
      for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
      {
        if ( channelList & (1 << i) )
        {
           j++;
           attr = i;
        }
      }

      // If only one channel specified...
      if ( j == 1 )
      {
        _NIB.scanDuration = pData[4];
        _NIB.nwkLogicalChannel = attr;
        _NIB.channelList = channelList;
        if ( !_NIB.CapabilityInfo )
          _NIB.CapabilityInfo = ZDO_Config_Node_Descriptor.CapabilityFlags;

        devState = DEV_NWK_ORPHAN;
        ret = (byte)NLME_OrphanJoinRequest( channelList, pData[4] );
      }
      else
        ret = ZNwkInvalidParam;
      break;
#endif  // !ZDO
	
#if defined (RTR_NWK)
    case SPI_CMD_NLME_ROUTE_DISC_REQ:
      ret = (byte)NLME_RouteDiscoveryRequest( BUILD_UINT16( pData[1], pData[0] ), pData[2] );
      break;
			
    case SPI_CMD_NLME_DIRECT_JOIN_REQ:
      MT_ReverseBytes( pData, 8 );
      ret = (byte)NLME_DirectJoinRequest( pData, pData[8] );
    break;
#endif	// RTR

#endif // MT_NWK_FUNC

    default:
      ret = (byte)ZUnsupportedMode;
      break;
  }

#if defined ( MT_NWK_FUNC )
	MT_SendSPIRespMsg( ret, cmd_id, len, SPI_RESP_LEN_NWK_DEFAULT );
#endif	
  (void)len;
  (void)ret;
}
Exemple #2
0
/*********************************************************************
 * @fn      MT_afCommandProcessing
 *
 * @brief
 *
 *   Process all the AF commands that are issued by test tool
 *
 * @param   cmd_id - Command ID
 * @param   len    - Length of received SPI data message
 * @param   data   - pointer to received SPI data message
 *
 * @return  none
 */
void MT_afCommandProcessing( uint16 cmd_id , byte len , byte *pData )
{
  byte i;
  endPointDesc_t *epDesc;
  uint8 af_stat = afStatus_FAILED;

  switch (cmd_id)
  {
    case SPI_CMD_AF_INIT:

      afInit();

      //No response for this command
      break;

    case SPI_CMD_AF_REGISTER:

      // First allocate memory for the AF structure epIntDesc
      epDesc = ( endPointDesc_t * )
                  osal_mem_alloc( sizeof( endPointDesc_t ) );

      if ( epDesc )
      {
        //Assemble the AF structures with the data received
        //First the Endpoint
        epDesc->simpleDesc = ( SimpleDescriptionFormat_t * )
                    osal_mem_alloc( sizeof( SimpleDescriptionFormat_t ) );

        if ( epDesc->simpleDesc )
        {
          epDesc->endPoint = *pData++;
          epDesc->simpleDesc->EndPoint = epDesc->endPoint;

          epDesc->task_id = &MT_TaskID;

          //Now for the simple description part
          epDesc->simpleDesc->AppProfId = BUILD_UINT16( pData[1],pData[0]);
          pData += sizeof( uint16 );
          epDesc->simpleDesc->AppDeviceId = BUILD_UINT16( pData[1],pData[0]);
          pData += sizeof( uint16 );
          epDesc->simpleDesc->AppDevVer = (*pData++) & AF_APP_DEV_VER_MASK ;
          epDesc->simpleDesc->Reserved = (*pData++) & AF_APP_FLAGS_MASK ;

          epDesc->simpleDesc->AppNumInClusters = *pData++;

          if (epDesc->simpleDesc->AppNumInClusters)
          {
            epDesc->simpleDesc->pAppInClusterList = (uint16 *)
            osal_mem_alloc(ZTEST_DEFAULT_PARAM_LEN*sizeof(uint16));

            for (i=0; i<ZTEST_DEFAULT_PARAM_LEN; i++)  {
              epDesc->simpleDesc->pAppInClusterList[i] = BUILD_UINT16(*pData, 0);
              pData++;
            }
          }
          else
          {
            pData += ZTEST_DEFAULT_PARAM_LEN;
          }

          epDesc->simpleDesc->AppNumOutClusters = *pData++;

          if (epDesc->simpleDesc->AppNumOutClusters)
          {
            epDesc->simpleDesc->pAppOutClusterList = (uint16 *)
            osal_mem_alloc(ZTEST_DEFAULT_PARAM_LEN*sizeof(uint16));

            for (i=0; i<ZTEST_DEFAULT_PARAM_LEN; i++)  {
              epDesc->simpleDesc->pAppOutClusterList[i] = BUILD_UINT16(*pData, 0);
              pData++;
            }
          }
          else
          {
            pData += ZTEST_DEFAULT_PARAM_LEN;
          }

          epDesc->latencyReq = (afNetworkLatencyReq_t)*pData;

          if ( afFindEndPointDesc( epDesc->endPoint ) == NULL )
          {
            af_stat = afRegister( epDesc );
          }
        }
        else
        {
          osal_mem_free( epDesc );
          af_stat = afStatus_MEM_FAIL;
        }
      }

      len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_AF_DEFAULT;
      MT_SendSPIRespMsg( af_stat, SPI_CMD_AF_REGISTER, len, SPI_RESP_LEN_AF_DEFAULT );

      break;

    case SPI_CMD_AF_SENDMSG:
    {
#if ( AF_KVP_SUPPORT )
      afKVPCommandFormat_t kvp;
      afAddOrSend_t addOrSend;
      byte frameType;
#else
      endPointDesc_t *epDesc;
      byte transId;
#endif
      afAddrType_t dstAddr;
      cId_t cId;
      byte txOpts, radius, srcEP;

#if ( AF_KVP_SUPPORT )
      frameType = *pData;
#endif
      pData++;
      txOpts = *pData++;
      radius = *pData++;

      // Fill the AF structures with the data received.
      dstAddr.addrMode = afAddr16Bit;
      dstAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;
      dstAddr.endPoint = *pData++;

      srcEP = *pData++;
      cId = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;
#if ( AF_KVP_SUPPORT )
      addOrSend = (afAddOrSend_t)(*pData++);
      kvp.TransSeqNumber = *pData++;
      kvp.CommandType = *pData++;
      kvp.AttribDataType = *pData++;
      kvp.AttribId = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;
      kvp.ErrorCode = *pData++;
      kvp.DataLength = *pData++;
      kvp.Data = pData;

      af_stat = afAddOrSendMessage( &dstAddr, srcEP, cId,
          addOrSend, frameType, &kvp.TransSeqNumber,
          kvp.CommandType, kvp.AttribDataType, kvp.AttribId, kvp.ErrorCode,
          kvp.DataLength, kvp.Data, (txOpts & ~AF_DISCV_ROUTE),
                                    (txOpts &  AF_DISCV_ROUTE), radius );
#else
      pData++;
      transId = *pData++;
      pData += 5;
      len = *pData++;
      epDesc = afFindEndPointDesc( srcEP );
      if ( epDesc == NULL )
      {
        af_stat = afStatus_INVALID_PARAMETER;
      }
      else
      {
        af_stat = AF_DataRequest( &dstAddr, epDesc, cId, len, pData,
                                  &transId, txOpts, radius );
      }
#endif

      len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_AF_DEFAULT;
      MT_SendSPIRespMsg( af_stat, SPI_CMD_AF_SENDMSG,
                             len, SPI_RESP_LEN_AF_DEFAULT );
    }
    break;
  }
}
Exemple #3
0
/*********************************************************************
 * @fn      MT_ZdoCommandProcessing
 *
 * @brief
 *
 *   Process all the ZDO commands that are issued by test tool
 *
 * @param   cmd_id - Command ID
 * @param   len    - Length of received SPI data message
 * @param   pData  - pointer to received SPI data message
 *
 * @return  void
 */
void MT_ZdoCommandProcessing( uint16 cmd_id , byte len , byte *pData )
{
  byte i;
  byte x;
  byte ret;
  byte attr;
  byte attr1;
  uint16 cID;
  uint16 shortAddr;
  uint16 uAttr;
  byte *ptr;
  byte *ptr1;
  zAddrType_t devAddr;
  zAddrType_t dstAddr;
  byte respLen;
#if defined ( ZDO_MGMT_NWKDISC_REQUEST )
  uint32 scanChans;
#endif
#if defined ( ZDO_USERDESCSET_REQUEST )
  UserDescriptorFormat_t userDesc;
#endif

  ret = UNSUPPORTED_COMMAND;
  len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_ZDO_DEFAULT;
  respLen = SPI_RESP_LEN_ZDO_DEFAULT;

  switch (cmd_id)
  {
    case SPI_CMD_ZDO_AUTO_ENDDEVICEBIND_REQ:
      i = *pData;    // Get the endpoint/interface
      ZDApp_SendEndDeviceBindReq( i );

      //Since function type is void, report a succesful operation to the test tool
      ret = ZSUCCESS;
      break;

    case SPI_CMD_ZDO_AUTO_FIND_DESTINATION_REQ:
      i = *pData;    // Get the endpoint/interface
      ZDApp_AutoFindDestination( i );
      //Since function type is void, report a succesful operation to the test tool
      ret = ZSUCCESS;
      break;

#if defined ( ZDO_NWKADDR_REQUEST )
    case SPI_CMD_ZDO_NWK_ADDR_REQ:
      // Copy and flip incoming 64-bit address
      pData = zdo_MT_MakeExtAddr( &devAddr, pData );

      ptr = (byte*)&devAddr.addr.extAddr;

      attr = *pData++;   // RequestType
      attr1 = *pData++;  // StartIndex
      x = *pData;
      ret = (byte)ZDP_NwkAddrReq( ptr, attr, attr1, x );
      break;
#endif

#if defined ( ZDO_IEEEADDR_REQUEST )
    case SPI_CMD_ZDO_IEEE_ADDR_REQ:
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += sizeof( shortAddr );
      attr = *pData++;   // RequestType
      attr1 = *pData++;  // StartIndex
      x = *pData;        // SecuritySuite
      ret = (byte)ZDP_IEEEAddrReq( shortAddr, attr, attr1, x );
      break;
#endif

#if defined ( ZDO_NODEDESC_REQUEST )
    case SPI_CMD_ZDO_NODE_DESC_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      attr = *pData;
      ret = (byte)ZDP_NodeDescReq( &devAddr, shortAddr, attr );
      break;
#endif

#if defined ( ZDO_POWERDESC_REQUEST )
    case SPI_CMD_ZDO_POWER_DESC_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      attr = *pData;
      ret = (byte)ZDP_PowerDescReq( &devAddr, shortAddr, attr );
      break;
#endif

#if defined ( ZDO_SIMPLEDESC_REQUEST )
    case SPI_CMD_ZDO_SIMPLE_DESC_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      attr = *pData++;  // endpoint/interface
      attr1 = *pData;   // SecuritySuite
      ret = (byte)ZDP_SimpleDescReq( &devAddr, shortAddr, attr, attr1 );
      break;
#endif

#if defined ( ZDO_ACTIVEEP_REQUEST )
    case SPI_CMD_ZDO_ACTIVE_EPINT_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      attr = *pData;  // SecuritySuite
      ret = (byte)ZDP_ActiveEPReq( &devAddr, shortAddr, attr );
      break;
#endif

#if defined ( ZDO_MATCH_REQUEST )
    case SPI_CMD_ZDO_MATCH_DESC_REQ:
      {
        uint16 inC[16], outC[16];

        // destination address
        devAddr.addrMode = Addr16Bit;
        devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
        pData += 2;

        // Network address of interest
        shortAddr = BUILD_UINT16( pData[1], pData[0] );
        pData += 2;

        uAttr = BUILD_UINT16( pData[1], pData[0] );   // Profile ID
        pData += 2;

        attr = *pData++;   // NumInClusters
        for (i=0; i<16; ++i)  {
          inC[i] = BUILD_UINT16(pData[1], pData[0]);
          pData += 2;
        }

        attr1 = *pData++;  // NumOutClusters
        for (i=0; i<16; ++i)  {
          outC[i] = BUILD_UINT16(pData[1], pData[0]);
          pData += 2;
        }

        i = *pData;        // SecuritySuite

        ret = (byte)ZDP_MatchDescReq( &devAddr, shortAddr, uAttr,
                                  attr, inC, attr1, outC, i );
      }
      break;
#endif

#if defined ( ZDO_COMPLEXDESC_REQUEST )
    case SPI_CMD_ZDO_COMPLEX_DESC_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      attr = *pData;  // SecuritySuite
      ret = (byte)ZDP_ComplexDescReq( &devAddr, shortAddr, attr );
      break;
#endif

#if defined ( ZDO_USERDESC_REQUEST )
    case SPI_CMD_ZDO_USER_DESC_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      attr = *pData;  // SecuritySuite
      ret = (byte)ZDP_UserDescReq( &devAddr, shortAddr, attr );
      break;
#endif

#if defined ( ZDO_ENDDEVICEBIND_REQUEST )
    case SPI_CMD_ZDO_END_DEV_BIND_REQ:
      //TODO: When ZTool supports 16 bits the code below will need to take it into account
      {
        uint16 inC[16], outC[16];

        // destination address
        devAddr.addrMode = Addr16Bit;
        devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
        pData += 2;

        // Network address of interest
        shortAddr = BUILD_UINT16( pData[1], pData[0] );
        pData += 2;

        x = *pData++;      // EPInt

        uAttr = BUILD_UINT16( pData[1], pData[0] );   // Profile ID
        pData += 2;

        attr = *pData++;   // NumInClusters
        for (i=0; i<16; ++i)  {
          inC[i] = BUILD_UINT16(pData[1], pData[0]);
          pData += 2;
        }

        attr1 = *pData++;  // NumOutClusters
        for (i=0; i<16; ++i)  {
          outC[i] = BUILD_UINT16(pData[1], pData[0]);
          pData += 2;
        }

        i = *pData;        // SecuritySuite

        ret = (byte)ZDP_EndDeviceBindReq( &devAddr, shortAddr, x, uAttr,
                                attr, inC, attr1, outC, i );
      }
      break;
#endif

#if defined ( ZDO_BIND_UNBIND_REQUEST )
    case SPI_CMD_ZDO_BIND_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      MT_ReverseBytes( pData, Z_EXTADDR_LEN );
      ptr = pData;       // SrcAddress
      pData += Z_EXTADDR_LEN;

      attr = *pData++;   // SrcEPInt

      cID = BUILD_UINT16( pData[1], pData[0]);      // ClusterID
      pData += 2;
      
      dstAddr.addrMode = *pData++;
      if ( NLME_GetProtocolVersion() == ZB_PROT_V1_0 )
        dstAddr.addrMode = Addr64Bit;
      
      MT_ReverseBytes( pData, Z_EXTADDR_LEN );
      if ( dstAddr.addrMode == Addr64Bit )
      {
        ptr1 = pData;      // DstAddress
        osal_cpyExtAddr( dstAddr.addr.extAddr, ptr1 );
      }
      else
      {
        dstAddr.addr.shortAddr = BUILD_UINT16( pData[0], pData[1] ); 
      }
      
      // The short address occupies lsb two bytes
      pData += Z_EXTADDR_LEN;

      
      attr1 = *pData++;  // DstEPInt

      x = *pData;        // SecuritySuite
     
#if defined ( REFLECTOR )
      if ( devAddr.addr.shortAddr == _NIB.nwkDevAddress )
      {
	ZDApp_BindReqCB( 0, &devAddr, ptr, attr, cID, &dstAddr, attr1, x );
        ret = ZSuccess;
      }
      else
#endif
      ret = (byte)ZDP_BindReq( &devAddr, ptr, attr, cID, &dstAddr, attr1, x );
      break;
#endif

#if defined ( ZDO_BIND_UNBIND_REQUEST )
    case SPI_CMD_ZDO_UNBIND_REQ:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      MT_ReverseBytes( pData, Z_EXTADDR_LEN );
      ptr = pData;       // SrcAddress
      pData += Z_EXTADDR_LEN;

      attr = *pData++;   // SrcEPInt

      cID = BUILD_UINT16( pData[1], pData[0]);      // ClusterID
      pData += 2;

      dstAddr.addrMode = *pData++;
      if ( NLME_GetProtocolVersion() == ZB_PROT_V1_0 )
        dstAddr.addrMode = Addr64Bit;
      MT_ReverseBytes( pData, Z_EXTADDR_LEN );
      if ( dstAddr.addrMode == Addr64Bit )
      {
        ptr1 = pData;      // DstAddress
        osal_cpyExtAddr( dstAddr.addr.extAddr, ptr1 );
      }
      else
      {
        dstAddr.addr.shortAddr = BUILD_UINT16( pData[0], pData[1] ); 
      }      
      pData += Z_EXTADDR_LEN;

      attr1 = *pData++;  // DstEPInt

      x = *pData;        // SecuritySuite

#if defined ( REFLECTOR )
      if ( devAddr.addr.shortAddr == _NIB.nwkDevAddress )
      {
        ZDApp_UnbindReqCB( 0, &devAddr, ptr, attr, cID, &dstAddr, attr1, x );
        ret = ZSuccess;
      }
      else
#endif
      {
        ret = (byte)ZDP_UnbindReq( &devAddr, ptr, attr, cID, &dstAddr, attr1, x );
      }
      break;
#endif

#if defined ( ZDO_MGMT_NWKDISC_REQUEST )
    case SPI_CMD_ZDO_MGMT_NWKDISC_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;
      scanChans = BUILD_UINT32( pData[3], pData[2], pData[1], pData[0] );
      ret = (byte)ZDP_MgmtNwkDiscReq( &devAddr, scanChans, pData[4], pData[5], false );
      break;
#endif

#if defined ( ZDO_MGMT_LQI_REQUEST )
    case SPI_CMD_ZDO_MGMT_LQI_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      ret = (byte)ZDP_MgmtLqiReq( &devAddr, pData[2], false );
      break;
#endif

#if defined ( ZDO_MGMT_RTG_REQUEST )
    case SPI_CMD_ZDO_MGMT_RTG_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      ret = (byte)ZDP_MgmtRtgReq( &devAddr, pData[2], false );
      break;
#endif

#if defined ( ZDO_MGMT_BIND_REQUEST )
    case SPI_CMD_ZDO_MGMT_BIND_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      ret = (byte)ZDP_MgmtBindReq( &devAddr, pData[2], false );
      break;
#endif

#if defined ( ZDO_MGMT_JOINDIRECT_REQUEST )
    case SPI_CMD_ZDO_MGMT_DIRECT_JOIN_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      MT_ReverseBytes( &pData[2], Z_EXTADDR_LEN );
      ret = (byte)ZDP_MgmtDirectJoinReq( &devAddr,
                               &pData[2],
                               pData[2 + Z_EXTADDR_LEN],
                               false );
      break;
#endif

#if defined ( ZDO_MGMT_LEAVE_REQUEST )
    case SPI_CMD_ZDO_MGMT_LEAVE_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      MT_ReverseBytes( &pData[2], Z_EXTADDR_LEN );
      ret = (byte)ZDP_MgmtLeaveReq( &devAddr, &pData[2], false );
      break;
#endif

#if defined ( ZDO_MGMT_PERMIT_JOIN_REQUEST )
    case SPI_CMD_ZDO_MGMT_PERMIT_JOIN_REQ:
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      ret = (byte)ZDP_MgmtPermitJoinReq( &devAddr, pData[2], pData[3], false );
      break;
#endif


#if defined ( ZDO_USERDESCSET_REQUEST )
    case SPI_CMD_ZDO_USER_DESC_SET:
      // destination address
      devAddr.addrMode = Addr16Bit;
      devAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // Network address of interest
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // User descriptor
      userDesc.len = *pData++;
      osal_memcpy( userDesc.desc, pData, userDesc.len );
      pData += 16;  // len of user desc

      ret =(byte)ZDP_UserDescSet( &devAddr, shortAddr, &userDesc, pData[0] );
      break;
#endif

#if defined ( ZDO_ENDDEVICE_ANNCE_REQUEST )
    case SPI_CMD_ZDO_END_DEV_ANNCE:
      // network address
      shortAddr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;

      // extended address
      ptr = pData;
      MT_ReverseBytes( ptr, Z_EXTADDR_LEN );
      pData += Z_EXTADDR_LEN;

      // security
      attr = *pData++;

      ret = (byte)ZDP_EndDeviceAnnce( shortAddr, ptr, *pData, attr );
      break;
#endif

#if defined (ZDO_SERVERDISC_REQUEST )
    case SPI_CMD_ZDO_SERVERDISC_REQ:
      
      // Service Mask
      uAttr = BUILD_UINT16( pData[1], pData[0] );
      pData += 2;
      attr = *pData++; // Security suite
      
      ret = (byte) ZDP_ServerDiscReq( uAttr, attr );
      break;
#endif
      
#if defined (ZDO_NETWORKSTART_REQUEST )
    case SPI_CMD_ZDO_NETWORK_START_REQ:
      ret = ZDApp_StartUpFromApp( ZDAPP_STARTUP_AUTO );
      break;
    
#endif
    
    default:
      break;
  }

  MT_SendSPIRespMsg( ret, cmd_id, len, respLen );
}