ESP32: Rotating device ID for BLE transport (#13206)

* ESP32: Rotating device ID for BLE transport

* Remove the ifdefs and fix the Zephyr static assert

Also, set the default value of chip_enable_additional_data_advertising
to false in src/platform/BUILD.gn. If this flag is set then Linux and
ESP32 set the Additional Data flag and displayes the C3 characteristic.

* Changed kServiceDataLenSize to kServiceDataTypeSize

Added chip_enable_additional_data_advertising = true to tv-app and
tv-cast-app
Removed the unused characteristic definitions
diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt
index e405201..94153fa 100644
--- a/config/esp32/components/chip/CMakeLists.txt
+++ b/config/esp32/components/chip/CMakeLists.txt
@@ -107,6 +107,11 @@
     chip_gn_arg_append("chip_enable_ota_requestor"                 "true")
 endif()
 
+if (CONFIG_ENABLE_ROTATING_DEVICE_ID)
+    chip_gn_arg_append("chip_enable_additional_data_advertising"   "true")
+    chip_gn_arg_append("chip_enable_rotating_device_id"            "true")
+endif()
+
 set(args_gn_input "${CMAKE_CURRENT_BINARY_DIR}/args.gn.in")
 file(GENERATE OUTPUT "${args_gn_input}" CONTENT "${chip_gn_args}")
 
diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig
index b7837b4..3e4dfb5 100644
--- a/config/esp32/components/chip/Kconfig
+++ b/config/esp32/components/chip/Kconfig
@@ -706,6 +706,11 @@
                 Setting this to y will cause the commissioner to send commissioning commands to the
                 various clusters after establishing a PASE session.
 
+        config ENABLE_ROTATING_DEVICE_ID
+            depends on ENABLE_CHIPOBLE
+            bool "Enable Rotating Device Identifier Support"
+            default n
+
     endmenu
 
 
diff --git a/examples/tv-app/linux/args.gni b/examples/tv-app/linux/args.gni
index beb1956..266d8cb 100644
--- a/examples/tv-app/linux/args.gni
+++ b/examples/tv-app/linux/args.gni
@@ -26,4 +26,6 @@
 
 chip_build_libshell = true
 
+chip_enable_additional_data_advertising = true
+
 chip_enable_rotating_device_id = true
diff --git a/examples/tv-casting-app/linux/args.gni b/examples/tv-casting-app/linux/args.gni
index e036446..3175a83 100644
--- a/examples/tv-casting-app/linux/args.gni
+++ b/examples/tv-casting-app/linux/args.gni
@@ -26,4 +26,6 @@
 
 chip_build_libshell = true
 
+chip_enable_additional_data_advertising = true
+
 chip_enable_rotating_device_id = true
diff --git a/src/ble/CHIPBleServiceData.h b/src/ble/CHIPBleServiceData.h
index cd4d84e..e8ca517 100644
--- a/src/ble/CHIPBleServiceData.h
+++ b/src/ble/CHIPBleServiceData.h
@@ -45,12 +45,14 @@
  */
 struct ChipBLEDeviceIdentificationInfo
 {
-    constexpr static uint16_t kDiscriminatorMask = 0xfff;
+    constexpr static uint16_t kDiscriminatorMask     = 0xfff;
+    constexpr static uint8_t kAdditionalDataFlagMask = 0x1;
 
     uint8_t OpCode;
     uint8_t DeviceDiscriminator[2];
     uint8_t DeviceVendorId[2];
     uint8_t DeviceProductId[2];
+    uint8_t AdditionalDataFlag;
 
     void Init() { memset(this, 0, sizeof(*this)); }
 
@@ -74,6 +76,20 @@
         deviceDiscriminator |= static_cast<uint16_t>(DeviceDiscriminator[1] << 8u & ~kDiscriminatorMask);
         chip::Encoding::LittleEndian::Put16(DeviceDiscriminator, deviceDiscriminator);
     }
+
+    uint8_t GetAdditionalDataFlag() const { return (AdditionalDataFlag & kAdditionalDataFlagMask); }
+
+    void SetAdditionalDataFlag(bool flag)
+    {
+        if (flag)
+        {
+            AdditionalDataFlag |= kAdditionalDataFlagMask;
+        }
+        else
+        {
+            AdditionalDataFlag &= static_cast<uint8_t>(~kAdditionalDataFlagMask);
+        }
+    }
 } __attribute__((packed));
 
 } /* namespace Ble */
diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn
index c154565..37dd34a 100644
--- a/src/platform/BUILD.gn
+++ b/src/platform/BUILD.gn
@@ -54,7 +54,7 @@
     chip_bypass_rendezvous = false
 
     # Enable including the additional data in the advertisement packets
-    chip_enable_additional_data_advertising = true
+    chip_enable_additional_data_advertising = false
 
     # Enable adding optional rotating device id to the additional data.
     chip_enable_rotating_device_id = false
