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.

CC2652R: Attribute "ATTRID_CLUSTER_REVISION" is before than other optional attributes when "zcl_config.c" is generated by sysconfig.

Part Number: CC2652R
Other Parts Discussed in Thread: SYSCONFIG, CC2652P, SIMPLELINK-CC13X2-26X2-SDK

In this condition, ZCL_Discover_Attribute command can't response other optional attributes. 

It should be fixed like this

static uint8_t zclFindNextAttrRec( uint8_t endpoint, uint16_t clusterID, uint16_t manuCode, uint8_t direction,
                                   uint16_t *attrId, zclAttrRec_t *pAttr, uint8_t *startIdx, bool cmpAttr )
{
  zclAttrRecsList *pRec = zclFindAttrRecsList( endpoint );
  uint8_t attrDir;
  uint8_t matchManuCode = FALSE;

  //match manufacturer-cluster, fixed by luoyiming 2020-01-08
  if ( ( clusterID < 0xFC00 ) && ( manuCode != 0 ) )
  {
    matchManuCode = TRUE;
  }

  if ( pRec != NULL )
  {
    uint16_t x;

    for ( x = *startIdx; x < pRec->numAttributes; x++ )
    {
      // match manufacturer attribute at first, luoyiming 2020-01-08
      if ( ( pRec->attrs[x].attr.accessControl & ACCESS_MANU_ATTR ) && matchManuCode == FALSE )
      {
        continue;
      }
      if ( pRec->attrs[x].clusterID == clusterID )
      {
        // compare attrId or not, fixed by luoyiming 2021-07-04
        if( (pRec->attrs[x].attr.attrId >= *attrId) || (cmpAttr == false) )
        {
          // also make sure direction is right
          attrDir = (pRec->attrs[x].attr.accessControl & ACCESS_CLIENT) ? 1 : 0;
          if ( (attrDir == direction) || (pRec->attrs[x].attr.accessControl & ACCESS_GLOBAL) )
          {
            // return attribute and found attribute ID
            *pAttr = pRec->attrs[x];
            *attrId = pAttr->attr.attrId;
            *startIdx = x; // Update startIdx for next loop, luoyiming 2020-07-11

            return ( TRUE ); // EMBEDDED RETURN
          }
        }
      }
    }
  }

  return ( FALSE );
}


uint8_t zclFindAttrRecEx( uint8_t endpoint, uint16_t clusterID, uint16_t manuCode, uint8_t direction,
                          uint16_t attrId, zclAttrRec_t *pAttr, uint8_t *idx )
{
  uint8_t x;
  zclAttrRecsList *pRec = zclFindAttrRecsList( endpoint );
  uint8_t matchManuCode = FALSE;

  // match manufacturer-cluster, fixed by luoyiming 2020-01-08
  // don't execute for wildcard manufacturer ID, luoyiming add at 2020-01-09
  if ( ( clusterID < 0xFC00 ) && ( manuCode != 0 ) && ( manuCode != 0xFFFF ) )
  {
    matchManuCode = TRUE;
  }

  if ( pRec != NULL )
  {
    for ( x = 0; x < pRec->numAttributes; x++ )
    {
      // match manufacturer attribute at first, luoyiming 2020-01-08
      if ( ( pRec->attrs[x].attr.accessControl & ACCESS_MANU_ATTR ) && matchManuCode == FALSE )
      {
        continue;
      }
      if ( pRec->attrs[x].clusterID == clusterID && pRec->attrs[x].attr.attrId == attrId )
      {
        //match direction, fixed by luoyiming 2019-11-16
        if ( (pRec->attrs[x].attr.accessControl & ACCESS_GLOBAL) ||
             ( GET_BIT( &(pRec->attrs[x].attr.accessControl), ACCESS_CONTROL_MASK ) == direction ) )
        {
          *pAttr = pRec->attrs[x];
          // return the attribute's index, luoyiming 2021-07-04
          if( idx != NULL )
          {
            *idx = x;
          }
          return ( TRUE ); // EMBEDDED RETURN
        }
      }
    }
  }

  return ( FALSE );
}


static uint8_t zclProcessInDiscAttrs( zclIncoming_t *pInMsg )
{
  zclDiscoverAttrsCmd_t *pDiscoverCmd;
  zclAttrRec_t attrRec;
  uint16_t attrID;
  uint8_t numAttrs = 0;
  uint8_t i;
  uint8_t startIdx = 0;
  uint8_t index;
  bool findAttr = true;

  pDiscoverCmd = (zclDiscoverAttrsCmd_t *)pInMsg->attrCmd;

  // find the start attribute's index, luoyiming 2021-07-04
  attrID = pDiscoverCmd->startAttr;
  if ( !zclFindAttrRecEx( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                          pInMsg->hdr.fc.direction,  attrID, &attrRec, &startIdx ) )
  {
    // current attribute is not found, find the next valid attribute, louyiming 2021-07-04
    if ( !zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                              pInMsg->hdr.fc.direction, &attrID, &attrRec, &startIdx, true ) )
    {
      // attribute is not found, louyiming 2021-07-04
      findAttr = false;
    }
  }
  index = startIdx;

  if( findAttr ) // If attribute is not found, set total number is 0. louyiming 2021-07-04
  {
    // Find out the number of attributes supported within the specified range
    for ( i = 0; i < pDiscoverCmd->maxAttrIDs; i++ )
    {
      // finds the next attribute on this endpoint/cluster after the range.
      // attributes must be in numerical order in the list.
      if ( !zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                                pInMsg->hdr.fc.direction, &attrID, &attrRec, &index, false ) )
      {
        break;
      }
      index += 1; // update startIdx for next loop, luoyiming fixed at 2020-07-22
    }

    numAttrs = i;  // store range of attributes in buffer
  }

    // Process message for either attributes or extended attributes
  if ( pInMsg->hdr.commandID == ZCL_CMD_DISCOVER_ATTRS )
  {
    zclProcessInDiscAttrsCmd( pInMsg, pDiscoverCmd, numAttrs, startIdx );
  }
  else if ( pInMsg->hdr.commandID == ZCL_CMD_DISCOVER_ATTRS_EXT )
  {
    zclProcessInDiscAttrsExtCmd( pInMsg, pDiscoverCmd, numAttrs, startIdx );
  }

  return TRUE;
}

