This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

WEBENCH® Tools/CC2652R: some improvement for z-stack's zcl.c

Part Number: CC2652R
Other Parts Discussed in Thread: Z-STACK

Tool/software: WEBENCH® Design Tools

It is known that the ZCL of z-stack don't support manufacture code, don't support specific-command filter. Some zigbee device who is base on zstack can receives and executes specific-command whose cluster ID and command-ID can't be lookup by ZDP-Simple-Desc-req and ZCL-DISCOVER-CMDS.

1st, add this function in zcl.c

/*********************************************************************
 * @fn      zcl_matchClusterId
 *
 * @brief   Match if cluster ID is supported by current EP, add by
 *          Luoyiming, 2019-10-20
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  TRUE if cluster ID is supported by EP, FALSE ont support
 */
uint8_t zcl_matchClusterId( zclIncoming_t *pInMsg )
{
  uint8_t free = FALSE;
  uint8_t match = FALSE;
  SimpleDescriptionFormat_t *sDesc = NULL;

  free = afFindSimpleDesc( &sDesc, pInMsg->msg->endPoint );
  if ( sDesc )
  {
    uint8_t numClusters = 0;
    cId_t *pClusterList = NULL;

    if ( zcl_ServerCmd(pInMsg->hdr.fc.direction) ) // match if InCluster is support by sever.
    {
      numClusters = sDesc->AppNumInClusters;
      pClusterList = sDesc->pAppInClusterList;
    }
    else if ( zcl_ClientCmd(pInMsg->hdr.fc.direction) )// match if OutCluster is support by client.
    {
      numClusters = sDesc->AppNumOutClusters;
      pClusterList = sDesc->pAppOutClusterList;
    }

    //match incoming message cluster with EP's SimpleDesc.
    if ( ( pClusterList != NULL ) && ( numClusters ) )
    {
      uint8_t n;
      for ( n = 0; n < numClusters; n++ )
      {
        if ( pInMsg->msg->clusterId == pClusterList[n] )
        {
          match = TRUE;
          break;
        }
      }
    }
  }
  if ( free && sDesc )
  {
    zcl_mem_free( sDesc );
  }
  return match;
}

2nd, add "zclGenUnsupportCallback" into  zcl_general.c to execute manufacture code command. This function can also collect wrong command receiving.

static ZStatus_t (*zclGenUnsupportCallback)(zclIncoming_t* pInMsg) = NULL;

/*********************************************************************
 * @fn      zclGeneral_RegisterUnsupportCallback
 *
 * @brief   Register an callback for unsupport endpoint
 *
 * @param   callback - pointer to the callback record.
 *
 * @return  NONE
 */
void zclGeneral_RegisterUnsupportCallback( ZStatus_t (*callback)(zclIncoming_t*pInMsg) )
{
  // Register as a ZCL Plugin
  if ( zclGenPluginRegisted == FALSE )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_GEN_BASIC,
                        ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC,
                        zclGeneral_HdlIncoming );

#ifdef ZCL_SCENES
    // Initialize the Scenes Table
    zclGeneral_ScenesInit();
#endif // ZCL_SCENES

    zclGenPluginRegisted = TRUE;
  }

  zclGenUnsupportCallback = callback;
}

3rd, fix function "zclGeneral_HdlIncoming"

  if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
  {
    // Is this a manufacturer specific command?
    stat = ZFailure;
    if ( pInMsg->hdr.fc.manuSpecific == 0 )
    {
      if ( zcl_matchClusterId( pInMsg ) ) //match cluster ID support.
      {
#ifdef ZCL_DISCOVER
        zclCommandRec_t cmdRec;
        if( TRUE == zclFindCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId,
                                  pInMsg->hdr.commandID, &cmdRec ) )
        {
          if( ( zcl_ServerCmd(pInMsg->hdr.fc.direction) && (cmdRec.flag & CMD_DIR_SERVER_RECEIVED) ) ||
             ( zcl_ClientCmd(pInMsg->hdr.fc.direction) && (cmdRec.flag & CMD_DIR_CLIENT_RECEIVED) ) )
          {
            stat = zclGeneral_HdlInSpecificCommands( pInMsg );
          }
        }
#else
        stat = zclGeneral_HdlInSpecificCommands( pInMsg );
#endif
      }
    }
    else
    {
      // We don't support any manufacturer specific command.
      stat = ZFailure;
    }
    //execute unsupported command,luoyiming fix at 2019-07-20
    if( stat == ZFailure)
    {
      if( zclGenUnsupportCallback )
      {
        stat = zclGenUnsupportCallback( pInMsg );
      }
    }
  }

4th, This model can be used in any other zlc plugin, such as zcl_ss, zcl_se, zcl_hvac.