/*********************************************************************
 * @fn          ZDP_SimpleDescReq
 *
 * @brief       This builds and send a NWK_Simple_Desc_req
 *              message.  This function sends unicast message to the
 *              destination device.
 *
 * @param       dstAddr - destination address
 * @param       nwkAddr - 16 bit address
 * @param       epIntf - endpoint/interface
 * @param       SecurityEnable - Security Options
 *
 * @return      afStatus_t
 */
afStatus_t ZDP_SimpleDescReq( zAddrType_t *dstAddr, uint16 nwkAddr,
                                    byte endPoint, byte SecurityEnable )

{
  uint8 *pBuf, rtrn;

  (void)SecurityEnable;

  pBuf = zap_msg_allocate(5, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ,
                             (uint8)MT_ZDO_SIMPLE_DESC_REQ);
  if (NULL == pBuf)
  {
    return afStatus_MEM_FAIL;
  }

  pBuf[0] = LO_UINT16(dstAddr->addr.shortAddr);
  pBuf[1] = HI_UINT16(dstAddr->addr.shortAddr);
  pBuf[2] = LO_UINT16(nwkAddr);
  pBuf[3] = HI_UINT16(nwkAddr);
  pBuf[4] = endPoint;

  zapPhySend(zapAppPort, pBuf);
  rtrn = ZAP_SRSP_STATUS(pBuf);
  zap_msg_deallocate(&pBuf);

  return (afStatus_t)rtrn;
}
/**************************************************************************************************
 * @fn          ZDP_EndDeviceBindReq
 *
 * @brief       This builds and sends a End_Device_Bind_req message.
 *              This function sends a unicast message.
 *
 * input parameters
 *
 * @param       dstAddr - destination address
 * @param       LocalCoordinator - short address of local coordinator
 * @param       epIntf - Endpoint/Interface of Simple Desc
 * @param       ProfileID - Profile ID
 *
 *   The Input cluster list is the opposite of what you would think.
 *   This is the output cluster list of this device
 * @param       NumInClusters - number of input clusters
 * @param       InClusterList - input cluster ID list
 *
 *   The Output cluster list is the opposite of what you would think.
 *   This is the input cluster list of this device
 * @param       NumOutClusters - number of output clusters
 * @param       OutClusterList - output cluster ID list
 *
 * @param       SecurityEnable - Security Options
 *
 * output parameters
 *
 * None.
 *
 * @return      afStatus_t
 **************************************************************************************************
 */
afStatus_t ZDP_EndDeviceBindReq(zAddrType_t *dstAddr,
                                uint16 LocalCoordinator,
                                byte endPoint,
                                uint16 ProfileID,
                                byte NumInClusters, cId_t *InClusterList,
                                byte NumOutClusters, cId_t *OutClusterList,
                                byte SecurityEnable)
{
  const uint8 len = 17 + ((NumInClusters + NumOutClusters) * 2);
  uint8 *pBuf, *pPtr, cnt;

  (void)SecurityEnable;

  if ((Addr16Bit != dstAddr->addrMode) && (AddrBroadcast != dstAddr->addrMode))
  {
    return afStatus_INVALID_PARAMETER;
  }

  pBuf = zap_msg_allocate(len, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ,
                               (uint8)MT_ZDO_END_DEV_BIND_REQ);

  if (NULL == pBuf)
  {
    return afStatus_MEM_FAIL;
  }

  pPtr = pBuf;
  *pPtr++ = LO_UINT16(dstAddr->addr.shortAddr);
  *pPtr++ = HI_UINT16(dstAddr->addr.shortAddr);
  *pPtr++ = LO_UINT16(LocalCoordinator);
  *pPtr++ = HI_UINT16(LocalCoordinator);
  //(void)osal_memset(pPtr, 0, Z_EXTADDR_LEN);  // MT_ZDO ignores extended address.
  pPtr += Z_EXTADDR_LEN;
  *pPtr++ = endPoint;
  *pPtr++ = LO_UINT16(ProfileID);
  *pPtr++ = HI_UINT16(ProfileID);
  *pPtr++ = NumInClusters;
  for (cnt = 0; cnt < NumInClusters; cnt++)
  {
    *pPtr++ = LO_UINT16(*InClusterList);
    *pPtr++ = HI_UINT16(*InClusterList);
    InClusterList++;
  }
  *pPtr++ = NumOutClusters;
  for (cnt = 0; cnt < NumOutClusters; cnt++)
  {
    *pPtr++ = LO_UINT16(*OutClusterList);
    *pPtr++ = HI_UINT16(*OutClusterList);
    OutClusterList++;
  }

  zapPhySend(zapAppPort, pBuf);
  cnt = ZAP_SRSP_STATUS(pBuf);
  zap_msg_deallocate(&pBuf);

  return (afStatus_t)cnt;
}
/*********************************************************************
 * @fn          ZDO_RemoveRegisteredCB
 *
 * @brief       Call this function if you don't want to receive the
 *              incoming message.
 *
 * @param       taskID - Where the messages are being delivered.
 * @param       clusterID - What message?
 *
 * @return      ZSuccess - successful, ZFailure if not found
 */
