[Zigbee] Manufacturer Code clarification

Setup: 

nrf52840DK (Zigbee Cordinator based on Zigbee Coordinator sample)

nrf52840DK (ZED)

nrf52840 dongle (Wireshark sniffer)

NCS v2.4.1

Hi,

In my application I am using Manufacturer specific ZCL commands and attributes. All of that seems working fine but I am little bit confused regarding the Manufacturer Code usage.

There are two magic values in NCS: 
0x1234 defined as:

#define ZB_MANUFACTURER_CODE_DSR            0x1234U
/* That is not a joke, our manufacturer code is really 1234! */
/*! @endcond */ /* internals_doc */

#define ZB_DEFAULT_MANUFACTURER_CODE ZB_MANUFACTURER_CODE_DSR

Manufacturer Code of DSR for all applications based on ZBOSS.

0x127F defined as: 

config ZIGBEE_FOTA_MANUFACTURER_ID
	hex "Manufacturer ID"
	default 0x127F
	range 0x0000 0xFFFF
	help
	  This is the ZigBee assigned identifier for each member company.
	  0x127F - Nordic Semiconductor
	  0xFFFF - wild card value has a 'match all' effect.

Manufacturer Code of Nordic Semiconductor used only for FOTA purposes to fill up OTA Header with it.

  1. What happens if the manufacturer code placed in the OTA Header of the received image is different from the one set on the device (0x127F by default)?
  2. Which Manufacturer Code should be used in Cluster descriptor ?
    /** @brief ZCL cluster description. */
    typedef ZB_PACKED_PRE struct zb_zcl_cluster_desc_s
    {
      zb_uint16_t cluster_id; /**< ZCL 16-bit cluster id. @see zcl_cluster_id */
      zb_uint16_t attr_count;  /**< Attributes number supported by the cluster */
      struct zb_zcl_attr_s *attr_desc_list; /**< List of cluster attributes,
             declared using ZB_ZCL_DECLARE_<CLUSTER_NAME>_ATTRIB_LIST() macro */
      zb_uint8_t role_mask;   /**< Cluster role, refer to zcl_cluster_role */
      zb_uint16_t manuf_code; /**< Manufacturer code for cluster and its attributes */
      zb_zcl_cluster_init_t cluster_init;
    } ZB_PACKED_STRUCT
    zb_zcl_cluster_desc_t;
  3. Is it possible to overwrite #ZB_DEFAULT_MANUFACTURER_CODE ?
  4. Why #ZB_DEFAULT_MANUFACTURER_CODE is not overwritten by Nordic Semiconductor Manufacturer Code (0x127F) ? 

I am looking forward to hearing from you,

Pawel

Parents
  • Hello Pawel,

    What happens if the manufacturer code placed in the OTA Header of the received image is different from the one set on the device (0x127F by default)?

    According to the Zigbee FOTA library documentation, the image should only be accepted if the Manufacturer ID of the FOTA header matches, as well as the image type, Hardware version and Firmware version. 

    Regarding question 3 and 4. I assume it is possible to overwrite it, but I am not sure whether this code is even used at all. Unless the Zboss library (not open source) fetches the ZB_DEFAULT_MANUFACTURER_CODE and uses it, it is not used at all in the nRF Connect SDK. Seeing as it builds just fine without the ZB_DEFAULT_MANUFACTURER_CODE_DSR definition, I believe that isn't used anywhere. Remember that this library is not used on Nordic devices only. So perhaps it is used by other chip vendors. 

    To answer your second question, and all of them, I guess. If you intend to create a custom cluster, you must include a manufacturer_code. Before you start selling it, you need to certify it with the Zigbee Alliance, and for this, you are assigned your own company manufacturer code. So I believe they will tell you to use your custom manufacturer code for your own clusters. And I guess you are free to use either Nordic's or your own for the FOTA cluster, and as long as you use the same when generating FOTA images, that should work just fine.

    Best regards,

    Edvin

  • Hi Edvin,

    Thank you for fast response.

    ZB_DEFAULT_MANUFACTURER_CODE is indeed used by the stack. 
    Manufacturer Code 0x1234 (DSR) is used in Node Descriptor Response as an answer for Nordic Descriptor Request sent from parent device. Have a look on the screenshot below: 



    My goal is to have my custom (ofc certified by Zigbee Aliance) manufacturer code everywhere. 
    I am able to set it in Cluster descriptors and for FOTA purposes in OTA Upgrade cluster as well but it seems that the Node Descriptor Response still uses the DSR Manufacturer Code. 
    I would like to change ZB_DEFAULT_MANUFACTURER_CODE to custom one without needing to do the fork of NCS.
    Is it possible ? 

    Thanks in advance,

    Pawel

  • In fact, this is what it looks like in NCS v2.6.0:

    void zb_zcl_send_report_attr_command(zb_zcl_reporting_info_t *rep_info, zb_uint8_t param)
    {
      zb_uint8_t *cmd_data;
      zb_zcl_reporting_info_t *cur_rep_info;
      zb_zcl_attr_t *attr_desc;
      zb_uint16_t bytes_avail;
      zb_uint8_t attr_size;
      zb_uint8_t send_mode;
      zb_uint8_t is_manuf_spec;
    
      TRACE_MSG(
          TRACE_ZCL1,
          ">> zb_zcl_send_report_attr_command rep_info %p, param %hd",
          (FMT__P_H, rep_info, param));
    
      attr_desc =
        zb_zcl_get_attr_desc_manuf_a(
          rep_info->ep,
          rep_info->cluster_id,
          rep_info->cluster_role,
          rep_info->attr_id,
          rep_info->manuf_code);
    
      is_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc);
    
      /* ZCL spec, 2.4.11 Report Attributes Command */
      /* Read attribute command
         | ZCL header 3 b | Attr Report 1 XX b | Attr Report 1 XX b | ...
    
         Attr Report format
         | attr id 2 b |  Attr data type 1 b | attr value XX b |
      */
      /* Construct packet header */
      /* Use buffer specified by input param */
      cmd_data = ZB_ZCL_START_PACKET(param);
    
      /* NOTE: currently, manufacturer specific is not supported */
      ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(
        cmd_data, ZB_ZCL_FRAME_DIRECTION_TO_CLI,
        is_manuf_spec, ZB_ZCL_ENABLE_DEFAULT_RESPONSE);
    
      if (is_manuf_spec)
      {
        TRACE_MSG(TRACE_ERROR, "rep_info->manuf_code 0x%x", (FMT__D, rep_info->manuf_code));
        ZB_ASSERT(rep_info->manuf_code != ZB_ZCL_NON_MANUFACTURER_SPECIFIC);
    
        ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(cmd_data, ZB_ZCL_GET_SEQ_NUM(), ZB_TRUE, rep_info->manuf_code, ZB_ZCL_CMD_REPORT_ATTRIB);
      }

    And it looks like ZB_ZCL_MANUF_CODE_INVALID = 0x0000 and ZB_ZCL_NON_MANUFACTURER_SPECIFIC = 0xFFFF. I guess the callstack up until this is a bit different as well. Perhaps the default (if nothing else is specified) manuf_spec code has changed from 0x0000 to 0xFFFF. 

    pwpot said:
    AFAIU that single line forces us to give the standard cluster Manufacturer-specific code.

    But only if 

    is_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc);

    is true, right?

    Does this return true if you are using a standard cluster as well?

    To me, it looks like if the command is for a manufacturer specific cluster, then it checks whether the manufacturer code is not 0x0000 (in v2.4.0) and not 0xFFFF (in 2.6.0). Are you seeing something else?

    BR,

    Edvin

  • Hi,

    is_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc);

    returns true indeed. That is because my attribute descriptor looks as follows: 

    #define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTIC_FAULT_CODE_ID(data_ptr) \
        { \
            ZB_ZCL_ATTR_DIAGNOSTIC_FAULT_CODE_ID, ZB_ZCL_ATTR_TYPE_U16, \
                ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_MANUF_SPEC, (void *)data_ptr \
        }

    Then: 

    ZB_ASSERT(ep_desc && cluster_desc && cluster_desc->manuf_code != ZB_ZCL_MANUF_CODE_INVALID);

    Manufacturer Code shall be different than 0x0000, otherwise the ASSERT occurs.

    I see that the reporting mechanism is slightly different in 2.6.0. I am going to migrate to 2.6.0 but no matter the version my question will be the same :) 

    At this point, In my opinion in the case of manufacturer-specific attributes within the standard cluster, the cluster descriptor shall use a Manufacturer Code different than 0x0000 and that is valid for NCS 2.4.1.

    Maybe, that exact scenario is solved in 2.6.0 because the ASSERT does not check cluster_desc->manuf_code but rep_info->manuf_code. 

    What do you think? 

    Regards,

    Pawel

  • Hello Pawel,

    I am not saying you are wrong, but I am trying to understand. 

    Whenever you call:

    void zb_zcl_send_report_attr_command(zb_zcl_reporting_info_t *rep_info, zb_uint8_t param)

    wouldn't the *rep_info hold information so that:

    is_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc);

    would return false if that attribute is not a manufacturer specific attribute?

    And if is_manuf_spec is false, then the 

    ZB_ASSERT(rep_info->manuf_code != ZB_ZCL_NON_MANUFACTURER_SPECIFIC);

    will not run, right?

  • Hi Edvin,

    Sorry for the late reply.

    Whenever you call:

    Fullscreen
    1
    void zb_zcl_send_report_attr_command(zb_zcl_reporting_info_t *rep_info, zb_uint8_t param)
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    wouldn't the *rep_info hold information so that:

    Fullscreen
    1
    is_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    would return false if that attribute is not a manufacturer specific attribute?

    Yes, is_manuf_spec will be false, and that information is determined based on the attribute descriptor, not based on reporting info.

    And if is_manuf_spec is false, then the 

    Fullscreen
    1
    ZB_ASSERT(rep_info->manuf_code != ZB_ZCL_NON_MANUFACTURER_SPECIFIC);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    will not run, right?

    That assert is in 2.6.0 in 2.4.1 it looks different. 

    ZB_ASSERT(ep_desc && cluster_desc && cluster_desc->manuf_code != ZB_ZCL_MANUF_CODE_INVALID);


  • pwpot said:
    That assert is in 2.6.0 in 2.4.1 it looks different

    Yes, but it will still only be checked if is_manuf_specific is true?

Reply Children
No Data
Related