static void zclProcessInDiscAttrsCmd( zclIncoming_t *pInMsg, zclDiscoverAttrsCmd_t *pDiscoverCmd, uint8_t numAttrs, uint8_t startIdx )
{
  zclDiscoverAttrsRspCmd_t *pDiscoverRsp;
  uint8_t discComplete = TRUE;
  zclAttrRec_t attrRec;
  uint16_t attrID;
  uint8_t i;

  // Allocate space for the response command
  pDiscoverRsp = (zclDiscoverAttrsRspCmd_t *)zcl_mem_alloc( sizeof (zclDiscoverAttrsRspCmd_t)
                                                          + sizeof ( zclDiscoverAttrInfo_t ) * numAttrs );
  if ( pDiscoverRsp == NULL )
  {
    return; // EMBEDDED RETURN
  }

  if ( numAttrs != 0 )
  {
    for ( i = 0; i < numAttrs; i++ )
    {
      if ( !zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                                pInMsg->hdr.fc.direction, &attrID, &attrRec, &startIdx, false ) )
      {
        break; // should not happen, as numAttrs already calculated
      }

      pDiscoverRsp->attrList[i].attrID = attrRec.attr.attrId;
      pDiscoverRsp->attrList[i].dataType = attrRec.attr.dataType;
      startIdx += 1; // update startIdx for next loop, luoyiming fixed at 2020-07-22
    }

    // Are there more attributes to be discovered?
    if ( zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                             pInMsg->hdr.fc.direction, &attrID, &attrRec, &startIdx, false ) )
    {
      discComplete = FALSE;
    }
  }

  pDiscoverRsp->discComplete = discComplete;
  pDiscoverRsp->numAttr = numAttrs;

  zcl_SendDiscoverAttrsRspCmd( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
                               pInMsg->msg->clusterId, pDiscoverRsp, !(pInMsg->hdr.fc.direction),
                               true, pInMsg->hdr.manuCode, pInMsg->hdr.transSeqNum );
  zcl_mem_free( pDiscoverRsp );

  return;
}

static void zclProcessInDiscAttrsExtCmd( zclIncoming_t *pInMsg, zclDiscoverAttrsCmd_t *pDiscoverCmd, uint8_t numAttrs, uint8_t startIdx )
{
  zclDiscoverAttrsExtRsp_t *pDiscoverExtRsp;
  uint8_t discComplete = TRUE;
  zclAttrRec_t attrRec;
  uint16_t attrID;
  uint8_t i;

    // Allocate space for the response command
  pDiscoverExtRsp = (zclDiscoverAttrsExtRsp_t *)zcl_mem_alloc( sizeof (zclDiscoverAttrsExtRsp_t)
                                                         + sizeof ( zclExtAttrInfo_t ) * numAttrs );
  if ( pDiscoverExtRsp == NULL )
  {
    return; // EMBEDDED RETURN
  }


  if ( numAttrs != 0 )
  {
    for ( i = 0; i < numAttrs; i++ )
    {
      if ( !zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                                pInMsg->hdr.fc.direction, &attrID, &attrRec, &startIdx, false ) )
      {
        break; // Should not happen, as numAttrs already calculated
      }

      pDiscoverExtRsp->aExtAttrInfo[i].attrID = attrRec.attr.attrId;
      pDiscoverExtRsp->aExtAttrInfo[i].attrDataType = attrRec.attr.dataType;
      pDiscoverExtRsp->aExtAttrInfo[i].attrAccessControl = attrRec.attr.accessControl & ACCESS_CONTROLEXT_MASK;
      startIdx += 1; // update startIdx for next loop, luoyiming fixed at 2020-07-22
    }

    // Are there more attributes to be discovered?
    if ( zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.manuCode,
                             pInMsg->hdr.fc.direction, &attrID, &attrRec, &startIdx, false ) )
    {
      discComplete = FALSE;
    }
  }

  pDiscoverExtRsp->discComplete = discComplete;
  pDiscoverExtRsp->numAttr = numAttrs;

  zcl_SendDiscoverAttrsExtRsp( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
                               pInMsg->msg->clusterId, pDiscoverExtRsp, !(pInMsg->hdr.fc.direction),
                               true, pInMsg->hdr.manuCode, pInMsg->hdr.transSeqNum );

  zcl_mem_free( pDiscoverExtRsp );

  return;
}


















The idea is that:

1,  Find the index of start attribute of zcl-DIsc-Attr command in device's attribute table. If the start attribute is not valid in attribute table, find another attribute whose attribute-ID is larger than it.

2,  Generate the zcl-Disc-Attr Response from start-attribute's index to the end of attribute table.