ZStatus_t ZDO_RemoveRegisteredCB( uint8 taskID, uint16 clusterID )
{
  ZDO_MsgCB_t *pList;
  ZDO_MsgCB_t *pLast = NULL;

  pList = zdoMsgCBs;
  while ( pList )
  {
    if ( pList->taskID == taskID && pList->clusterID == clusterID )
    {
      uint8 *pBuf, rtrn;

      // Note that this could be sent AREQ to free up the host (but then no status.)
      if (NULL == (pBuf = zap_msg_allocate(2, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ,
                                              (uint8)MT_ZDO_MSG_CB_REMOVE)))
      {
        return ZMemError;
      }

      pBuf[0] = LO_UINT16(clusterID);
      pBuf[1] = HI_UINT16(clusterID);

      zapPhySend(zapAppPort, pBuf);
      rtrn = ZAP_SRSP_STATUS(pBuf);
      zap_msg_deallocate(&pBuf);

      if (ZSuccess != rtrn)
      {
        return (ZStatus_t)rtrn;
      }

      if ( pLast )
      {
        // remove this one from the linked list
        pLast->next = pList->next;
      }
      else if ( pList->next )
      {
        // remove the first one from the linked list
        zdoMsgCBs = pList->next;
      }
      else
      {
        // remove the only item from the list
        zdoMsgCBs = (ZDO_MsgCB_t *)NULL;
      }
      osal_mem_free( pList );
      return ( ZSuccess );
    }
    pLast = pList;
    pList = pList->next;
  }

  return ( ZFailure );
}
示例#4
0
/**************************************************************************************************
 * @fn          afRetrieve
 *
 * @brief       This function retrieves the data of a huge incoming message. On an failure during
 *              the retrieval, the incoming message is freed. Otherwise, the incoming message is
 *              forwarded to the corresponding task.
 *
 * input parameters
 *
 * @param       pMsg - Pointer to the incoming AF message.
 * @param       taskId - The task ID corresponding to the destination endpoint of the message.
 *
 * output parameters
 *
 * @param       pMsg->cmd.Data - The incoming message data buffer member is filled.
 *
 * @return      None.
 **************************************************************************************************
 */