diff --git a/src/platform/ESP32/BLEManagerImpl.h b/src/platform/ESP32/BLEManagerImpl.h
index 624da05..62ba2b7 100644
--- a/src/platform/ESP32/BLEManagerImpl.h
+++ b/src/platform/ESP32/BLEManagerImpl.h
@@ -189,6 +189,9 @@
     uint16_t mServiceAttrHandle;
     uint16_t mRXCharAttrHandle;
     uint16_t mTXCharAttrHandle;
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    uint16_t mC3CharAttrHandle;
+#endif
     uint16_t mTXCharCCCDAttrHandle;
     BitFlags<Flags> mFlags;
     char mDeviceName[kMaxDeviceNameLength + 1];
@@ -246,6 +249,11 @@
     static int ble_svr_gap_event(struct ble_gap_event * event, void * arg);
 
     static int gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg);
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    static int gatt_svr_chr_access_additional_data(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt,
+                                                   void * arg);
+    void HandleC3CharRead(struct ble_gatt_char_context * param);
+#endif /* CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING */
 #endif
 
     static void DriveBLEState(intptr_t arg);
diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn
index 7d70d6b..3b13cfd 100644
--- a/src/platform/ESP32/BUILD.gn
+++ b/src/platform/ESP32/BUILD.gn
@@ -48,7 +48,10 @@
     "nimble/BLEManagerImpl.cpp",
   ]
 
-  deps = [ "${chip_root}/src/lib/dnssd:platform_header" ]
+  deps = [
+    "${chip_root}/src/lib/dnssd:platform_header",
+    "${chip_root}/src/setup_payload",
+  ]
 
   public_deps = [
     "${chip_root}/src/crypto",
diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp
index a59ed79..f7dd906 100644
--- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp
+++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp
@@ -34,6 +34,7 @@
 #include <lib/support/CodeUtils.h>
 #include <lib/support/logging/CHIPLogging.h>
 #include <platform/internal/BLEManager.h>
+#include <setup_payload/AdditionalDataPayloadGenerator.h>
 #include <system/SystemTimer.h>
 
 #include "esp_log.h"
@@ -67,9 +68,6 @@
     ChipBLEDeviceIdentificationInfo DeviceIdInfo;
 };
 
-const ble_uuid128_t UUID_CHIPoBLEService = {
-    BLE_UUID_TYPE_128, { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xF6, 0xFF, 0x00, 0x00 }
-};
 const ble_uuid16_t ShortUUID_CHIPoBLEService = { BLE_UUID_TYPE_16, 0xFFF6 };
 
 const ble_uuid128_t UUID128_CHIPoBLEChar_RX = {
@@ -77,19 +75,19 @@
 };
 const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
                                                  0x9D, 0x11 } };
-const ble_uuid128_t UUID_CHIPoBLEChar_RX   = {
-    { BLE_UUID_TYPE_128 }, { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D, 0x11 }
-};
 
-const ble_uuid128_t UUID128_CHIPoBLEChar_TX = {
-    BLE_UUID_TYPE_128, { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }
-};
 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
                                                  0x9D, 0x12 } };
 const ble_uuid128_t UUID_CHIPoBLEChar_TX   = {
     { BLE_UUID_TYPE_128 }, { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }
 };
 
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+const ble_uuid128_t UUID_CHIPoBLEChar_C3 = {
+    { BLE_UUID_TYPE_128 }, { 0x04, 0x8F, 0x21, 0x83, 0x8A, 0x74, 0x7D, 0xB8, 0xF2, 0x45, 0x72, 0x87, 0x38, 0x02, 0x63, 0x64 }
+};
+#endif
+
 SemaphoreHandle_t semaphoreHandle = NULL;
 
 } // unnamed namespace
@@ -115,6 +113,14 @@
                   .flags      = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
                   .val_handle = &sInstance.mTXCharCCCDAttrHandle,
               },
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+              {
+                  .uuid       = (ble_uuid_t *) (&UUID_CHIPoBLEChar_C3),
+                  .access_cb  = gatt_svr_chr_access_additional_data,
+                  .flags      = BLE_GATT_CHR_F_READ,
+                  .val_handle = &sInstance.mC3CharAttrHandle,
+              },
+#endif
               {
                   0, /* No more characteristics in this service */
               },
@@ -133,7 +139,10 @@
     err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
     SuccessOrExit(err);
 
-    mRXCharAttrHandle     = 0;
+    mRXCharAttrHandle = 0;
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    mC3CharAttrHandle = 0;
+#endif
     mTXCharCCCDAttrHandle = 0;
     mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
     mFlags.Set(Flags::kFastAdvertisingEnabled, true);
@@ -683,6 +692,10 @@
     uint8_t advData[MAX_ADV_DATA_LEN];
     uint8_t index = 0;
 
