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.

CC2538: 2 bugs are still appearing in zcl.c file of z-stack 3.0.2

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

1, in file zcl.c, the function zcl_SendReportCmd not support getting attribute value that access by zclReadWriteCB.

2, in file zcl.c, the function zcl_getExternalFoundationHandler's access parameter is afIncomingMSGPacket_t type, that could affect to return error Task_Id value.

  • Hi Aries,

    Thank you for bringing these to our attention, I know that the first was previously made known but could have gotten missed during resolution of other known issues: e2e.ti.com/.../715743

    Had the second already been raised as well or is this a new issue?

    Regards,
    Ryan
  • Hi Aries,

    Since reporting is now defined in Base Device Behavior specification, now the z-stack bdb implementation also supports the access to attributes with callbacks. Take a look to bdb_RepReport() in bdb_reporting.c, the is a function named bdb_RepFindAttrEntry() that is called to find the attribute record even if the access requires a callback or not and then sends the report with zcl_SendReportCmd() once the attribute was found.

    Can you elaborate on point number 2? I cannot see the issue here.

  • but  zcl_SendReportCmd()  have no ability to access to attributes with callbacks. zcl_SendReportCmd() should be fixed like this.

    ZStatus_t zcl_SendReportCmd( uint8 srcEP, afAddrType_t *dstAddr,
                                 uint16 clusterID, zclReportCmd_t *reportCmd,
                                 uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
    {
      uint16 dataLen = 0;
      uint8 *buf;
      ZStatus_t status;
      uint8 i;
    
      // calculate the size of the command
      for ( i = 0; i < reportCmd->numAttr; i++ )
      {
        zclReport_t *reportRec = &(reportCmd->attrList[i]);
    
        dataLen += 2 + 1; // Attribute ID + data type
    
        // Attribute Data
        //dataLen += zclGetAttrDataLength( reportRec->dataType, reportRec->attrData );
        if( reportRec->attrData )
        {
          dataLen += zclGetAttrDataLength( reportRec->dataType, reportRec->attrData );
        }
        else
        {
          dataLen += zclGetAttrDataLengthUsingCB( srcEP, clusterID, reportRec->attrID );
        }
      }
    
      buf = zcl_mem_alloc( dataLen );
      if ( buf != NULL )
      {
        // Load the buffer - serially
        uint8 *pBuf = buf;
    
        for ( i = 0; i < reportCmd->numAttr; i++ )
        {
          zclReport_t *reportRec = &(reportCmd->attrList[i]);
    
          *pBuf++ = LO_UINT16( reportRec->attrID );
          *pBuf++ = HI_UINT16( reportRec->attrID );
          *pBuf++ = reportRec->dataType;
    
          //pBuf = zclSerializeData( reportRec->dataType, reportRec->attrData, pBuf );
          if ( reportRec->attrData != NULL )
          {
            // Copy attribute data to the buffer to be sent out
            pBuf = zclSerializeData( reportRec->dataType, reportRec->attrData, pBuf );
          }
          else
          {
            uint16 dataLen;
            // Read attribute data directly into the buffer to be sent out
            zclReadAttrDataUsingCB( srcEP, clusterID, reportRec->attrID, pBuf, &dataLen );
            pBuf += dataLen;
          }
        }
    
        status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_REPORT, FALSE,
                                  direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
        zcl_mem_free( buf );
      }
      else
      {
        status = ZMemError;
      }
    
      return ( status );
    }

    the number 2 issue is the under code in fuction "zcl_event_loop" in zcl.c

          if ( *msgPtr == AF_INCOMING_MSG_CMD )
          {
            zcl_ProcessMessageMSG( (afIncomingMSGPacket_t *)msgPtr );
          }
          else
          {
            taskID = zcl_getExternalFoundationHandler( (afIncomingMSGPacket_t *)msgPtr );
            
            if ( taskID != TASK_NO_TASK )
            {
              // send it to another task to process.
              osal_msg_send( taskID, msgPtr );
              dealloc = FALSE;
            }
          }

  • zcl_SendReportCmd() already holds the attribute data in "reportCmd" in a struct of type zclReportCmd_t. Attribute reporting is now part of BDB state machine so zcl_SendReportCmd() is used only to send the report buffer given by BDB state machine, not to solve the list of attributes to be reported.



    typedef struct
    {
      uint8       numAttr;       // number of reports in the list
      zclReport_t attrList[];    // attribute report list
    } zclReportCmd_t;

    You can take a look in to Sample Temperature Sensor at zclSampleTemperatureSensor_Init() where bdb_RepAddAttrCfgRecordDefaultToList() is used to set the default reporting configuration, then BDB reporting state machine solves everything related to attribute reporting. Also look at ZigBee Application Architecture, ZigBee Alliance document and Base Device Behavior Specification.


    For number 2, are you talking about to use the endpoint directly instead of msgPtr? however the return of the function is not affected by this.

     

  • In function bdb_RepReport() in "bdb_Reporting.c", pReportCmd in type zclReportCmd_t was send by zcl_SendReportCmd. The member "attrList[i].attrData" of pReportCmd is a data pointer type that access to buffer "gAttrDataValue".  "gAttrDataValue" can only carry one Attribute value, but if there was more than one attribute in a cluster should be reported, the error will happen.

  • Part Number: CC2538

    Function zcl_SendReportCmd can carry multi attributes with same cluster-ID in once bdb reporting trigger. In function bdb_RepReport, the reported attribute value is cached in global variable "gAttrDataValue", who can only cache one-attribute. If multi attributes need to be reported, more caches are needed. So the function bdb_RepReport can be fixed like this

    static void bdb_RepReport( uint8 specificCLusterEndpointIndex )
    {
      afAddrType_t dstAddr;
      zclReportCmd_t *pReportCmd;
      uint8 i;
      
      bdbReportAttrClusterEndpoint_t* clusterEndpointItem = NULL;
      if( specificCLusterEndpointIndex == BDBREPORTING_INVALIDINDEX )
      {
        if( bdb_reportingNextClusterEndpointIndex < bdb_reportingClusterEndpointArrayCount )
        {
          clusterEndpointItem = &(bdb_reportingClusterEndpointArray[bdb_reportingNextClusterEndpointIndex]);
        }
      }
      else
      {
        clusterEndpointItem = &(bdb_reportingClusterEndpointArray[specificCLusterEndpointIndex]);
      }
    
      // actually send the report
      if( clusterEndpointItem->consolidatedMaxReportInt != ZCL_REPORTING_OFF && clusterEndpointItem->attrLinkedList.numItems )
      {
        dstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
        dstAddr.addr.shortAddr = 0;
        dstAddr.endPoint = clusterEndpointItem->endpoint;
        dstAddr.panId = _NIB.nwkPanId;
        
        //pReportCmd = osal_mem_alloc( sizeof( zclReportCmd_t ) + (clusterEndpointItem->attrLinkedList.numItems * sizeof( zclReport_t )) );
        uint8 *pBuffer = osal_mem_alloc( sizeof( zclReportCmd_t ) + (clusterEndpointItem->attrLinkedList.numItems * ( sizeof( zclReport_t )) + BDBREPORTING_MAX_ANALOG_ATTR_SIZE ) );
        //if ( pReportCmd != NULL )
        if( pBuffer )
        {
          pReportCmd = (zclReportCmd_t*)pBuffer;
          pBuffer += sizeof( zclReportCmd_t ) + (clusterEndpointItem->attrLinkedList.numItems * sizeof( zclReport_t ));
          pReportCmd->numAttr = clusterEndpointItem->attrLinkedList.numItems;
          for ( i = 0; i < clusterEndpointItem->attrLinkedList.numItems; ++ i )
          {
            pReportCmd->attrList[i].attrID   = 0xFFFF;
            pReportCmd->attrList[i].dataType = 0xFF;
            pReportCmd->attrList[i].attrData = NULL;
            
            bdbLinkedListAttrItem_t* attrListItem = bdb_linkedListAttrGetAtIndex( &clusterEndpointItem->attrLinkedList, i );
            if(attrListItem!=NULL)
            {
              pReportCmd->attrList[i].attrID = attrListItem->data->attrID;
              zclAttribute_t attrRec;
              uint8 attrRes = bdb_RepFindAttrEntry( clusterEndpointItem->endpoint, clusterEndpointItem->cluster, attrListItem->data->attrID, &attrRec );
              if( attrRes == BDBREPORTING_TRUE )
              {
                uint8 *dataPtr = pBuffer + i*BDBREPORTING_MAX_ANALOG_ATTR_SIZE;
                pReportCmd->attrList[i].dataType = attrRec.dataType;
                //pReportCmd->attrList[i].attrData = attrRec.dataPtr;
                osal_memcpy( dataPtr, attrRec.dataPtr, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );
                pReportCmd->attrList[i].attrData = dataPtr;
                //Update last value reported
                if( zclAnalogDataType( attrRec.dataType ) )
                { 
                  //Only if the datatype is analog
                  osal_memset( attrListItem->data->lastValueReported,0x00, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );
                  osal_memcpy( attrListItem->data->lastValueReported, attrRec.dataPtr, zclGetDataTypeLength( attrRec.dataType ) );
                }
              }
            }
          }
    
          zcl_SendReportCmd( clusterEndpointItem->endpoint, &dstAddr,
                             clusterEndpointItem->cluster, pReportCmd,
                             ZCL_FRAME_SERVER_CLIENT_DIR, BDB_REPORTING_DISABLE_DEFAULT_RSP, bdb_getZCLFrameCounter( ) );
    
          osal_mem_free( pReportCmd );
        }
      }
    }

  • You are right. The issue will cause you to have the same data pointer for all attributes.