static void afRetrieve(uint8 taskId, afIncomingMSGPacket_t *pMsg)
{
  #define ZAP_AF_RTV_MSG_HDR  7  // Retrieve message header length.
  #define ZAP_AF_RTV_RPY_HDR  2  // Retrieve-reply message header length.
  #define ZAP_AF_RTV_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_RTV_RPY_HDR)

  uint16 idx = 0, len = pMsg->cmd.DataLength;
  uint8 *pBuf, rtrn, tmpLen = 0;

  do {
    /* This trick to pre-decrement (with zero on the first pass) allows the while() test to
     * succeed and loop to send a zero data length message which will trigger the ZNP to
     * de-allocate the huge incoming message being held.
     */
    len -= tmpLen;
    idx += tmpLen;

    if (len > ZAP_AF_RTV_DAT_MAX)
    {
      tmpLen = ZAP_AF_RTV_DAT_MAX;
    }
    else
    {
      tmpLen = len;
    }

    if ((pBuf = zap_msg_allocate(ZAP_AF_RTV_MSG_HDR, ((uint8)MT_RPC_SYS_AF | MT_RPC_CMD_SREQ),
                                                             MT_AF_DATA_RETRIEVE)) == NULL)
    {
      rtrn = afStatus_MEM_FAIL;
      break;
    }

    pBuf[0] = BREAK_UINT32(pMsg->timestamp, 0);
    pBuf[1] = BREAK_UINT32(pMsg->timestamp, 1);
    pBuf[2] = BREAK_UINT32(pMsg->timestamp, 2);
    pBuf[3] = BREAK_UINT32(pMsg->timestamp, 3);
    pBuf[4] = LO_UINT16(idx);
    pBuf[5] = HI_UINT16(idx);
    pBuf[6] = tmpLen;
    zapPhySend(zapAppPort, pBuf);
    rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf);
    (void)osal_memcpy(pMsg->cmd.Data+idx, pBuf+ZAP_AF_RTV_RPY_HDR, tmpLen);
    zap_msg_deallocate(&pBuf);
  } while ((rtrn == afStatus_SUCCESS) && len);

  if (rtrn == afStatus_SUCCESS)
  {
    (void)osal_msg_send(taskId, (uint8 *)pMsg);
  }
  else
  {
    (void)osal_msg_deallocate((uint8 *)pMsg);
  }
}
/*********************************************************************
 * @fn      ZDOInitDevice
 *
 * @brief   Start the device in the network.  This function will read
 *   ZCD_NV_STARTUP_OPTION (NV item) to determine whether or not to
 *   restore the network state of the device.
 *
 * @param   startDelay - timeDelay to start device (in milliseconds).
 *      There is a jitter added to this delay:
 *              ((NWK_START_DELAY + startDelay)
 *              + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK))
 *
 * NOTE:    If the application would like to force a "new" join, the
 *          application should set the ZCD_STARTOPT_DEFAULT_NETWORK_STATE
 *          bit in the ZCD_NV_STARTUP_OPTION NV item before calling
 *          this function. "new" join means to not restore the network
 *          state of the device. Use zgWriteStartupOptions() to set these
 *          options.
 *
 * @return
 *    ZDO_INITDEV_RESTORED_NETWORK_STATE  - The device's network state was
 *          restored.
 *    ZDO_INITDEV_NEW_NETWORK_STATE - The network state was initialized.
 *          This could mean that ZCD_NV_STARTUP_OPTION said to not restore, or
 *          it could mean that there was no network state to restore.
 *    ZDO_INITDEV_LEAVE_NOT_STARTED - Before the reset, a network leave was issued
 *          with the rejoin option set to TRUE.  So, the device was not
 *          started in the network (one time only).  The next time this
 *          function is called it will start.
 *    0xFF for failure.
 */
uint8 ZDOInitDevice(uint16 startDelay)
{
  uint8 *pBuf;
#if !ZAP_ZDO_STARTUP_AREQ
  uint8 rtrn;
#endif

  (void)startDelay;  // ZNP MT_ZDO_STARTUP_FROM_APP processing forces delay 0.

  zb_GetDeviceInfo(ZB_INFO_DEV_STATE, &devState);
  if ((DEV_HOLD != devState) && (DEV_INIT != devState) && (DEV_NWK_ORPHAN != devState))
  {
    return FAILURE;
  }

#if ZAP_ZDO_STARTUP_AREQ
  pBuf = zap_msg_allocate(0, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_AREQ,
                             (uint8)MT_ZDO_STARTUP_FROM_APP);
#else
  pBuf = zap_msg_allocate(0, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ,
                             (uint8)MT_ZDO_STARTUP_FROM_APP);
#endif

  if (NULL == pBuf)
  {
    return 0xFF;
  }

  zapPhySend(zapAppPort, pBuf);
#if !ZAP_ZDO_STARTUP_AREQ
  if (ZSuccess == (rtrn = ZAP_SRSP_STATUS(pBuf)))
#endif
  // Need to locally enter the discovery state to holdoff calls to ZDOInitDevice() until the ZAP
  // monitoring task requests the actual ZNP state.
  devState = DEV_NWK_DISC;
  zap_msg_deallocate(&pBuf);

  // Joining can take some time - especially with > 1 scan channel.
  if (ZSuccess != osal_start_timerEx(zapTaskId, ZAP_APP_TMR_EVT, ZAP_APP_JOIN_DLY))
  {
    (void)osal_set_event(zapTaskId, ZAP_APP_TMR_EVT);
  }

#if ZAP_ZDO_STARTUP_AREQ
  // Made into an AREQ after empirical results showed > 400 msec delay on SRSP.
#if ZAP_NV_RESTORE
  return ZDO_INITDEV_RESTORED_NETWORK_STATE;
#else
  return ZDO_INITDEV_NEW_NETWORK_STATE;
#endif
#else
  return rtrn;
#endif
}
/**************************************************************************************************
 * @fn          ZDP_MatchDescReq
 *
 * @brief       This builds and send a Match_Desc_req message.  This
 *              function sends a broadcast or unicast message
 *              requesting the list of endpoint/interfaces that
 *              match profile ID and cluster IDs.
 *
 * input parameters
 *
 * @param       dstAddr - destination address
 * @param       ProfileID - Profile ID
 * @param       NumInClusters - number of input clusters
 * @param       InClusterList - input cluster ID list
 * @param       NumOutClusters - number of output clusters
 * @param       OutClusterList - output cluster ID list
 * @param       SecurityEnable - Security Options
 *
 * output parameters
 *
 * None.
 *
 * @return      afStatus_t
 **************************************************************************************************
 */
afStatus_t ZDP_MatchDescReq(zAddrType_t *dstAddr, uint16 nwkAddr,
                            uint16 ProfileID,
                            byte NumInClusters, cId_t *InClusterList,
                            byte NumOutClusters, cId_t *OutClusterList,
                            byte SecurityEnable)
{
  const uint8 len = 8 + ((NumInClusters + NumOutClusters) * 2);
  uint8 *pBuf, *pPtr, cnt;

  (void)SecurityEnable;

  if ((Addr16Bit != dstAddr->addrMode) && (AddrBroadcast != dstAddr->addrMode))
  {
    return afStatus_INVALID_PARAMETER;
  }

  pBuf = zap_msg_allocate(len, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ,
                               (uint8)MT_ZDO_MATCH_DESC_REQ);

  if (NULL == pBuf)
  {
    return afStatus_MEM_FAIL;
  }

  pPtr = pBuf;
  *pPtr++ = LO_UINT16(dstAddr->addr.shortAddr);
  *pPtr++ = HI_UINT16(dstAddr->addr.shortAddr);
  *pPtr++ = LO_UINT16(nwkAddr);
  *pPtr++ = HI_UINT16(nwkAddr);
  *pPtr++ = LO_UINT16(ProfileID);
  *pPtr++ = HI_UINT16(ProfileID);
  *pPtr++ = NumInClusters;
  for (cnt = 0; cnt < NumInClusters; cnt++)
  {
    *pPtr++ = LO_UINT16(*InClusterList);
    *pPtr++ = HI_UINT16(*InClusterList);
    InClusterList++;
  }
  *pPtr++ = NumOutClusters;
  for (cnt = 0; cnt < NumOutClusters; cnt++)
  {
    *pPtr++ = LO_UINT16(*OutClusterList);
    *pPtr++ = HI_UINT16(*OutClusterList);
    OutClusterList++;
  }

  zapPhySend(zapAppPort, pBuf);
  cnt = ZAP_SRSP_STATUS(pBuf);
  zap_msg_deallocate(&pBuf);

  return (afStatus_t)cnt;
}
示例#7
0
/**************************************************************************************************
 * @fn          afStore
 *
 * @brief       This function stores a huge outgoing message data buffer on the ZNP.
 *
 * input parameters
 *
 * @param       buf - Pointer to the message data buffer.
 * @param       len - The length of the message data buffer 'buf'.
 *
 * output parameters
 *
 * None.
 *
 * @return      The AF-Status of storing the message data on the ZNP.
 **************************************************************************************************
 */
static afStatus_t afStore(uint8 *buf, uint16 len)
{
  #define ZAP_AF_STO_MSG_HDR  3
  #define ZAP_AF_STO_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_STO_MSG_HDR)
  uint8 *pBuf;
  uint16 idx = 0;
  uint8 tmpLen = 0;
  afStatus_t rtrn;

  do {
    /* This trick to pre-decrement (with zero on the first pass) allows the while() test to
     * succeed and loop to send a zero data length message which will trigger the ZNP to send the
     * accumulated data OTA in an AF_DataRequest().
     */
    len -= tmpLen;
    idx += tmpLen;

    if (len > ZAP_AF_STO_DAT_MAX)
    {
      tmpLen = ZAP_AF_STO_DAT_MAX;
    }
    else
    {
      tmpLen = len;
    }

    if ((pBuf = zap_msg_allocate((uint8)(tmpLen + ZAP_AF_STO_MSG_HDR),
                                 (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_SREQ,
                                 (uint8)MT_AF_DATA_STORE)) == NULL)
    {
      rtrn = afStatus_MEM_FAIL;
      break;
    }

    pBuf[0] = LO_UINT16(idx);
    pBuf[1] = HI_UINT16(idx);
    pBuf[2] = tmpLen;
    (void)osal_memcpy(pBuf+3, buf+idx, tmpLen);
    zapPhySend(zapAppPort, pBuf);
    rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf);
    zap_msg_deallocate(&pBuf);
  } while ((rtrn == afStatus_SUCCESS) && len);

  return rtrn;
}
示例#8
0
/**************************************************************************************************
 * @fn      AF_DataRequest
 *
 * @brief   API definition to invoke AF_DataRequest on the ZNP.
 *
 * input parameters
 *
 * @param  *dstAddr - Full ZB destination address: Nwk Addr + End Point.
 * @param  *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
 * @param   cID - A valid cluster ID as specified by the Profile.
 * @param   len - Number of bytes of data pointed to by next param.
 * @param  *buf - A pointer to the data bytes to send.
 * @param  *transID - A pointer to a byte which can be modified and which will
 *                    be used as the transaction sequence number of the msg.
 * @param   options - Valid bit mask of Tx options.
 * @param   radius - Normally set to AF_DEFAULT_RADIUS.
 *
 * output parameters
 *
 * @param  *transID - Incremented by one if the return value is success.
 *
 * @return  afStatus_t per declaration.
 **************************************************************************************************
 */
afStatus_t AF_DataRequest(afAddrType_t *dstAddr, endPointDesc_t *srcEP,
                          uint16 cID, uint16 len, uint8 *buf, uint8 *transID,
                          uint8 options, uint8 radius)
{
  #define ZAP_AF_REQ_MSG_HDR  20
  #define ZAP_AF_REQ_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_REQ_MSG_HDR)
  uint8 *pBuf;

#if !ZAP_AF_DATA_REQ_AREQ
  afStatus_t rtrn;

#if ZAP_AF_DATA_REQ_FRAG
  if (len > ZAP_AF_REQ_DAT_MAX)
  {
    pBuf = zap_msg_allocate(ZAP_AF_REQ_MSG_HDR, (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_SREQ,
                                                (uint8)MT_AF_DATA_REQUEST_EXT);
  }
  else
#endif
  {
    pBuf = zap_msg_allocate((uint8)(len + ZAP_AF_REQ_MSG_HDR),
                            (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_SREQ,
                            (uint8)MT_AF_DATA_REQUEST_EXT);
  }
#else
  pBuf = zap_msg_allocate((uint8)(len + ZAP_AF_REQ_MSG_HDR),
                          (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_AREQ,
                          (uint8)MT_AF_DATA_REQUEST_EXT);
#endif

  if (NULL == pBuf)
  {
    return afStatus_MEM_FAIL;
  }

  *pBuf++ = dstAddr->addrMode;

  if (dstAddr->addrMode == afAddr64Bit)
  {
    (void)osal_memcpy(pBuf, dstAddr->addr.extAddr, Z_EXTADDR_LEN);
  }
  else
  {
    pBuf[0] = LO_UINT16(dstAddr->addr.shortAddr);
    pBuf[1] = HI_UINT16(dstAddr->addr.shortAddr);
  }
  pBuf += Z_EXTADDR_LEN;

  *pBuf++ = dstAddr->endPoint;
#if defined INTER_PAN
  *pBuf++ = LO_UINT16(dstAddr->panId);
  *pBuf++ = HI_UINT16(dstAddr->panId);
#else
  *pBuf++ = 0;
  *pBuf++ = 0;
#endif
  *pBuf++ = srcEP->endPoint;
  *pBuf++ = LO_UINT16(cID);
  *pBuf++ = HI_UINT16(cID);
  *pBuf++ = *transID;
  (*transID)++;
  *pBuf++ = options;
  *pBuf++ = radius;
  *pBuf++ = LO_UINT16(len);
  *pBuf++ = HI_UINT16(len);

#if ZAP_AF_DATA_REQ_FRAG
  if (len <= ZAP_AF_REQ_DAT_MAX)
#endif
  {
    (void)osal_memcpy(pBuf, buf, len);
  }

  pBuf -= ZAP_AF_REQ_MSG_HDR;
  zapPhySend(zapAppPort, pBuf);
#if !ZAP_AF_DATA_REQ_AREQ
  rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf);
#endif
  zap_msg_deallocate(&pBuf);

#if ZAP_AF_DATA_REQ_FRAG
  if ((len > ZAP_AF_REQ_DAT_MAX) && (rtrn == afStatus_SUCCESS))
  {
    rtrn = afStore(buf, len);
  }
#endif

#if ZAP_AF_DATA_REQ_AREQ
  return SUCCESS;
#else
  return rtrn;
#endif
}