+    constexpr uint8_t kServiceDataTypeSize = 1;
+
+    chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo;
+
     // If a custom device name has not been specified, generate a CHIP-standard name based on the
     // bottom digits of the Chip device id.
     uint16_t discriminator;
@@ -706,12 +719,11 @@
     advData[index++] = 0x02;                                                                // length
     advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS;                                            // AD type : flags
     advData[index++] = CHIP_ADV_DATA_FLAGS;                                                 // AD value
-    advData[index++] = 0x0A;                                                                // length
+    advData[index++] = kServiceDataTypeSize + sizeof(ESP32ChipServiceData);                 // length
     advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA;                                     // AD type: (Service Data - 16-bit UUID)
     advData[index++] = static_cast<uint8_t>(ShortUUID_CHIPoBLEService.value & 0xFF);        // AD value
     advData[index++] = static_cast<uint8_t>((ShortUUID_CHIPoBLEService.value >> 8) & 0xFF); // AD value
 
-    chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo;
     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
     if (err != CHIP_NO_ERROR)
     {
@@ -719,6 +731,10 @@
         ExitNow();
     }
 
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    deviceIdInfo.SetAdditionalDataFlag(true);
+#endif
+
     VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG);
     memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo));
     index = static_cast<uint8_t>(index + sizeof(deviceIdInfo));
@@ -1046,6 +1062,69 @@
     return err.AsInteger();
 }
 
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+void BLEManagerImpl::HandleC3CharRead(struct ble_gatt_char_context * param)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    chip::System::PacketBufferHandle bufferHandle;
+
+    char serialNumber[ConfigurationManager::kMaxSerialNumberLength + 1];
+    uint16_t lifetimeCounter = 0;
+    BitFlags<AdditionalDataFields> additionalDataFields;
+
+#if CHIP_ENABLE_ROTATING_DEVICE_ID
+    err = ConfigurationMgr().GetSerialNumber(serialNumber, sizeof(serialNumber));
+    SuccessOrExit(err);
+    err = ConfigurationMgr().GetLifetimeCounter(lifetimeCounter);
+    SuccessOrExit(err);
+
+    additionalDataFields.Set(AdditionalDataFields::RotatingDeviceId);
+#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID */
+
+    err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(lifetimeCounter, serialNumber, strlen(serialNumber),
+                                                                         bufferHandle, additionalDataFields);
+    SuccessOrExit(err);
+
+    os_mbuf_append(param->ctxt->om, bufferHandle->Start(), bufferHandle->DataLength());
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data (%s)", __func__);
+    }
+    return;
+}
+
+int BLEManagerImpl::gatt_svr_chr_access_additional_data(uint16_t conn_handle, uint16_t attr_handle,
+                                                        struct ble_gatt_access_ctxt * ctxt, void * arg)
+{
+    struct ble_gatt_char_context param;
+    int err = 0;
+
+    memset(&param, 0, sizeof(struct ble_gatt_char_context));
+
+    switch (ctxt->op)
+    {
+    case BLE_GATT_ACCESS_OP_READ_CHR:
+
+        param.conn_handle = conn_handle;
+        param.attr_handle = attr_handle;
+        param.ctxt        = ctxt;
+        param.arg         = arg;
+        sInstance.HandleC3CharRead(&param);
+        break;
+
+    default:
+        err = BLE_ATT_ERR_UNLIKELY;
+        break;
+    }
+
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+
+    return err;
+}
+#endif /* CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING */
+
 int BLEManagerImpl::gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg)
 {
     struct ble_gatt_char_context param;
diff --git a/src/platform/Linux/bluez/Helper.cpp b/src/platform/Linux/bluez/Helper.cpp
index 4da5da3..feae414 100644
--- a/src/platform/Linux/bluez/Helper.cpp
+++ b/src/platform/Linux/bluez/Helper.cpp
@@ -45,9 +45,8 @@
 
 /**
  *    @file
- *          Provides Bluez dbus implementatioon for BLE
+ *          Provides Bluez dbus implementation for BLE
  */
-
 #include <ble/BleUUID.h>
 #include <ble/CHIPBleServiceData.h>
 #include <lib/support/BitFlags.h>
@@ -1520,6 +1519,10 @@
     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(apEndpoint->mDeviceIdInfo);
     SuccessOrExit(err);
 
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    apEndpoint->mDeviceIdInfo.SetAdditionalDataFlag(true);
+#endif
+
 exit:
     if (nullptr != msg)
     {
diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp
index e7b99e7..072e1c0 100644
--- a/src/platform/Zephyr/BLEManagerImpl.cpp
+++ b/src/platform/Zephyr/BLEManagerImpl.cpp
@@ -269,7 +269,7 @@
     }
 
     // Initialize service data
-    static_assert(sizeof(serviceData) == 9, "Size of BLE advertisement data changed! Was that intentional?");
+    static_assert(sizeof(serviceData) == 10, "Size of BLE advertisement data changed! Was that intentional?");
     chip::Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val);
     ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo));