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.

CC2652P: make z-stack to support manufacturer clusters and manufacturer attributes

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

First, make z-stack to support manufacturer attribute.

Manufacturer flag can be added into "accessControl" of "zclAttribute_t", because one device has only one manufacturer code. The "ACCESS_CONTROL_COMMAND" flag is not used in z-stack, and we can use it to mark "manufacturer code" flag.

...
#define ACCESS_CONTROL_COMMAND                          0x08
...
// Access Control for manufacturer-specific attribute, fixed by luoyiming 2020-01-08
#define ACCESS_MANU_ATTR                                ACCESS_CONTROL_COMMAND
...

So the attribute-access function in z-stack should be fixed to supports "ACCESS_MANU_ATTR". In "zcl.h" and "zcl.c", define a new function "zclFindAttrRecEx" to instead of "zclFindAttrRec"

#define zclFindAttrRec(ep,cId,attr,rec)  zclFindAttrRecEx(ep,cId,0,0,attr,rec,NULL)

extern uint8_t zclFindAttrRecEx( uint8_t endpoint, uint16_t realClusterID, uint16_t manuCode, uint8_t direction,
                                 uint16_t attrId, zclAttrRec_t *pAttr, uint8_t *idx );

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 );
}

Function "zclFindNextAttrRec" also needs to be fixed to supports manufacturer-code

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 );
}

define a new function in "zcl.c" ti support manufacturer code

uint8_t zcl_MatchClusterManuCode( uint16_t clusterID, uint16_t manuCode )
{
  uint16_t node_manuCode;

  // no manufacturer code processing
  if ( manuCode == 0 && clusterID < 0xFC00 )
  {
    return TRUE;
  }

  // get local manufacturer code for manufacturer-specific indication, luoyiming 2020-01-15
  node_manuCode = zcl_GetManuCode( clusterID );
  // manufacturer code is valid, match with node's manu-code or wildcard manu-code, luoyiming 2020-01-09
  if ( ( node_manuCode != 0 ) && ( node_manuCode == manuCode || 0xFFFF == manuCode ) )
  {
    return TRUE;
  }

  return FALSE;
}

Add manufacturer-code processing in "zcl_ProcessMessageMSG"

zclProcMsgStatus_t zcl_ProcessMessageMSG( afIncomingMSGPacket_t *pkt )
{
 

  // Is this a foundation type message
  if ( !interPanMsg && zcl_ProfileCmd( inMsg.hdr.fc.type ) )
  {
    if ( CMD_REQ_IND( inMsg.hdr.commandID ) &&
         ( inMsg.hdr.fc.manuSpecific ) && // add by luoyiming 2019-5-19
         ( !zcl_MatchClusterManuCode( inMsg.msg->clusterId, inMsg.hdr.manuCode )) ) // manu code match cluster fail, fix at 2019-10-20
    {
      // We don't support any manufacturer specific command
      status = ZCL_STATUS_UNSUP_MANU_GENERAL_COMMAND;
    }

...
  }

}

  • Make "bdb_reporting.c" to supports manufacturer code. 

    Add struct-members "manuCode" and "direction" to every struct which has "cluster" and "attrID" in "bdb_reporting.c"

    typedef struct
    {
      uint8_t endpoint;
      uint8_t direction;  //add by luoyiming, 2020-01-07
      uint16_t cluster;
      uint16_t manuCode;  //add by luoyiming, 2019-10-21
      uint16_t attrID;
      uint16_t minReportInt;
      uint16_t maxReportInt;
      uint16_t defaultMinReportInt;
      uint16_t defaultMaxReportInt;
      uint8_t  reportableChange[BDBREPORTING_MAX_ANALOG_ATTR_SIZE];
      uint8_t  defaultReportableChange[BDBREPORTING_MAX_ANALOG_ATTR_SIZE];
    } bdbReportAttrCfgData_t;
    
    typedef struct
    {
      uint8_t flags;
      uint8_t  endpoint;             // status field
      uint8_t  direction;         //add by luoyiming, 2020-01-07
      uint16_t  cluster;          // to send or receive reports of the attribute
      uint16_t  manuCode;         //add by luoyiming, 2019-10-21
      uint16_t  consolidatedMinReportInt;             // attribute ID
      uint16_t  consolidatedMaxReportInt;           // attribute data type
      uint16_t  timeSinceLastReport;
      bdbAttrLinkedListAttr_t attrLinkedList;
    } bdbReportAttrClusterEndpoint_t;
    
    typedef struct
    {
      uint8_t flags;
      uint8_t  endpoint;
      uint8_t  direction;  //add by luoyiming, 2020-01-07
      uint16_t  cluster;
      uint16_t  manuCode;  //add by luoyiming, 2019-10-21
    } bdbReportFlagsHolder_t;
    
    typedef struct
    {
      uint8_t endpoint;
      uint8_t direction;  //add by luoyiming, 2020-01-07
      uint16_t cluster;
      uint16_t manuCode;  //add by luoyiming, 2019-10-21
      uint16_t attrID;
      uint16_t minReportInt;
      uint16_t maxReportInt;
      uint8_t  reportableChange[BDBREPORTING_MAX_ANALOG_ATTR_SIZE];
    } bdbReportAttrDefaultCfgData_t;
    
    

    Then  add parameter "direction" and "manuCode" into every function which has "cluster" and "attrID" in "bdb_reporting.c".

    static uint8_t bdb_clusterEndpointArrayAdd( uint8_t endpoint, uint16_t cluster, uint16_t manuCode, uint8_t direction, uint16_t consolidatedMinReportInt, uint16_t consolidatedMaxReportInt, uint16_t timeSinceLastReport );
    static uint8_t bdb_clusterEndpointArraySearch( uint8_t endpoint, uint16_t cluster, uint16_t manuCode, uint8_t direction );
    static uint8_t bdb_repAttrCfgRecordsArrayAdd( uint8_t endpoint, uint16_t cluster, uint16_t manuCode, uint8_t direction, uint16_t attrID, uint16_t minReportInt,
                                                  uint16_t maxReportInt, uint8_t  reportableChange[], uint16_t defMinReportInt, uint16_t defMaxReportInt, uint8_t defReportChange[] );
                                                  static uint8_t bdb_repAttrCfgRecordsArraySearch( uint8_t endpoint, uint16_t cluster, uint16_t manuCode, uint8_t direction, uint16_t attrID ); //add manuCode, fixed by luoyiming 2019-10-20
    static uint8_t bdb_repAttrCfgRecordsArrayConsolidateValues( uint8_t endpoint, uint16_t cluster, uint16_t manuCode, uint8_t direction, uint16_t* consolidatedMinReportInt, uint16_t* consolidatedMaxReportInt );
    static uint8_t bdb_RepFindAttrEntry( uint8_t endpoint, uint16_t cluster, uint16_t manuCode, uint8_t direction, uint16_t attrID, zclAttribute_t* attrRes );

  • The fixing is too many, so I have to update my fixed files.

    zcl.zip

    bdb_reporting.zip

    The complete fixing can be downloaded at gitee.com/.../simplelink_zstack_sdk.git

  • Hey Aries,

    Thank you for providing a detailed explanation of your changes and link to your complete solution.  I assume this has been verified on the SIMPLELINK-CC13X2-26X2-SDK v5.20?

    Regards,
    Ryan

  • Yes, all of these has been verified on the SIMPLELINK-CC13X2-26X2-SDK v5.20. We have designed a light-level-sensor device which can read illuminance-measurement-value from other light-sensor and send level-command to other lights