Silicon Labs documentation on Bluetooth Mesh version 11.0.0.

Documentation source: https://docs.silabs.com/btmesh/11.0.0

# Bluetooth Mesh

## Developing with Silicon Labs Bluetooth Mesh

Bluetooth Mesh is ideally suited for control, monitoring, and automation systems where hundreds or thousands of devices need to communicate with one another. Bluetooth Mesh was designed to meet the strict requirements of commercial and industrial environments where ease of deployment, performance, and security are of the utmost importance. Networked lighting control is one use case that has rapidly embraced Bluetooth Mesh technology.

![diagram](/btmesh-start/10.0.0/images/sld176-image1.png)

The content on these pages is intended for those who want to experiment with or are already developing a Bluetooth Mesh application using [Silicon Labs technology](https://www.silabs.com/developers/bluetooth-mesh).

For details about this release, links to release notes are available on the [silabs.com SDK Release Notes page](https://www.silabs.com/developer-tools/software-development-kit-release-notes).

For Silicon Labs Bluetooth Mesh product information, see the [product pages on silabs.com](https://www.silabs.com/wireless/bluetooth/bluetooth-mesh).

For background about Bluetooth Mesh, the [Introduction](https://www.bluetooth.com/bluetooth-resources/bluetooth-mesh-networking-an-introduction-for-developers/) is a good place to start.

To get started with development, see the [Getting Started section](/btmesh/11.0.0/btmesh-getting-started-overview) to get started working with example applications.

If you are already in development, see the [Developer's Guide](/btmesh/11.0.0/btmesh-developers-guide-overview) for details or go directly to the [API Reference Guide](/btmesh/11.0.0/bluetooth-mesh-api).

If you are using Bluetooth Mesh SDK version 1.x, see [Transitioning from the v1.x to the v2.x Bluetooth Mesh SDK](/btmesh/11.0.0/transitioning-from-bluetooth-mesh-1x-to-2x).

## Release Notes

### Bluetooth Mesh Version 11.0.0 - Release Notes (Jun 23, 2026)

Bluetooth Mesh is a standards-based, many-to-many communication topology available for Bluetooth Low Energy (LE) devices, optimized for large-scale networks and ideally suited for building automation, sensor networks, and asset tracking.

Click [here](https://github.com/siliconlabs/simplicity_sdk/tags) for earlier releases.

#### Release Summary

<table>
    <thead>
        <tr>
            <th>Release Item</th>
            <th>Version</th>
            <th>Release Date</th>
            <th>Release Notes</th>
            <th>Key Features</th>
            <th>API Changes</th>
            <th>Bug Fixes</th>
            <th>Chip Enablement</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    SDK
                </p>
            </td>
            <td>
                <p>
                    11.0.0
                </p>
            </td>
            <td>
                <p>
                    Jun 23, 2026
                </p>
            </td>
            <td>
                <p>
                    <a href="sisdk-bt-mesh-sdk-release-notes">Release Notes</a>
                </p>
            </td>
            <td>
                <ul>
                    <li>GCC and IAR compiler version updates</li>
                </ul>
            </td>
            <td>
                <ul>
                    <li>Added MBT Client and Server model deinitialization API</li>
                    <li>Exposed additional LPN configuration parameters (Experimental)</li>
                </ul>
            </td>
            <td>
                <ul>
                    <li>Fixed Secure Network Beacon handling</li>
                    <li>Fixed foundation request memory configuration issues</li>
                    <li>Fixed Sensor Client Model message parsing</li>
                </ul>
            </td>
            <td>None
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    iOS ADK
                </p>
            </td>
            <td>
                <p>
                    11.0.0
                </p>
            </td>
            <td>
                <p>
                    Jun 23, 2026
                </p>
            </td>
            <td>
                <p>
                    <a href="sisdk-bt-mesh-ios-adk-release-notes">Release Notes</a>
                </p>
            </td>
            <td> None
            </td>
            <td> None
            </td>
            <td> None
            </td>
            <td> None
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Android ADK
                </p>
            </td>
            <td>
                <p>
                    11.0.0
                </p>
            </td>
            <td>
                <p>
                    Jun 23, 2026
                </p>
            </td>
            <td>
                <p>
                    <a href="sisdk-bt-mesh-android-adk-release-notes">Release Notes</a>
                </p>
            </td>
            <td> None
            </td>
            <td> None
            </td>
            <td> None
            </td>
            <td> None
            </td>
        </tr>
    </tbody>
</table>

#### Impact of Release Changes

[Impact Statements](#impact-statements) | [Migration Guide](#migration-guide)

##### Impact Statements

<table>
    <thead>
        <tr>
            <th>Change </th>
            <th>Impact</th>
            <th>Affected Software Variants if applicable</th>
            <th>Affected Modes</th>
            <th>Affected OPNs / Boards / OPN Combinations</th>
            <th>Affected Host Interfaces</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Support for GCC 14 and GCC LTO may cause linker issues when combining code compiled with current and older GCC versions.
                </p>
            </td>
            <td>Either disable LTO, if it is not needed, or re-compile all code with GCC 14.</td>
            <td>
                N/A
            </td>
            <td>
                All
            </td>
            <td>
                All
            </td>
            <td>
                All
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Corrected key index data type for Firmware Distribution client model's distribution start API.
                </p>
            </td>
            <td>Ensure a 16-bit unsigned integer is supplied instead of a 8-bit unsigned integer.</td>
            <td>
                N/A
            </td>
            <td>
                All
            </td>
            <td>
                All
            </td>
            <td>
                All
            </td>
        </tr>
    </tbody>
</table>

##### Migration Guide

See [Transitioning from the v1.x to v2.x Bluetooth Mesh
SDK](https://www.silabs.com/documents/public/application-notes/an1298-transitioning-from-bluetooth-mesh-1x-to-2x.pdf)
for a guide on how to migrate from SDK version 1.x to newer versions.

The [API Reference
Guide](https://docs.silabs.com/btmesh/8.0.1/bluetooth-mesh-api/)
provides guidance on replacing currently deprecated API calls with
supported calls before deprecated APIs are removed.

#### Using This Release

[What's in the Release?](#what-s-in-the-release) | [Compatible Software](#compatible-software) | [Installation and Use](#installation-and-use) | [Help and Feedback](#help-and-feedback)

##### What's in the Release?

- [Bluetooth Mesh SDK](https://github.com/SiliconLabsSoftware/sisdk-release/tree/sisdk-2025.12/bluetooth_mesh)
- [Application Examples](https://github.com/SiliconLabsSoftware/sisdk-release/tree/sisdk-2025.12/bluetooth_mesh_app/example)
- [Host Application Examples](https://github.com/SiliconLabsSoftware/sisdk-release/tree/sisdk-2025.12/bluetooth_mesh_app/example_host)
- [IOS / Android ADK](https://github.com/SiliconLabsSoftware/sisdk-release/releases)

##### Compatible Software

<table>
    <thead>
        <tr>
            <th>Software</th>
            <th>Compatible Version or Variant</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                Simplicity SDK
            </td>
            <td>
                2025.12.3
            </td>
        </tr>
        <tr>
            <td>
                Simplicity Studio
            </td>
            <td>
                5.11.0.0
            </td>
        </tr>
        <tr>
            <td>
                Simplicity Commander
            </td>
            <td>
                1.18.2 (provided with Simplicity Studio)
            </td>
        </tr>
        <tr>
            <td>
                GCC (The GNU Compiler Collection)
            </td>
            <td>
                12.2.1 (provided with Simplicity Studio)
            </td>
        </tr>
        <tr>
            <td>
                IAR Embedded Workbench for ARM (IAR-EWARM)
            </td>
            <td>
                9.40.1
            </td>
        </tr>
    </tbody>
</table>

##### Installation and Use

To run your first demo, see our [Getting Started Guides](https://docs.silabs.com/btmesh/11.0.0/btmesh-getting-started-overview).

To kick start your development, see our [Developer's Guide](https://docs.silabs.com/btmesh/11.0.0/btmesh-developers-guide-overview).

For information about Secure Vault Integration, see [here](https://www.silabs.com/security/secure-vault).

To review Security and Software Advisory notifications and manage your notification preferences:

1. Go to [https://community.silabs.com/](https://community.silabs.com/).
2. Log in with your account credentials.
3. Click your profile icon in the upper-right corner of the page.
4. Select **Notifications** from the dropdown menu.
5. In the Notifications section, go to the **My Product Notifications** tab to review historical Security and Software Advisory notifications
6. To manage your preferences, use the **Manage Notifications** tab to customize which product updates and advisories you receive.

For recommended settings, configurations, and usage guidelines, see [here](https://docs.silabs.com/btmesh/latest/btmesh-performance-overview/).

To learn more about the software in this release, dive into our [online documentation](https://docs.silabs.com/btmesh/11.0.0/btmesh-start/).

##### Help and Feedback

- Contact [Silicon Labs Support](https://www.silabs.com/support).
- To use our **Ask AI** tool to get answers, see the search field at the top of [this page](https://docs.silabs.com/).  
  > **Note:** **Ask AI** is experimental.
- Get help from our [developer community](https://community.silabs.com/s/?language=en_US).

#### Feature Matrix

Bluetooth Mesh SDK Version 11.0.0 implements the following specifications:

- Mesh Protocol 1.1
- Mesh Model 1.1
- Mesh Binary Large Object Transfer Model 1.0
- Mesh Device Firmware Update Model 1.0
- Ambient Light Sensor NLC Profile 1.0.1
- Basic Lightness Controller NLC Profile 1.0.1
- Basic Scene Selector NLC Profile 1.0.1
- Dimming Control NLC Profile 1.0.1
- Occupancy Sensor NLC Profile 1.0.1
- Energy Monitoring NLC Profile 1.0.1

[Supported Features](#supported-features) | [Unsupported Features](#unsupported-features)

##### Supported Features

<table>
    <thead>
        <tr>
            <th>Feature Name</th>
            <th>Description</th>
            <th>Quality</th>
            <th>Related API Names</th>
            <th>Supported Software Variants, Hardware, Modes, Host Interfaces</th>
            <th>Related Example Names</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                Mesh node
            </td>
            <td>
                Base functionality to implement a Mesh network node.
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-node">sl_btmesh_node</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                All examples (except btmesh_host_provisioner)
            </td>
        </tr>
        <tr>
            <td>
                Mesh provisioner
            </td>
            <td>
                Base functionality to implement a Mesh network provisioner.
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-provisioner">sl_btmesh_provisioner</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                <ul>
                    <li>Bluetooth Mesh - NCP Empty</li>
                    <li>btmesh_host_provisioner</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                Mesh GATT proxy
            </td>
            <td>
                GATT proxy connectivity
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy">sl_btmesh_proxy</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy-client">sl_btmesh_proxy_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy-server">sl_btmesh_proxy_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                All examples
            </td>
        </tr>
        <tr>
            <td>
                Mesh On-demand GATT proxy models
            </td>
            <td>
                Models for configuring and activating on-demand GATT proxy functionality
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-on-demand-private-proxy-client">sl_btmesh_on_demand_private_proxy_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-on-demand-private-proxy-client">sl_btmesh_on_demand_private_proxy_server</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-solicitation_config-client">sl_btmesh_solicitation_config_client</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Low Power Node
            </td>
            <td>
                Implementation of low-power node (a node that is mostly in power saving mode during operation)
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lpn">sl_btmesh_lpn</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                <ul>
                    <li>Bluetooth Mesh - SoC Switch CTL</li>
                    <li>Bluetooth Mesh - SoC Sensor Thermometer</li>
                    <li>Bluetooth Mesh - NLC Occupancy Sensor</li>
                    <li>Bluetooth Mesh - NLC Ambient Light Sensor</li>
                    <li>Bluetooth Mesh - NLC Dimming Control</li>
                    <li>Bluetooth Mesh - NLC Basic Scene Selector</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                Friend Node
            </td>
            <td>
                Implementation of friend node (a companion for a low-power node)
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-friend">sl_btmesh_friend</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                <ul>
                    <li>Bluetooth Mesh - SoC Sensor Client</li>
                    <li>Bluetooth Mesh - NLC Basic Lightness Controller</li>
                    <li>Bluetooth Mesh - SoC Light HSL</li>
                    <li>Bluetooth Mesh - SoC DFU Distributor</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                Mesh Configuration Client model
            </td>
            <td>
                Client model for remote configuration of mesh configuration parameters
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-config-client">sl_btmesh_config_client</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Silicon Labs configuration models
            </td>
            <td>
                Client and server models for remote configuration of Silicon Labs specific configuration parameters
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-silabs-config-client">sl_btmesh_silabs_config_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-silabs-config-server">sl_btmesh_silabs_config_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Mesh Health models
            </td>
            <td>
                Mesh health client and health server model implementations
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-health-client">sl_btmesh_health_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-health-server">sl_btmesh_health_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                All examples (except Bluetooth Mesh - SoC Empty)
            </td>
        </tr>
        <tr>
            <td>
                Mesh Generic and Lighting models
            </td>
            <td>
                Mesh generic and lighting client and server model implementations
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-generic-client">sl_btmesh_generic_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-generic-server">sl_btmesh_generic_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                All examples (except Bluetooth Mesh - SoC Empty)
            </td>
        </tr>
        <tr>
            <td>
                Mesh Lighting Control models
            </td>
            <td>
                Mesh lighting control (LC) client and server model implementations, for implementing sensor-driven dimming
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lc-client">sl_btmesh_lc_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lc-server">sl_btmesh_lc_server</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lc-setup-server">sl_btmesh_lc_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NLC Basic Lightness Controller
            </td>
        </tr>
        <tr>
            <td>
                Mesh Sensor models
            </td>
            <td>
                Mesh sensor client and server model implementations
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-sensor-client">sl_btmesh_sensor_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-sensor-server">sl_btmesh_sensor_server</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-sensor-server">sl_btmesh_sensor_setup_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                <ul>
                    <li>Bluetooth Mesh - SoC Sensor Thermometer</li>
                    <li>Bluetooth Mesh - SoC Sensor Client</li>
                    <li>Bluetooth Mesh - NLC Occupancy Sensor</li>
                    <li>Bluetooth Mesh - NLC Ambient Light Sensor</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                Mesh Scene models
            </td>
            <td>
                Mesh scene client and server model implementations
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-scene-client">sl_btmesh_scene_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-scene-server">sl_btmesh_scene_server</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-scene-server">sl_btmesh_scene_setup_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NLC Basic Scene Selector
            </td>
        </tr>
        <tr>
            <td>
                Mesh Scheduler models
            </td>
            <td>
                Mesh scheduler client and server model implementations
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-scheduler-client">sl_btmesh_scheduler_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-scheduler-server">sl_btmesh_scheduler_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NLC Basic Lightness Controller
            </td>
        </tr>
        <tr>
            <td>
                Mesh Time models
            </td>
            <td>
                Mesh time client and server model implementations
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-time-client">sl_btmesh_time_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-time-server">sl_btmesh_time_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NLC Basic Lightness Controller
            </td>
        </tr>
        <tr>
            <td>
                Mesh Vendor models
            </td>
            <td>
                Support for implementing vendor models in applications
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-vendor-model">sl_btmesh_vendor_model</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Mesh Remote Provisioning models
            </td>
            <td>
                Remote Provisioning client and server models
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-remote-provisioning-client">sl_btmesh_remote_provisioning_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-remote-provisioning-server">sl_btmesh_remote_provisioning_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                btmesh_host_provisioner
            </td>
        </tr>
        <tr>
            <td>
                Mesh SAR Configuration models
            </td>
            <td>
                Models for remote configuration of segmentation and Reassembly (SAR) parameters
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-sar-config-client">sl_btmesh_sar_config_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-sar-config-server">sl_btmesh_sar_config_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - SoC DFU Distributor
            </td>
        </tr>
        <tr>
            <td>
                Mesh Private Beacon models
            </td>
            <td>
                Models for remote configuration of private beaconing
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-private-beacon-client">sl_btmesh_private_beacon_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-private-beacon-server">sl_btmesh_private_beacon_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Mesh Large Composition Data models
            </td>
            <td>
                Models for large composition data retrieval
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lcd-client">sl_btmesh_lcd_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lcd-server">sl_btmesh_lcd_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Binary Large Object Transfer models
            </td>
            <td>
                Models for Binary Large Object Transfer (BLOB) functionality
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-mbt-client">sl_btmesh_mbt_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-mbt-server">sl_btmesh_mbt_server</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                All examples (except Bluetooth Mesh - SoC Empty)
            </td>
        </tr>
        <tr>
            <td>
                Device Firmware Update models
            </td>
            <td>
                Models for Device Firmware Update (DFU) functionality
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-fw-update-client">sl_btmesh_fw_update_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-fw-update-server">sl_btmesh_fw_update_server</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-fw-dist-client">sl_btmesh_fw_dist_client</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-fw-dist-server">sl_btmesh_fw_dist_server</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-fw-standalone-updater">sl_btmesh_fw_standalone_updater</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                All examples (except Bluetooth Mesh - SoC Empty)
            </td>
        </tr>
        <tr>
            <td>
                Test and diagnostic commands
            </td>
            <td>
                Test commands to aid development
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-diagnostic">sl_btmesh_diagnostic</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-test">sl_btmesh_test</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-ncp-fw-list">sl_btmesh_ncp_fw_list</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                Bluetooth Mesh - NCP Empty
            </td>
        </tr>
        <tr>
            <td>
                Migration support
            </td>
            <td>
                Commands to migrate existing device data to currently supported formats after firmware update
            </td>
            <td>
                GA
            </td>
            <td>
                <ul>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-migration">sl_btmesh_migration</a></li>
                    <li><a href="https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-model-migration">sl_btmesh_model_migration</a></li>
                </ul>
            </td>
            <td>
                All
            </td>
            <td>
                None
            </td>
        </tr>
    </tbody>
</table>

##### Unsupported Features

- Mesh Protocol: Directed Forwarding
- Mesh Protocol: Subnet Bridging
- Mesh Protocol: Opcode Aggregation
- Mesh Model: xyL Models

#### SDK Release and Maintenance Policy

See our [SDK Release and Maintenance Policy](https://www.silabs.com/developer-tools/sdk-release-and-maintenance-policy).

### Bluetooth Mesh SDK Version 11.0.0 - Release Notes (Jun 23, 2026)

[**Bluetooth Mesh Version 11.0.0**](.)

Bluetooth Mesh is a standards-based, many-to-many communication topology available for Bluetooth Low Energy (LE) devices, optimized for large-scale networks and ideally suited for building automation, sensor networks, and asset tracking.

Click [here](https://github.com/siliconlabs/simplicity_sdk/tags) for earlier releases.

#### Release Summary

[Key Features](#key-features) | [API Changes](#api-changes) | [Bug Fixes](#bug-fixes) | [Chip Enablement](#chip-enablement)

##### Key Features

- Updated supported compiler versions for GCC and IAR.
- Included selected bug fixes and quality improvements.

##### API Changes

- Added deinitialization APIs for the MBT Client and MBT Server models.
- Added experimental configuration parameters for Low Power Node (LPN).
- Deprecated the event-based device database query API.
- Deprecated the API used to set Light Control (LC) Server model publishing data.

##### Bug Fixes

- Fixed a potential null pointer dereference when SL_BTMESH_CONFIG_MAX_FOUNDATION_CLIENT_CMDS is set to 0.
- Fixed Sensor Client model handling of Format A values with a length of 0xF.
- Fixed Secure Network Beacon tallying when observing beacons and corrected the maximum interval between beacon transmissions.

##### Chip Enablement

None.

#### Key Features

[New Features](#new-features) | [Enhancements](#enhancements) | [Removed Features](#removed-features) | [Deprecated Features](#deprecated-features)

##### New Features

- Added support for GCC 14.2.
- Added support for IAR 9.70.4.

##### Enhancements

- Added support for runtime deinitialization of the MBT Client and MBT Server models, allowing applications to free resources when needed.
- Added experimental Low Power Node (LPN) friendship configuration parameters to provide greater control over the time an LPN spends listening for Friend Offers.

##### Removed Features

None.

##### Deprecated Features

None.

#### API Changes

[New APIs](#new-apis) | [Modified APIs](#modified-apis) | [Removed APIs](#removed-apis) | [Deprecated APIs](#deprecated-apis)

##### New APIs

|New API Signature|Deprecated API replaced by this (if any)|
|---|---|
|sl_status_t [sl_btmesh_mbt_client_deinit](https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-mbt-client#sl-btmesh-mbt-client-deinit)|N/A|
|sl_status_t [sl_btmesh_mbt_server_deinit](https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-mbt-server#sl-btmesh-mbt-server-deinit)|N/A|

##### Modified APIs

- Updated the dist_appkey_index parameter of sl_btmesh_fw_dist_client_start_distribution from an 8-bit unsigned integer to a 16-bit unsigned integer to support the full 12-bit application key index range.
- Exposed the following Low Power Node (LPN) friendship negotiation configuration parameters as an experimental feature:  
  - sl_btmesh_lpn_max_receive_window  
  - sl_btmesh_lpn_min_subscription_list_size  
  - sl_btmesh_lpn_min_friend_offer_rssi  
  - sl_btmesh_lpn_receive_window_factor  
  - sl_btmesh_lpn_rssi_factor  
  - sl_btmesh_lpn_friend_offer_listen_timeout_slack

##### Removed APIs

None.

##### Deprecated APIs

|Deprecated API Name|Planned Removal Date|
|---|---|
|[sl_btmesh_prov_list_ddb_entries](https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-prov#sl-btmesh-prov-list-ddb-entries)|Dec 2026|
|[sl_btmesh_lc_server_set_publish_mask](https://docs.silabs.com/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-lc-server#sl-btmesh-lc-server-set-publish-mask)|Dec 2026|

#### Bug Fixes

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Issue Description</th>
            <th>GitHub / Salesforce Reference (if any)</th>
            <th>Affected Software Variants, Hardware, Modes, Host Interfaces</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                361685
            </td>
            <td>
                Fixed an issue with tallying incoming Secure Network Beacons and capped the maximum time before a beacon is emitted.
            </td>
            <td>
                None
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                1565611
            </td>
            <td>
                Fixed an issue where configuring zero Foundation Model requests for allocation did not allocate an array, but certain code paths still attempted to access the array during periodic task execution and deinitialization cleanup.
            </td>
            <td>
                None
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                1630873
            </td>
            <td>
                Fixed an issue where the Sensor Client model interpreted the Format A length value 0xF as zero, resulting in parsing errors for received messages.
            </td>
            <td>
                None
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                1642800
            </td>
            <td>
                Fixed an issue in the Bluetooth Mesh Lighting Server where the Generic Level Move handler incorrectly evaluated state_changed, causing move requests with no effect on the current state to be reported as state changes. The check now correctly compares the current state against the move target, ensuring that no-op move requests are properly identified.
            </td>
            <td>
                None
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
    </tbody>
</table>

#### Chip Enablement

None.

#### Application Example Changes

[New Examples](#new-examples) | [Modified Examples](#modified-examples) | [Removed Examples](#removed-examples) | [Deprecated Examples](#deprecated-examples)

##### New Examples

None.

##### Modified Examples

None.

##### Removed Examples

None.

##### Deprecated Examples

None.

#### Known Issues and Limitations

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Issue or Limitation Description</th>
            <th>GitHub / Salesforce Reference (if any)</th>
            <th>Workaround (if any)</th>
            <th>Affected Software Variants, Hardware, Modes, Host Interfaces</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                401550
            </td>
            <td>
                No BGAPI event for segmented message handling failure.
            </td>
            <td>
                212392, 214429, 216665
            </td>
            <td>
                Application needs to deduce failure from timeout / lack of
                application layer response; for vendor models, an API has
                been provided.
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                454059
            </td>
            <td>
                A large number of key refresh state change events are
                generated at the end of KR process, and that may flood NCP
                queue.
            </td>
            <td>
                None
            </td>
            <td>
                Increase NCP queue length in the project.
            </td>
            <td>
                NCP interface; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                454061
            </td>
            <td>
                Slight performance degradation compared to 1.5 in round-trip
                latency tests was observed.
            </td>
            <td>
                None
            </td>
            <td>
                None
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                624514
            </td>
            <td>
                Issue with re-establishing connectable advertising if all
                connections have been active and GATT proxy is in use.
            </td>
            <td>
                235615
            </td>
            <td>
                Allocate one more connection than is needed.
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                841360
            </td>
            <td>
                Poor performance of segmented message transmission over GATT
                bearer.
            </td>
            <td>
                283876
            </td>
            <td>
                Ensure that the underlying BLE connection’s Connection
                interval is short; ensure that ATT MTU is large enough to
                fit a full Mesh PDU; tune the minimum connection event
                length to allow multiple LL packets to be transmitted per
                connection event.
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                1204017
            </td>
            <td>
                Distributor is not able to handle parallel self FW
                Update and FW Upload.
            </td>
            <td>
                None
            </td>
            <td>
                Don’t run self FW update and FW upload in parallel.
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
        <tr>
            <td>
                1226127
            </td>
            <td>
                Host provisioner example can be stuck when it
                starts to provision a second node.
            </td>
            <td>
                None
            </td>
            <td>
                Restart the host provisioner app before provisioning the second
                node.
            </td>
            <td>
                All; generic software issue
            </td>
        </tr>
    </tbody>
</table>

### Bluetooth Mesh iOS ADK Version 11.0.0 - Release Notes (Jun 23, 2026)

[**Bluetooth Mesh Version 11.0.0**](.)

This application implements Bluetooth Mesh networking for the iOS operating system. The Bluetooth Mesh by Silicon Labs application can be used to provision Bluetooth Mesh capable devices and add them as nodes into a Bluetooth Mesh network.

Click [here](https://github.com/SiliconLabsSoftware/sisdk-release/releases) for earlier releases.

#### Release Summary

[Key Features](#key-features) | [API Changes](#api-changes) | [Bug Fixes](#bug-fixes) | [Chip Enablement](#chip-enablement)

##### Key Features

None.

##### API Changes

None.

##### Bug Fixes

None.

##### Chip Enablement

None.

#### Key Features

[New Features](#new-features) | [Enhancements](#enhancements) | [Removed Features](#removed-features) | [Deprecated Features](#deprecated-features)

> **Note:** See [Feature Matrix](#feature-matrix) for a list of any applicable APIs, examples, software variants, modes, hardware, and host interfaces applicable for each feature.

##### New Features

None.

##### Enhancements

None.

##### Removed Features

None.

##### Deprecated Features

None.

#### API Changes

[New APIs](#new-apis) | [Modified APIs](#modified-apis) | [Removed APIs](#removed-apis) | [Deprecated APIs](#deprecated-apis)

##### New APIs

None.

##### Modified APIs

None.

##### Removed APIs

None.

##### Deprecated APIs

None.

#### Bug Fixes

None.

#### Chip Enablement

None.

#### Application Example Changes

[New Examples](#new-examples) | [Modified Examples](#modified-examples) | [Removed Examples](#removed-examples) | [Deprecated Examples](#deprecated-examples)

##### New Examples

None.

##### Modified Examples

None.

##### Removed Examples

None.

##### Deprecated Examples

None.

#### Known Issues and Limitations

None.

#### Impact of Release Changes

None.

#### Using This Release

##### What's in the Release?

- [iOS mobile app](https://apps.apple.com/us/app/bluetooth-mesh-by-silicon-labs/id1411352948).
- [Application Development Kit](https://apps.apple.com/us/app/xcode/id497799835?mt=12).
- [Application examples](https://docs.silabs.com/mobile-apps/3.0.2/mobile-apps-demos-overview/).

##### Compatible Software

|Software|Compatible version or variant|
|---|---|
|ADK|11.0.0|
|BTMESH SDK|11.0.0|
|WiSeConnect|4.1.0|

##### Installation and Use

To upgrade your application with this release, download from [Apple App Store](https://apps.apple.com/us/app/bluetooth-mesh-by-silicon-labs/id1411352948).

To Download source code from [GitHub](https://github.com/SiliconLabsSoftware/sisdk-release).

To kick start your development, see our [Developer's Guide](https://docs.silabs.com/btmesh/latest/bluetooth-mesh-for-android-and-ios-adk/).

For information about Secure Vault Integration, see [Secure Vault](https://www.silabs.com/security/secure-vault).

To review Security and Software Advisory notifications and manage your notification preferences:

1. Go to [https://community.silabs.com/](https://community.silabs.com/).
2. Log in with your account credentials.
3. Click your profile icon in the upper-right corner of the page.
4. Select **Notifications** from the dropdown menu.
5. In the Notifications section, go to the **My Product Notifications** tab to review historical Security and Software Advisory notifications
6. To manage your preferences, use the **Manage Notifications** tab to customize which product updates and advisories you receive.

##### Help and Feedback

- Contact [Silicon Labs Support](https://www.silabs.com/support).
- Use our [Ask AI](https://www.silabs.com/support) tool to get answers.
- Log an issue in the [GitHub repo](https://github.com/siliconlabs).
- See our open-source [contribution guidelines](https://github.com/siliconlabs).
- Get help from our [developer community](https://community.silabs.com/s/?language=en_US).

#### Feature Matrix

##### Supported Features

<table>
    <thead>
        <tr>
            <th>Feature Name</th>
            <th>Description</th>
            <th>Quality</th>
            <th>Related API Name(S)</th>
            <th>Supported Software Variant(s)</th>
            <th>Supported Mode(s)</th>
            <th>Supported OPN(s) / Board(s) / OPN Combination(s)</th>
            <th>Supported Host Interface(s)</th>
            <th>Application Examples</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                NLC
            </td>
            <td>
                Discover, Provision, Set functionality and control on NLC Devices
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                None
            </td>
            <td>
                "Bluetooth Mesh - SoC Light HSL" example from Simplicity Studio
            </td>
        </tr>
        <tr>
            <td>
                Non NLC
            </td>
            <td>
                Discover, Provision, Set functionality and control on Non NLC Devices
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                None
            </td>
            <td>
                "Bluetooth Mesh - NLC Basic Lightness Controller" example from Simplicity Studio
            </td>
        </tr>
        <tr>
            <td>
                OTA Update
            </td>
            <td>
                OTA wirelessly updates a device's firmware via Bluetooth without needing a physical connection.
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                UART
            </td>
            <td>
                "NLC Basic Lightness Controller &amp; NLC Basic Lightness Controller" example from Simplicity Studio
            </td>
        </tr>
        <tr>
            <td>
                IOP Test
            </td>
            <td>
                IOP Test verifies that different systems or devices can work together and exchange information effectively.
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                UART
            </td>
            <td>
                "Bluetooth Mesh - IOP Test - Friend node, Bluetooth Mesh - IOP Test - LPN node, Bluetooth Mesh - IOP Test - Proxy node, Bluetooth Mesh - IOP Test - Relay node" example from Simplicity Studio
            </td>
        </tr>
    </tbody>
</table>

##### Unsupported Features

None.

#### SDK Release and Maintenance Policy

See our [SDK Release and Maintenance Policy](https://www.silabs.com/developer-tools/sdk-release-and-maintenance-policy).

### Bluetooth Mesh Android ADK Version 11.0.0 - Release Notes (Jun 23, 2026)

[**Bluetooth Mesh Version 11.0.0**](.)

This application implements Bluetooth Mesh networking for the Android operating system. The Bluetooth Mesh by Silicon Labs application can be used to provision Bluetooth Mesh capable devices and add them as nodes into a Bluetooth Mesh network.

Click [here](https://github.com/SiliconLabsSoftware/sisdk-release/releases) for earlier releases.

#### Release Summary

[Key Features](#key-features) | [API Changes](#api-changes) | [Bug Fixes](#bug-fixes) | [Chip Enablement](#chip-enablement)

##### Key Features

None.

##### API Changes

None.

##### Bug Fixes

None.

##### Chip Enablement

None.

#### Key Features

[New Features](#new-features) | [Enhancements](#enhancements) | [Removed Features](#removed-features) | [Deprecated Features](#deprecated-features)

> **Note:** See [Feature Matrix](#feature-matrix) for a list of any applicable APIs, examples, software variants, modes, hardware, and host interfaces applicable for each feature.

##### New Features

None.

##### Enhancements

None.

##### Removed Features

None.

##### Deprecated Features

None.

#### API Changes

[New APIs](#new-apis) | [Modified APIs](#modified-apis) | [Removed APIs](#removed-apis) | [Deprecated APIs](#deprecated-apis)

##### New APIs

None.

##### Modified APIs

None.

##### Removed APIs

None.

##### Deprecated APIs

None.

#### Bug Fixes

None.

#### Chip Enablement

None.

#### Application Example Changes

[New Examples](#new-examples) | [Modified Examples](#modified-examples) | [Removed Examples](#removed-examples) | [Deprecated Examples](#deprecated-examples)

##### New Examples

None.

##### Modified Examples

None.

##### Removed Examples

None.

##### Deprecated Examples

None.

#### Known Issues and Limitations

None.

#### Impact of Release Changes

None.

#### Using This Release

##### What's in the Release?

- [Android mobile app](https://play.google.com/store/apps/details?id=com.siliconlabs.bluetoothmesh).
- [Application Development Kit](https://developer.android.com/codelabs/basic-android-kotlin-compose-install-android-studio#0).
- [Application examples](https://docs.silabs.com/mobile-apps/3.0.2/mobile-apps-demos-overview/.)

##### Compatible Software

|Software|Compatible version or variant|
|---|---|
|ADK|11.0.0|
|BTMESH SDK|11.0.0|
|WiSeConnect|4.1.0|

##### Installation and Use

To upgrade your application with this release, download from [Play store](https://play.google.com/store/apps/details?id=com.siliconlabs.bluetoothmesh).

To Download source code from [GitHub](https://github.com/SiliconLabsSoftware/sisdk-release).

to kick start your development, see our [Developer's Guide](https://www.silabs.com/documents/public/application-notes/an1200-1-bluetooth-mesh-2x-for-android-and-ios-adk.pdf).

For information about Secure Vault Integration, see [Secure Vault](https://www.silabs.com/security/secure-vault).

To review Security and Software Advisory notifications and manage your notification preferences:

1. Go to [https://community.silabs.com/](https://community.silabs.com/).
2. Log in with your account credentials.
3. Click your profile icon in the upper-right corner of the page.
4. Select **Notifications** from the dropdown menu.
5. In the Notifications section, go to the **My Product Notifications** tab to review historical Security and Software Advisory notifications
6. To manage your preferences, use the **Manage Notifications** tab to customize which product updates and advisories you receive.

##### Help and Feedback

- Contact [Silicon Labs Support](https://www.silabs.com/support).
- Use our [Ask AI](https://www.silabs.com/support) tool to get answers.
- Log an issue in the [GitHub repo](https://github.com/siliconlabs).
- See our open-source [contribution guidelines](https://github.com/siliconlabs).
- Get help from our [developer community](https://community.silabs.com/s/?language=en_US).

#### Feature Matrix

##### Supported Features

<table>
    <thead>
        <tr>
            <th>Feature Name</th>
            <th>Description</th>
            <th>Quality</th>
            <th>Related API Name(S)</th>
            <th>Supported Software Variant(s)</th>
            <th>Supported Mode(s)</th>
            <th>Supported OPN(s) / Board(s) / OPN Combination(s)</th>
            <th>Supported Host Interface(s)</th>
            <th>Application Examples</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                NLC
            </td>
            <td>
                Discover, Provision, Set functionality and control on NLC Devices
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                None
            </td>
            <td>
                "Bluetooth Mesh - SoC Light HSL" example from Simplicity Studio
            </td>
        </tr>
        <tr>
            <td>
                Non NLC
            </td>
            <td>
                Discover, Provision, Set functionality and control on Non NLC Devices
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                None
            </td>
            <td>
                "Bluetooth Mesh - NLC Basic Lightness Controller" example from Simplicity Studio
            </td>
        </tr>
        <tr>
            <td>
                OTA Update
            </td>
            <td>
                OTA wirelessly updates a device's firmware via Bluetooth without needing a physical connection.
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                UART
            </td>
            <td>
                "NLC Basic Lightness Controller &amp; NLC Basic Lightness Controller" example from Simplicity Studio
            </td>
        </tr>
        <tr>
            <td>
                IOP Test
            </td>
            <td>
                IOP Test verifies that different systems or devices can work together and exchange information effectively.
            </td>
            <td>
                Sample Demo
            </td>
            <td>
                None
            </td>
            <td>
                Secure connectivity firmware for BLE
            </td>
            <td>
                SoC
            </td>
            <td>
                EFR32xG24
            </td>
            <td>
                UART
            </td>
            <td>
                "Bluetooth Mesh - IOP Test - Friend node, Bluetooth Mesh - IOP Test - LPN node, Bluetooth Mesh - IOP Test - Proxy node, Bluetooth Mesh - IOP Test - Relay node" example from Simplicity Studio
            </td>
        </tr>
    </tbody>
</table>

##### Unsupported Features

None.

#### SDK Release and Maintenance Policy

See our [SDK Release and Maintenance Policy](https://www.silabs.com/developer-tools/sdk-release-and-maintenance-policy).

## Getting Started

### Bluetooth Mesh Quick-Start Guide for SDK v2.x and v3.x (PDF)

- [Bluetooth Mesh Quick-Start Guide for SDK v2.x and v3.x (PDF)](https://www.silabs.com/documents/public/quick-start-guides/qsg176-bluetooth-mesh-sdk-v2x-quick-start-guide.pdf)
### Quick Start Guide for SDK v4.x and Higher

#### Getting Started with Silicon Labs Bluetooth Mesh Development

Get started with Bluetooth Mesh development using the Bluetooth Mesh Software Development Kit (SDK) and Simplicity Studio® 5 with a compatible wireless starter kit. This section includes step-by-step instructions to demonstrate a basic Bluetooth Mesh network. In this demo, three devices are provisioned as two Lights and one Switch. The mobile application allows the control of either the group of Lights or an individual Light. By pressing buttons on the Switch node, you can control the ON/OFF states and brightness for all lights in the same group. The demo is open-sourced and provides a good demonstration of a basic Bluetooth Mesh network.

This section contains information about features specific to Bluetooth Mesh specification version 1.1. If you are working with an earlier version of the specification, see [QSG176: Bluetooth® Mesh Quick-Start Guide for SDK v2.x and 3.x](https://www.silabs.com/documents/public/quick-start-guides/qsg176-bluetooth-mesh-sdk-v2x-quick-start-guide.pdf). For a more elaborate networked lighting setup, see [Networked Lighting Control](/btmesh/11.0.0/btmesh-networked-lighting-control).

The Bluetooth Mesh mobile app is intended to demonstrate the Silicon Labs Bluetooth Mesh technology together with the Bluetooth Mesh SDK sample apps. The mobile app is a reference app for the Bluetooth Mesh mobile ADK, but it should not be taken as a starting point for customers to create their own mobile apps. For guidance on creating mobile apps with the Bluetooth Mesh mobile ADK, refer to [iOS and Android ADK for Bluetooth® Mesh SDK 2.x and Higher](/btmesh/11.0.0/bluetooth-mesh-for-android-and-ios-adk).

![WSTK with EFR32xG24B board](/btmesh-getting-started-overview/10.0.0/images/sld433-image9.png)  ![Mobile app](/btmesh-getting-started-overview/10.0.0/images/sld433-image10.png)

##### Prerequisites

The Silicon Labs Bluetooth mesh lighting demonstration is designed to illustrate Bluetooth mesh operation without any need to config- ure or compile software. To get started with the Bluetooth mesh demo, do the following.

###### Order Development Kit(s)

The Blue Gecko Bluetooth SoC Wireless Starter Kit is the easiest and fastest way to start the evaluation and development of your own Bluetooth mesh applications. To get started with the Bluetooth mesh demo, you need to have **three (3)** EFR32 mainboards and radio boards. These can be obtained by ordering any of the Wireless Starter Kit options below.

**Option 1:** PN: SLWSTK6020B kit: [https://www.silabs.com/development-tools/wireless/bluetooth/efr32bg-bluetooth-soc-starter-kit](https://www.silabs.com/development-tools/wireless/bluetooth/efr32bg-bluetooth-soc-starter-kit)

**Option 2:** PN: SLWSTK6000B kit: [https://www.silabs.com/development-tools/wireless/zigbee/efr32mg-zigbee-thread-starter-kit](https://www.silabs.com/development-tools/wireless/zigbee/efr32mg-zigbee-thread-starter-kit)

**Option 3:** PN: SLWSTK6006A kit: [https://www.silabs.com/development-tools/wireless/efr32xg21-wireless-starter-kit](https://www.silabs.com/development-tools/wireless/efr32xg21-wireless-starter-kit)

**Option 4:** PN: SLWSTK6021A kit: [https://www.silabs.com/development-tools/wireless/efr32xg22-wireless-starter-kit](https://www.silabs.com/development-tools/wireless/efr32xg22-wireless-starter-kit)

**Option 5:** PN: xG24-PK6010A kit: [https://www.silabs.com/development-tools/wireless/efr32xg24-pro-kit-20-dbm](https://www.silabs.com/development-tools/wireless/efr32xg24-pro-kit-20-dbm)

**Option 6:** PN: xG27-PK6017A kit: [https://www.silabs.com/development-tools/wireless/efr32xg27-pro-kit-8-dbm](https://www.silabs.com/development-tools/wireless/efr32xg27-pro-kit-8-dbm)

**Note:** Some of these are starter-kits with multiple boards included, and some have only one board included.

This demo requires either **EFR32BG27**, **EFR32MG27**, **EFR32BG24**, **EFR32MG24**, **EFR32MG21**, **EFR32BG13**, **EFR32MG13**, **EFR32BG12**, or **EFR32MG12** radio boards. **EFR32MG22** and **EFR32BG22** can be used but are suggested for Low Power Nodes only. If you already have the mainboards, you can purchase the required radio boards on [www.silabs.com](https://www.silabs.com/products/development-tools/wireless/wireless-radio-boards#bluetooth).

###### Install Simplicity Studio and the GSDK

The Gecko SDK (GSDK) is the suite of Silicon Labs SDKs that includes the Bluetooth mesh SDK. To quickly get started with the GSDK and Bluetooth mesh, start by installing Simplicity Studio, which will set up your development environment. Go to: [https://www.silabs.com/developer-tools/simplicity-studio](https://www.silabs.com/developer-tools/simplicity-studio) to download the latest SSv5 version compatible with your computer’s operating system. Simplicity Studio 5 includes everything needed for IoT product development with Silicon Labs devices, including a resource and project launcher, software configuration tools, full IDE with GNU toolchain, and analysis tools.

Alternatively, Gecko SDK may be installed manually by downloading or cloning the latest from GitHub. See [https://github.com/SiliconLabs/gecko_sdk](https://github.com/SiliconLabs/gecko_sdk) for more information.

This section focuses on development and use in the SSv5 environment. It assumes that you are generally familiar with the SSv5 Launcher perspective. SSv5 installation and getting started instructions, along with a set of detailed references, can be found in the online [Simplicity Studio 5 User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/) and through the SSv5 help menu.

###### Download the Mobile App

Download the Bluetooth Mesh by Silicon Labs mobile app from the App Store or Google Play.

**App Store**: [https://apps.apple.com/us/app/bluetooth-mesh-by-silicon-labs/id1411352948](https://apps.apple.com/us/app/bluetooth-mesh-by-silicon-labs/id1411352948)

**Google Play**: [https://play.google.com/store/apps/details?id=com.siliconlabs.bluetoothmesh&hl=en](https://play.google.com/store/apps/details?id=com.siliconlabs.bluetoothmesh&hl=en)

**Note:** The minimum requirement for the smartphone is Android 11 (API30) or iOS 14.

###### Documentation

Hardware-specific documentation may be accessed through links on the part Overview tab in Simplicity Studio 5.

![Overview tab](/btmesh-getting-started-overview/10.0.0/images/sld433-image11.png)

SDK documentation, User’s Guides, and other references are available through the Documentation tab.

![Documentation tab](/btmesh-getting-started-overview/10.0.0/images/sld433-image12.png)

Key documentation for the Bluetooth Mesh SDK is summarized as follows:

- [AN1098: Understanding the Silicon Labs Bluetooth Mesh Lighting Demonstration in SDK v1.x](https://www.silabs.com/documents/public/application-notes/an1098-understanding-bluetooth-mesh-lighting-demo.pdf)
- [Bluetooth LE Fundamentals](/btmesh/11.0.0/bluetooth-le-fundamentals)
- [QSG139: Bluetooth SDK v2.x Quick Start Guide](https://www.silabs.com/documents/public/quick-start-guides/qsg139-getting-started-with-bluetooth.pdf)
- [UG144: EFR32BG1 2.4 GHz 10.5 dBm Radio Board User's Guide](https://www.silabs.com/documents/public/user-guides/ug144-brd4100a-user-guide.pdf)
- [UG122: BGM111 Bluetooth Module Radio Board User's Guide](https://www.silabs.com/documents/public/user-guides/ug122-brd4300a-user-guide.pdf)
- [UG250: Thunderboard Sense User's Guide](https://www.silabs.com/documents/public/user-guides/ug250-tb001-user-guide.pdf)
- [UG136: Silicon Labs Bluetooth C Application Developer's Guide for SDK v2.x](https://www.silabs.com/documents/public/user-guides/ug136-ble-c-soc-dev-guide.pdf)
- [Bluetooth Profile Toolkit Developer's Guide](/btmesh/11.0.0/bluetooth-profile-toolkit-developers-guide)
- [AN1042: Using the v2.x Silicon Labs Bluetooth Stack in Network Co-Processor Mode](https://www.silabs.com/documents/public/application-notes/an1042-bt-ncp-mode.pdf)
- [UG266: Silicon Labs Gecko Bootloader User’s Guide](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)
- [Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](/btmesh/11.0.0/using-gecko-bootloader-with-bluetooth-apps)

###### Obtaining Support

You can access the Silicon Labs support portal at [https://www.silabs.com/support](https://www.silabs.com/support) through Simplicity Studio Resources, or on the Simplicity Studio 5 welcome page under Learn and Support.

![Learn and Support section](/btmesh-getting-started-overview/10.0.0/images/sld433-image13.png)

#### About the Bluetooth Mesh SDK

The Silicon Labs Bluetooth mesh stack is an advanced Bluetooth mesh protocol stack implementing the Bluetooth mesh standard. It can run alongside the Bluetooth Low Energy (LE) stack, using a common link layer, which allows using LE features in parallel. The Silicon Labs Bluetooth mesh stack is meant for Silicon labs Wireless Gecko SoCs and modules.

The Silicon Labs Bluetooth mesh stack provides multiple APIs for the developer to access the Bluetooth mesh functionality. Two modes are supported.

1. Standalone mode (also referenced as SoC mode), where both the Bluetooth mesh stack and the application run in a Wireless Gecko SoC or module. The application can be developed with the C programming language. It can be running on bare metal or can use an operating system such as FreeRTOS or Micrium OS.  
   ![Standalone mode](/btmesh-getting-started-overview/10.0.0/images/sld433-image14.png)
2. Network Co-Processor (NCP) mode, where the Bluetooth stack runs in a Wireless Gecko and the application runs on a separate host MCU. For this use case, the Bluetooth stack can be configured into NCP mode where the API is exposed over a serial interface such as UART. For more information, see [Using the Silicon Labs Bluetooth Stack in Network Co-Processor Mode](/btmesh/11.0.0/bluetooth-network-coprocessor-mode).  
   ![NCP mode](/btmesh-getting-started-overview/10.0.0/images/sld433-image15.png)

##### Bluetooth Mesh Stack Features

The features of the Silicon Labs Bluetooth mesh stack are listed in the following table. For details on the features of the Bluetooth **Low Energy** stack, refer to the [Bluetooth Getting Started Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-getting-started-overview/).

|**Feature**|**Value and Comment**|
|---|---|
|Bluetooth mesh version|Bluetooth mesh 1.1|
|Node types|Relay, Proxy, Friend, and Low Power Node (LPN)|
|Provisioning bearers|PB-ADV<br/><br/>PB-GATT<br/><br/>PB-Remote (Remote Provisioning, RPR)|
|GATT services|Proxy<br/><br/>Provisioning|
|Security|ECDH<br/><br/>AES-128 encryption, authentication, and obfuscation<br/><br/>OoB authentication<br/><br/>Certificate-based provisioning<br/><br/>Replay protection<br/><br/>Key refresh (reject list)|
|Host (NCP) interfaces|4-wire UART with RTS/CTS control or 2-wire UART without RTS/CTS GPIOs for sleep and wake-up management<br/><br/>Secure NCP option for data encryption between NCP target and host|
|Wi-Fi Coexistence|Using Packet Trace Arbitration (PTA)|
|Bootloaders|Secure Gecko Bootloader supporting authenticated and encrypted updates over OTA (over GATT) or UART and Secure Boot. The Gecko Bootloader also supports flash partitioning and both internal and external (SPI) flash.|
|Non-volatile memory|EFR32[B|M]G12, EFR32[B|M]G13: NVM3 or Persistent Store (PS). (Note: Example applications in the SDK use NVM3 by default.)<br/><br/>EFR32[B|M]G21, EFR32[B|M]G22, EFR32[B|M]G24, EFR32[B|M]G27: NVM3|
|Mesh 1.1 new features|Device Firmware Update (Mesh DFU), Mesh Blob Transfer, Mesh Remote Provisioning, Certificate-Based Provisioning, Mesh Private Beacons, Enhanced Device Composition Data page, i.e. Large Composition Data, Configurable SAR timing, Proxy Service Solicitation, On-Demand Private Proxy|

###### Supported Models

|**Model**|**SIG Model ID**|**Example App (1)**|
|---|---|---|
|**Model Group: NA**| | |
|Vendor|N/A|N/A|
|**Model Group: Foundation**| | |
|Configuration Server|0x0000|All|
|Configuration Client|0x0001|BT Mesh Host Provisioner|
|Health Server|0x0002|N/A|
|Health Client|0x0003|N/A|
|Remote Provisioning Server|0x0004|N/A|
|Remote Provisioning Client|0x0005|N/A|
|Mesh Private Beacon Server|0x000A|N/A|
|Mesh Private Beacon Client|0x000B|N/A|
|**Model Group: Generic**| | |
|Generic OnOff Server|0x1000|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller, PyBGAPI NCP Host Light|
|Generic OnOff Client|0x1001|SoC Switch CTL, SoC Switch CTL Low Power, NLC Dimming Control, NLC Dimming Control Low Power, PyBGAPI NCP Host Switch|
|Generic Level Server|0x1002|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller, PyBGAPI NCP Host Light|
|Generic Level Client|0x1003|NLC Basic Scene Selector, NLC Dimming Control|
|Generic Default Transition Time Server|0x1004|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Generic Default Transition Time Client|0x1005|N/A|
|Generic Power OnOff Server|0x1006|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Generic Power OnOff Setup Server|0x1007|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Generic Power OnOff Client|0x1008|N/A|
|Generic Power Level Server|0x1009|N/A|
|Generic Power Level Setup Server|0x100A|N/A|
|Generic Power Level Client|0x100B|N/A|
|Generic Battery Server|0x100C|N/A|
|Generic Battery Client|0x100D|N/A|
|Generic Location Server|0x100E|N/A|
|Generic Location Setup Server|0x100F|N/A|
|Generic Location Client|0x1010|N/A|
|Generic Admin Property Server|0x1011|N/A|
|Generic Manufacturer Property Server|0x1012|N/A|
|Generic User Property Server|0x1013|N/A|
|Generic Client Property Server|0x1014|N/A|
|Generic Property Client|0x1015|N/A|
|**Model Group: Sensors**| | |
|Sensor Server|0x1100|SoC Sensor Thermometer, NLC Occupancy Sensor, NLC Ambient Light Sensor|
|Sensor Setup Server|0x1101|SoC Sensor Thermometer, NLC Occupancy Sensor, NLC Ambient Light Sensor|
|Sensor Client|0x1102|SoC Sensor Client|
|**Model Group: Times and Scenes**| | |
|Time Server|0x1200|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Time Setup Server|0x1201|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Time Client|0x1202|N/A|
|Scene Server|0x1203|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller, PyBGAPI NCP Host Light|
|Scene Setup Server|0x1204|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Scene Client|0x1205|SoC Switch CTL, SoC Switch CTL Low Power, NLC Basic Scene Selector, PyBGAPI NCP Host Switch|
|Scheduler Server|0x1206|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Scheduler Setup Server|0x1207|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Scheduler Client|0x1208|N/A|
|**Model Group: Lighting**| | |
|Light Lightness Server|0x1300|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller, PyBGAPI NCP Host Light|
|Light Lightness Setup Server|0x1301|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Light Lightness Client|0x1302|SoC Switch CTL, SoC Switch CTL Low Power, PyBGAPI NCP Host Switch|
|Light CTL Server|0x1303|SoC Light CTL, PyBGAPI NCP Host Light SoC Light CTL|
|Light CTL Setup Server|0x1304|SoC Light CTL|
|Light CTL Client|0x1305|SoC Switch CTL, SoC Switch CTL Low Power, PyBGAPI NCP Host Switch|
|Light CTL Temperature Server|0x1306|SoC Light CTL|
|Light HSL Server|0x1307|SoC Light HSL|
|Light HSL Setup Server|0x1308|SoC Light HSL|
|Light HSL Client|0x1309|N/A|
|Light HSL Hue Server|0x130A|SoC Light HSL|
|Light HSL Saturation Server|0x130B|SoC Light HSL|
|Light LC Server|0x130F|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Light LC Setup Server|0x1310|SoC Light CTL, SoC Light HSL, NLC Basic Lightness Controller|
|Light LC Client|0x1311|N/A|
|**Model Group: Firmware Update**| | |
|BLOB Transfer Server|0x1400|SoC DFU Distributor|
|BLOB Transfer Client|0x1401|N/A|
|Firmware Update Server|0x1402|SoC DFU Distributor|
|Firmware Update Client|0x1403|N/A|
|Firmware Distribution Server|0x1404|SoC DFU Distributor|
|Firmware Distribution Client|0x1405|SoC DFU Distributor|

(1) In Simplicity Studio 5, example app names are preceded with "Bluetooth Mesh -".

**Additional Models for Mesh 1.1 features**: Remote Provisioning, Private Beacon, On-demand Private Proxy, SAR Configuration, Large Composition Data, Solicitation PDU Replay Protection List Configuration, Firmware Distribution, Firmware Update, BLOB Transfer.

##### Bluetooth Mesh Stack Limitations

|**Component**|**Feature**|**Value and Comment**|
|---|---|---|
|Mesh Node (EFR32)|Network Keys on a node(1)|Maximum of 7|
|Application Keys on a node|Maximum of 8| |
|Number of nodes that can be communicated with|Maximum of 4096 (depending on available RAM and NVM3)| |
|Concurrent segmented messages being received|Maximum of 255 (depending on available RAM)| |
|Concurrent segmented messages being sent|Maximum of 255 (depending on available RAM)| |
|Parallel provisioning sessions|Maximum of 1| |
|Faults reported on the health server|Maximum of 5| |
|Mesh Provisioner (EFR32)|Maximum number of supported nodes|512|
|Maximum number of network keys per node|Maximum of 7| |
|Maximum number of application keys per node|Maximum of 8| |
|Replay protection list size|Maximum of 4096 (depending on available RAM and NVM3. Network size limit is still 512)| |
|Parallel provisioning sessions|1| |
|Concurrent key refresh operations|Maximum of 16| |
|Mesh Provisioner (ADK)|Replay protection list size (max network node count)|32768|
|Maximum number of network keys per node|Maximum of 7| |
|Maximum number of application keys per node|Maximum of 8| |
|Parallel provisioning sessions|1| |

(1) The node belongs to a single network, but the network may have multiple network keys to encrypt the traffic.

#### About Demos and Examples

Because starting application development from scratch is difficult, the Bluetooth Mesh SDK comes with a number of built-in demos and examples covering the most frequent use cases, as shown in the following figure. Demos are pre-built application images that you can run immediately. Software examples can be modified before building the application image. Demos with the same name as Software examples are built from their respective example. Click **View Project Documentation** to see additional information about some examples. This is also displayed on a **readme** tab when you create a project based on the example.

Use the **Demos** and **Example Projects** switches to filter on only examples or only demos. Demos are also noted by the blue Demo tag in the upper left of the card.

![Example projects and demos](/btmesh-getting-started-overview/10.0.0/images/sld433-image16.png)

**Note:** The demos and examples you see are determined by the part selected. If you are using a custom solution with more than one part, click the part you are working with to see only the items applicable to that part. Some functionality in these demos and examples depends on the features of the part, such as whether or not an LCD is included on the mainboard.

To download and run a demo on your device, click **[RUN]** on the desired demo card. The demo automatically downloads to the selected device.

##### Bluetooth Mesh Examples and Demos

The following examples are provided.

Examples with (**D**) in their names have a matching pre-built demo for some devices. Demos contain both a bootloader and the application. The compatible bootloader information provided for some examples is for later software development purposes. See [Getting Started with Application Development](05-btmesh-app-development) for more information.

Typically examples are running on bare metal. Examples with (**F**) in their names are using FreeRTOS and with (**M**) are using Micrium OS, both with selected devices.

The **NCP** examples require the BGAPI UART DFU Bootloader. The rest require one of the Internal Storage Bootloader (single image) variants, depending on device memory.

###### Bare minimum examples

- **Bluetooth Mesh - SoC Empty (F, M)**: Demonstrates the bare minimum needed for a Bluetooth Mesh C application. The application starts Unprovisioned Device Beaconing after booting, then waits to be provisioned.
- **Bluetooth Mesh - NCP Empty (D, F, M)**: An NCP Target C application that makes it possible for the NCP Host Controller to access the Bluetooth Mesh stack via UART. It provides access to the host layer via BGAPI and not to the link layer via HCI.  
  - A separate example is available for EFR32xG22, which has limited RAM and flash, and therefore some of the stack classes are disabled by default.

###### Typical applications

- **Bluetooth Mesh - SoC Light CTL (D)**: An out-of-the-box software demo where the LEDs of the mainboard/WSTK can be switched on and off, and their lighting intensity, color temperature, and delta UV can be set.  
  - The Thunderboard Sense 2 board can be switched on and off, and the lighting intensity, color temperature, and delta UV can be set.
- **Bluetooth Mesh - SoC Light HSL (D)**: An out-of-the-box software demo where the LEDs of the mainboard can be switched on and off, and their lighting intensity, hue, and saturation can be set. The example also tries to establish friendship as a Friend node.  
  - The Thunderboard Sense 2 can be switched on and off, and the lighting intensity, hue, and saturation can be set.
- **Bluetooth Mesh - SoC Sensor Client (D, F)**: This example demonstrates the Bluetooth Mesh Sensor Client Model. It collects and displays sensor measurement data from remote device(s) (e.g., btmesh_soc_sensor_server).
- **Bluetooth Mesh - SoC Sensor Thermometer (D, F)**: This example demonstrates the Bluetooth Mesh Sensor Server Model and Sensor Setup Server Model. It measures temperature and sends the measurement data to a remote device (e.g., btmesh_soc_sensor_client).  
  - For certain devices, if available, it measures CPU temperature and uses that data as temperature reading. Otherwise it sends mocked temperature data to a remote device (e.g., btmesh_soc_sensor_client).
- **Bluetooth Mesh - SoC Switch CTL (D, F, M)**: An out-of-the-box Software Demo where the device acts as a switch using the Light CTL Client Model. Push Button presses or CLI commands can control the lightness and color temperature of the LEDs on a remote device.  
  - **Note:** This example is not compatible with the Dimming Control NLC Profile.
- **Bluetooth Mesh - SoC Switch CTL Low Power (D, F, M)**: An out-of-the-box Software Demo where the device acts as a switch using the Light CTL Client Model. It is optimized for low current consumption with disabled CLI, logging, and LCD. Push Button presses or CLI commands can control the lightness and color temperature of the LEDs on a remote device.  
  - **Note:** This example is not compatible with the Dimming Control NLC Profile.
- **Bluetooth Mesh - SoC DFU Distributor (D)**: Demonstrates the Firmware Distributor role based on the BT Mesh Model specification. Distributor is responsible for delivering new firmware images to the Target nodes and monitoring the progress of the firmware update.

###### Security examples

- **Bluetooth Mesh - SoC CSR Generator (Secure Vault) (D)**: Certificate generating firmware example. Software generates the device EC key pair, the signing request for the device certificate, and other related data. The generated data can be read out by the Central Authority.
- **Bluetooth Mesh - SoC Empty with Certificate-Based Provisioning support**: Demonstrates the bare minimum needed for a Bluetooth Mesh C application that allows Certificate-Based Provisioning (CBP). The application starts Unprovisioned Device Beaconing after boot waiting to be provisioned to a Mesh Network.

###### Networked Lighting Control (NLC) examples

More information from Bluetooth SIG site: [Bluetooth® Networked Lighting Control](https://www.bluetooth.com/learn-about-bluetooth/use-cases/lighting-control/)

- **Bluetooth Mesh - NLC Ambient Light Sensor (D, F)**: An out-of-the-box Software Demo where the device acts as an Ambient Light Sensor in a Networked Lighting Control (NLC) system. The device measures ambient light and sends these measurements to the network. Properly configured NLC Basic Lightness Controllers then can act on the received data.
- **Bluetooth Mesh - NLC Ambient Light Sensor (Mock) (D, F)**: An out-of-the-box Software Demo where the device acts as an ambient light sensor in a Networked Lighting Control (NLC) system. The device simulates ambient light measurements and sends these to the network. Properly configured NLC Basic Lightness Controllers then can act on the received data.
- **Bluetooth Mesh - NLC Basic Lightness Controller (D)**: An out-of-the-box software demo where the device acts as a Basic Lightness Controller in a Networked Lighting Control (NLC) system. The device listens to messages from other NLC devices, namely Occupancy Sensor, Ambient Light Sensor, Dimming Control and Basic Scene Selector nodes.  
  - This project uses the RGB LED on the xG24 Dev Kit/Thunderboard Sense 2 board or LEDs on the mainboard/WSTK and display (if available).
- **Bluetooth Mesh - NLC Basic Scene Selector (D, F, M)**: An out-of-the-box Software Demo where the device acts as a Basic Scene Selector in a Networked Lighting Control (NLC) system. Push Button presses control Basic Lightness Controllers in the network by scene recall requests.
- **Bluetooth Mesh - NLC Basic Scene Selector Low Power (D, F, M)**: An out-of-the-box Software Demo where the device acts as a Basic Scene Selector in a Networked Lighting Control (NLC) system. It is optimized for low current consumption with disabled CLI, logging, and LCD. Push Button presses control Basic Lightness Controllers in the network by scene recall requests.
- **Bluetooth Mesh - NLC Dimming Control (D, F, M)**: An out-of-the-box Software Demo where the device acts as a Dimming Control in a Networked Lighting Control (NLC) system. Push Button presses control Basic Lightness Controllers in the network by Generic Level Delta or Generic On/Off messages.
- **Bluetooth Mesh - NLC Dimming Control Low Power (D, F, M)**: An out-of-the-box Software Demo where the device acts as a Dimming Control in a Networked Lighting Control (NLC) system. It is optimized for low current consumption with disabled CLI, logging, and LCD. Push Button presses control Basic Lightness Controllers in the network by Generic Level Delta or Generic On/Off messages.
- **Bluetooth Mesh - NLC Occupancy Sensor (D, F)**: An out-of-the-box Software Demo where the device acts as an Occupancy Sensor in a Networked Lighting Control (NLC) system. Push Button presses imitate people count changes which can control a properly configured NLC Basic Lightness Controller.

###### Interoperability Test Demos

The interoperability (IOP) tests check if the Bluetooth mesh stack running on the board is compatible with a smartphone or not. These are test procedures containing several test cases for each Bluetooth mesh operation. The demos are meant to be used with the Bluetooth mesh mobile application.

The supported boards are BRD4181A and BRD4181B using xG21, BRD4186C and BRD4187C using xG24 and BRD4194A using xG27. The LNP node test is supported also by BRD4182A using xG22.

- **Bluetooth Mesh - SoC IOP Test - Friend node (D)**: Friend example for IOP test. This node acts as a friend for the low power node and caches messages sent to it when the low power node is sleeping.
- **Bluetooth Mesh - SoC IOP Test - LPN node (D)**: Low power node example for IOP test. This node acts as a typical low power device and sleeps most of the time. It needs a friend node to cache messages and forward them when polled.
- **Bluetooth Mesh - SoC IOP Test - Proxy node (D)**: Proxy example for IOP test. This node forwards/relays messages between GATT and advertising bearers in the network.
- **Bluetooth Mesh - SoC IOP Test - Relay node (D)**: Relay example for IOP test. This node acts as a relay, that is, if a node is out of range for another node, it relays messages between the two, provided the relay node is in range for both.

##### NCP Host Examples

- **btmesh_host_empty**: Minimal host-side project structure, used as a starting point for NCP host applications. Use it with the Bluetooth Mesh - NCP Empty NCP target application flashed to the radio board. Access is to the NCP target stack layer via BGAPI and not to the link layer via HCI. The examples can be found in the GSDK install folder under _app/ btmesh/example_host_. The example requires a POSIX environment for compilation, such as Linux, macOS, or Windows MSYS2.
- **BT Mesh Host Provisioner**: NCP-mode host application for testing host provisioning including Remote Provisioning, for use with the Bluetooth Mesh - NCP Empty NCP-mode target application, located in <GSDK installation>app/btmesh/example_host/ btmesh_host_provisioner. Quick instructions: Compile with a POSIX-compatible toolchain with make parameters RPR=1 UI=1. See the README.txt included for more information.

##### Python-Based NCP Host Examples

Python-based NCP host examples can be accessed at [https://github.com/SiliconLabs/pybgapi-examples](https://github.com/SiliconLabs/pybgapi-examples). These examples are meant to be used with PyBGAPI ([https://pypi.org/project/pybgapi/](https://pypi.org/project/pybgapi/)). Use with **Bluetooth Mesh - NCP Empty** NCP target application flashed to the radio board.

##### GitHub Mesh Stack Features

For additional Mesh examples, see our GitHub repository which, provides examples for use-cases (such as Embedded Provisioner, Remote Provisioning, IV Update/Recovery, etc.) not covered by Simplicity Studio: [https://github.com/SiliconLabs/bluetooth_mesh_stack_features](https://github.com/SiliconLabs/bluetooth_mesh_stack_features).

#### Getting Started with the Bluetooth Mesh Demonstration Software

To get started with Bluetooth Mesh demo software, you should have downloaded Simplicity Studio 5 (SSv5) and the Bluetooth Mesh SDK as described in the [Simplicity Studio 5 User's Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/), available online and through the SSv5 help menu.

This section focuses on a light-switch demonstration using SDK 4.x examples. To see how to demonstrate Mesh 1.1 Device Firmware Update functionality, see [Bluetooth Mesh Device Firmware Update Example Walkthrough](/btmesh/11.0.0/btmesh-device-firmware-update-example).

To see how to demonstrate Remote Provisioning, see [Bluetooth Mesh Remote Provisioning](/btmesh/11.0.0/btmesh-remote-provisioning).

For building a network, based on the Networked Lighting Control profiles, see [Networked Lighting Control](/btmesh/11.0.0/btmesh-networked-lighting-control).

##### Preparing the Mainboard

The layout of the Wireless Starter Kit mainboard with attached **EFR32xG24B** radio board is shown in the following figure:

![WSTK mainboard with attached radio board](/btmesh-getting-started-overview/10.0.0/images/sld433-image17.jpg)

1. Connect a Blue Gecko Radio Board to the mainboard.  
   Use radio board BRD4187C **EFR32xG24B** 2.4 GHz (+20 dBm) (or similar) for this demo experience.
2. Connect the mainboard to a PC using the **J-Link USB** connector and the cable provided with the starter kit.
3. If not already set, turn the power switch to the **AEM** position.
4. Repeat the above steps for the other two kits so all three kits are connected to your computer.

###### Verifying the Setup

1. Check that the blue **USB Connection Indicator** LED (next to **J-Link USB**) turns on or starts blinking.
2. Check that the mainboard LCD display turns on and displays a Silicon Labs logo.

##### Install the Demonstration Firmware

When the devices are connected to your PC with a USB cable, you can see three devices listed in the **Debug Adapters** view in Sim-plicity Studio. Select the J-link for a device to display demonstrations, examples, and documentation associated with the Bluetooth Mesh SDK.

For this demo, you need to flash two devices with **Bluetooth Mesh – SoC Light CTL** and one device with **Bluetooth Mesh – SoC Switch CTL**. Go to the **Example Projects & Demos** tab. Click the target device in the **Debug Adapters** view and click **[RUN]** next to the desired demo (if available). If the demo is not available, click **[CREATE]** for an instance of the selected example, build it, and flash it. (In this case, the bootloader is required. See [Getting Started with Application Development](05-btmesh-app-development)).

![screenshot of demos](/btmesh-getting-started-overview/10.0.0/images/sld433-image18.png)

##### Use the Demo with an Android Smartphone

Make sure that all three devices have the status of **unprovisioned** on the device LCD screen before starting with the application. Open the **Bluetooth Mesh** app by Silicon Labs on your Android phone.

Follow the procedures below to set up and use the demonstration.

1. Go to the **Provision** view and tap scan to search for unprovisioned devices.
2. Select the Bluetooth mesh device you want to provision and configure.
3. Enter the descriptive name for the device and select the network you want to add it to.

![Provision button](/btmesh-getting-started-overview/10.0.0/images/sld433-image19.png)  ![Select a network](/btmesh-getting-started-overview/10.0.0/images/sld433-image20.png)

**Note:** The Android application has a pre-generated subnetwork and appkey, but you can add more to the application if you like. The subnetwork and node database can be erased by either left-swiping or long-pressing the subnetwork in the main view and by pressing the trash icon.

The network and node database can be erased by long-pressing the network in the main view and by pressing the trash icon.

![trash icon](/btmesh-getting-started-overview/10.0.0/images/sld433-image21.jpg)

To configure the newly provisioned Bluetooth mesh device:

1. Right after provisioning, the Android application connects the proxy service on the node.
2. During configuration select the Bluetooth mesh features (proxy, relay, low power, and friend) that you want to enable.  
   Notice that if you disable proxy, the node can no longer be directly accessed over GATT.
3. Select the Functionality (mesh model) that you want to enable.
4. Select the AppKey you want to associate the device with.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image22.png)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image23.png)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image24.png)

**Note:** The information view shows the Bluetooth Mesh node features, such as Unicast address, UUID, and security keys as well as the supported mesh models. It can be used for debug purposes.

To control a Bluetooth mesh node with the Android application:

1. Select the Subnet and AppKey you want to control.  
   The application will show the available nodes assigned to that appkey.
2. You can control the light by:  
   1. Pressing the light bulb icon will send an On/Off message.  
   2. Moving the upper slider will send Light Lightness (dimming) messages.  
   3. Moving the medium and lower sliders will send CTL (temperature and delta UV) messages.  
   4. Pressing [**STORE**] stores the corresponding scene.
3. By going to devices view and either left-swiping or long-pressing a node, you can then either delete or reconfigure the node.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image25.png)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image26.jpg)

Once the Android application has been used to provision a light bulb and a light switch to a subnetwork and appkey, the light switch (WSTK) can also be used to control the light bulb (WSTK) with the PB0 and PB1 buttons.

###### PB0 Button

- Short press: Decrease Light Lightness by 10%
- Medium press: Decrease CTL (temperature) value
- Long press: Send Off message
- Very long press (5 seconds or more): Recall scene 1

###### PB1 Button

- Short press: Increase Light Lightness by 10%
- Medium press: Increase CTL (temperature) value
- Long press: Send On message
- Very long press (5 seconds or more): Recall scene 2

On devices with only one button, such as Thunderboard BG22:

- Short press: Decrease Light Lightness by 10%, wraps back to 100% after 0%
- Medium press: Decrease CTL (temperature) value, wraps back to maximum after minimum
- Long press: Toggle sending Off message and On message
- Very long press (5 seconds or more): Recall scene 1

Button presses during startup (power-on or reset) execute the following actions:

- On devices with two buttons: PB0 = Full factory reset; PB1 = Node reset
- On devices with one button: PB0 = Full factory reset

##### Use the Demo with an iOS Smartphone

Make sure that all three devices have the status of **unprovisioned** on the device LCD screen before starting with the Mobile App. Open the **Bluetooth Mesh** app by Silicon Labs on your iOS phone.

Follow the procedures below to set up and use the demonstration.

1. Go to the provisioning view and tap scan to search for unprovisioned devices.
2. Select the Bluetooth Mesh device you want to provision and configure.
3. Enter the descriptive name for the device and select the network you want to add it to.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image27.jpg)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image28.png)

The subnetwork and node database can be erased by left-swiping the network in the main view and then pressing the trash icon.

![trash icon](/btmesh-getting-started-overview/10.0.0/images/sld433-image29.png)

To provision a Bluetooth Mesh device and configure the node:

1. During provisioning, select the subnetwork you want to add the device to.
2. During configuration, select the Bluetooth Mesh features (proxy, relay, low power and friend) that you want to enable.  
   Notice that if you disable proxy, the node can no longer be directly accessed over GATT.
3. Select the AppKey you want to associate the device with.
4. Finally, select the Functionality (mesh model) that you want to enable.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image30.png)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image31.png)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image32.png)

**Note:** The information view shows the Bluetooth mesh node features, such as Unicast address, UUID, and security keys as well as the supported mesh models. It can be used for debug purposes.

To control a Bluetooth Mesh node with the iOS application:

1. Select the Subnetwork and AppKey you want to control.  
   The application will show the available nodes associated with that AppKey.
2. You can control the light:  
   1. Pressing the light bulb icon will send an On/Off message.  
   2. Moving the upper slider will send Light Lightness (dimming) messages.  
   3. Moving the medium and lower sliders will send CTL (temperature and delta UV) messages.  
   4. Pressing [**STORE**] stores the corresponding scene.
3. By going to the Devices view and tapping a node name you can reconfigure the node. To remove the node from the subnetwork, left-swipe it and press the trash icon.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image33.png)  ![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image34.png)

Once the iOS application has been used to provision a light bulb and a light switch to a subnetwork and appkey, the light switch (WSTK) can also be used to control the light bulb (WSTK) with the PB0 and PB1 buttons.

###### PB0 Button

- Short press: Decrease Light Lightness by 10%
- Medium press: Decrease CTL (temperature) value
- Long press: Send Off message
- Very long press (5 seconds or more): Recall scene 1

###### PB1 Button

- Short press: Increase Light Lightness by 10%
- Medium press: Increase CTL (temperature) value
- Long press: Send On message
- Very long press (5 seconds or more): Recall scene 2

On devices with only one button, such as Thunderboard BG22:

- Short press: Decrease Light Lightness by 10%, wraps back to 100% after 0%
- Medium press: Decrease CTL (temperature) value, wraps back to maximum after minimum
- Long press: Toggle sending Off message and On message
- Very long press (5 seconds or more): Recall scene 1

Button presses during startup (power-on or reset) execute the following actions:

- On devices with two buttons: PB0 = Full factory reset; PB1 = Node reset
- On devices with one button: PB0 = Full factory reset

#### Getting Started with Application Development

The most common starting point for application development is the **Bluetooth Mesh - SoC Empty** example. This example demonstrates the bare minimum needed for a Bluetooth mesh C application. The application starts Unprovisioned Device Beaconing after boot waiting to be provisioned to a Mesh Network.

All Bluetooth Mesh devices must be loaded with the Gecko Bootloader as well as the application. While you are getting started, the easiest way to do this is to load any of the precompiled demo images that come with the bootloader configured as part of the image. When you flash your application, it overwrites the demo application, but the bootloader remains. Subsequently, you may wish to build your own bootloader, as described in [UG266: Silicon Labs Gecko Bootloader User's Guide for GSDK 3.2 and Lower](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf), [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](/btmesh/11.0.0/bootloader-user-guide-gsdk-4), and [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](/btmesh/11.0.0/bootloader-user-guide-series3-and-higher). If the application requires a specific bootloader type, it is noted in the example description in [About-Demos-and-Examples](03-about-demos-and-examples).

New Project creation is done through three dialogs:

- Target, SDK, and Toolchain Selection
- Example Project Selection
- Project Configuration

You can start a project from different locations in the Launcher Perspective, as described in the [Simplicity Studio 5 User's Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/). While you are getting started, we suggest starting from the File menu, as that takes you through all three of the above dialogs.

1. Select **New > Silicon Labs Project Wizard**.
2. Review your SDK and toolchain. If you wish to use IAR instead of GCC, be sure to change it here. Once you have created a project, it is difficult to change toolchains. Click **NEXT**.
3. On the **Example Project Selection** dialog, filter on **Bluetooth Mesh** and select **Bluetooth Mesh - SoC Empty**. Click **NEXT**.
4. On the **Project Configuration** dialog, rename your project if you wish. Note that if you change any linked resource, it is changed for any other project that references it. While you are getting started, the default choice is to include project files but link to the SDK is best. Click **FINISH**.

When you create a Bluetooth Mesh project, four tabs open automatically: a README file that describes the example, the GATT Configurator (gatt_configuration.btconf), the .slcp or Project Configurator (<projectname>.slcp), and the Mesh Configurator (dcd_config.btmeshconf). Note that a Simplicity IDE perspective control is now included in the upper right of the screen.

GATT configuration is the same for both Bluetooth and Bluetooth Mesh projects. [GATT Configurator User’s Guide for Bluetooth LE and Bluetooth Mesh](/btmesh/11.0.0/gatt-configurator-users-guide-ble-btmesh) describes how to configure the GATT database.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image35.png)

The Project Configurator and its associated Component Editor provide access to components. All the Bluetooth Mesh functionality is provided as components. You can customize projects by installing or uninstalling the components based on the use cases and requirements, and then configuring installed components using the Component Editor. The Bluetooth Mesh Component group shows the components specific to Bluetooth Mesh projects.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image36.png)

The Bluetooth Mesh Configurator provides access to Device Composition Data (DCD). This contains information about a Bluetooth Mesh node, the elements it includes, and the supported models. DCD exposes the node information to a configuration client so that it knows the potential functionalities the node supports and, based on that, can configure the node.

![screenshot](/btmesh-getting-started-overview/10.0.0/images/sld433-image37.png)

For more details on node configuration using the Project Configurator and Bluetooth Mesh Configurator, see [UG472: Bluetooth Mesh Stack and Bluetooth Mesh Configurator User's Guide for SDK v2.x and Higher](https://www.silabs.com/documents/public/user-guides/ug472-bluetooth-mesh-v2x-node-configuration-users-guide.pdf).

To build and debug your project click **Debug** (bug icon) in the upper left corner of the Simplicity IDE perspective. It will build and download your project, and open the Debug perspective. Click **Play** to start running your project on the device.

### Transitioning from the v1.x to the v2.x Bluetooth Mesh SDK

#### Transitioning from the v1.x to the v2.x Bluetooth Mesh SDK

> **NOTE: This section replaces _AN1298: Transitioning from the v1.x to the v2.x Bluetooth Mesh SDK_. Further updates to this application note will be provided here**.

Bluetooth Mesh Software Development Kit (SDK) v2.x contains a number of changes compared to Bluetooth Mesh SDK v1.x. Many of these changes are due to an underlying framework redesign that results in an improved developer experience within the new Simplicity Studio 5. Projects are now built on a component architecture. Simplicity Studio 5 includes project configuration tools that provide an enhanced level of software component discoverability, configurability, and dependency management. These include a Component Editor, a redesigned GATT configurator, a DCD configurator, and the stack configurator.

In Bluetooth Mesh SDK v2.x, sample applications have a new software architecture, and the Bluetooth Mesh API is redesigned. Additionally, the stack can now be configured in separate header files, and platform components can be added to the project with the Project Configurator instead of copying and including files manually. While these changes are a result of overall improvements in the SDK and in Simplicity Studio 5, it also means that migrating projects from Bluetooth Mesh SDK v1.x to v2.x is not trivial and has to be done manually. This document explains the steps needed to move your Bluetooth Mesh v1.x project into the v2.x environment.

This document is the Bluetooth Mesh extension of _AN1255: Transitioning from the v2.x to the v3.x Bluetooth® SDK_ which contains the general Bluetooth software architecture level information.

##### Key Points

Reviews difference in:

- Software architecture for Bluetooth Mesh application
- API
- Stack configuration
- New components

![Bluetooth Mesh Software Development Kit](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image1.png)

#### Introduction

Silicon Labs has introduced both a complete update to its Simplicity Studio tool suite, as well as a new, component-based Gecko Platform architecture. For more information about the changes in Simplicity Studio 5 and the Bluetooth SDK, see _AN1255: Transitioning from the v2.x to the v3.x Bluetooth® SDK_.

Bluetooth Mesh SDK 2.0.0 is released with Gecko Software Development Kit suite version 3.1.0 in Simplicity Studio 5 (SSv5). It is built on top of the component-based Gecko Platform architecture. With this design, Bluetooth Mesh developers benefit the following component-based project configuration features:

- Search and filter to find and discover software components that work with the target device.
- Automatically pull in all component dependencies and initialization code.
- Configurable software components including peripheral inits, drivers, middleware, and stacks.
- All configuration settings in C header files for use outside of Simplicity Studio.
- Configuration validation to alert developers to errors or issues.
- Easily manage all project source using git or other SCM tools.
- Managed migration to future component and SDK versions.
- Simplified transitions from Silicon Labs development kits to custom hardware.

Other features of the SSv5/GSDK v3.x development environment include:

- Project source management options (link to SDK sources or copy all contents to user folder).
- Graphical pin configuration.
- Redesigned Bluetooth Configurator with a fresh UI that is more intuitive for Bluetooth and GATT customization.
- Redesigned Radio Configurator with a fresh UI that is more intuitive for single- and multi-PHY customization.
- Redesigned stack configurator (used to be memory configuration) with a fresh UI that’s more intuitive for Bluetooth Mesh application customization.
- Iterative development (configure components, edit sources, compile, debug) using SSv5 configuration tools and third-party IDEs.
- GNU makefiles as a build option.

Other changes are specific to the SDK. Bluetooth Mesh SDK v2.x contains a number of changes compared to Bluetooth Mesh SDK v1.x. The main changes are as follows

1. The project structure of the sample applications has changed. Many autogenerated files and unified configuration files help when adding and configuring software components.
2. The entire project generation is now based on software components. This makes it possible to add functionality to the project with only a click, instead of copying files manually and looking for dependencies.
3. The Bluetooth Mesh API has changed. The API commands and events use a new nomenclature to comply with Silicon Labs standards. Additionally, some new classes and commands are introduced and some of them are removed to make the API more transparent and consistent.
4. The GATT configurator is completely redesigned. The new user interface is more modern, while the generator tool makes it possible to add partial extensions to the GATT database. This means that the GATT database can be easily extended programmatically.
5. The memory configurator is renamed to Bluetooth Mesh stack configurator and separated from the DCD configurator. A Component Configurator tool in SSv5 is available to configure all component parameters, which makes it easy to use predefined values, and to validate custom values.

This application note guides you through these changes, and describes the migration steps necessary to move a project from Bluetooth Mesh SDK v1.x to v2.x.

For details about the release, see the release notes provided with the SDK.

#### Project Structure

In Bluetooth Mesh SDK v1.x, a project contains the following folders:

```c++
/                   Application-specific files
/hardware           Development board configuration files and drivers for external peripherals
/platform           Device configuration files and drivers for the MCU peripherals
/protocol           Bluetooth stack files
```

When a new project is generated, a subset of the SDK files (source files, headers, configuration headers) is copied from the SDK folder into the project folders based on hardware type and on the needs of the sample application. Additionally, some files (for example init_mcu.c, hal-config.h, and so on) are generated from templates into the root folder of the project. Again, the output is based on the hardware type and on the needs of the sample application.

In Bluetooth Mesh SDK v2.x auto-generated files and configuration headers are clearly separated from the static SDK files and gathered into separate folders:

```c++
/autogen            Automatically-generated files based on the installed software components
/config             Editable configuration files for the software components
/gecko_sdk_3.x.x
  /app              Application-specific files
  /hardware         Development board configuration files and drivers for external peripherals
  /platform         Device configuration files and drivers for the MCU peripherals
  /protocol         Bluetooth stack files
  /util             Utilities
```

Developers can now easily see which files can be modified by the generator script and it is easy to access all configuration files. This is especially important because in Bluetooth Mesh SDK v2.x many more files are generated by the addition of [software components](03-components).

**Due to the new project structure – and due to the new auto-generated files required by the Bluetooth stack – migrating a v1.x project into Bluetooth Mesh SDK v2.x must begin by creating a new project in the new SDK. All Bluetooth Mesh v1.x SDK examples are also in the Bluetooth Mesh v2.x SDK. It is recommended to start from the equivalent or from the Bluetooth Mesh SoC Empty project. Application logic should be pulled into this new project. After you select a compatible part on SSv5’s Welcome page, the project can be created from the Part-specific Launcher perspective. The Technology filter makes it easy to find applicable projects.**

![The Technology filter](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image2.png)

In the project configuration dialog, you can rename the project, change the project location, and define how to handle project files.

> **Note**: In Bluetooth Mesh SDK v1.x all SDK files are copied into the project by default. In Bluetooth Mesh SDK v2.0 SDK files, considered to be static, are linked by default. If you want to version-control your full project, it is recommended to change this setting to “Copy contents” in the Project Configuration wizard, when you create the new project to have all content needed by the project in one folder.

![Copy contents](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image3.png)

Bluetooth Mesh projects automatically open in the Simplicity IDE’s Project Configurator. Three tabs are presented: the GATT Configurator (gatt_configuration.btconf), .the slcp or Project Configurator (<projectname>.slcp), and the Mesh Configurator (dcd_config.btmeshconf). If the example has documentation, the project opens on a readme tab.

GATT configuration is the same for both Bluetooth and Bluetooth mesh projects. [GATT Configurator User’s Guide for Bluetooth SDK v3.x](/btmesh/11.0.0/gatt-configurator-users-guide-ble-btmesh) describes how to configure the GATT database.

![GATT configuration](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image4.jpg)

The Project Configurator and its associated Component Editor provide access to components. All the Bluetooth Mesh functionality is provided as components. You can customize projects by installing or uninstalling the components based on the use cases and requirements, and then configuring installed components using the Component Editor. The Bluetooth Mesh Component group shows the components specific to Bluetooth Mesh projects. Components are discussed in more detail in the next section.

![The Project Configurator](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image5.jpg)

The Bluetooth Mesh Configurator provides access to information about a Bluetooth mesh node, the elements it includes, and the supported models. DCD exposes the node information to a configuration client so that it knows the potential functionalities the node supports and based on that can configure the node.

![The Bluetooth Mesh Configurator](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image6.jpg)

For more details on node configuration using the Project Configurator and Bluetooth Mesh Configurator, see _UG472: Bluetooth® Mesh Node Configurator User's Guide for SDK v2.x_.

#### Components

To add a new software component, for example a new model, in Bluetooth Mesh SDK v1.x the user must:

1. Copy the corresponding SDK files from the SDK folder into the project folder.
2. Copy all the dependencies of the given component into the project folder.
3. Add new include directories to the project settings.  
   And additionally:
4. Write the initialization code manually in the application.
5. Configure the component manually in the config files.
6. Use the API of the component in the application.

This is quite a cumbersome process, especially when figuring out the dependencies between components.

In Bluetooth Mesh SDK v2.x software components can be added easily by installing them from the Component Library. The installation process will automatically execute the first three steps listed above, and it also modifies the corresponding auto-generated files to integrate the component into the application (_“glue logic”_).

Additionally, the Component Configurator provides the possibility of:

1. Adding an “_init”_ type component that initializes the software component
2. Configuring the component with a GUI

Some software components (like OTA DFU) will fully integrate into the application to perform a specific task without the need of any additional code, while other components provide an API to be used in the application. The only task left for the developer is to use the API of those component in the application.

It is important to note that in Bluetooth Mesh SDK v2.x the Bluetooth Mesh stack itself is also just a collection of software components that can be added to and removed from the project.

**When migrating a project into Bluetooth Mesh SDK v2.x, start by finding out which functionality can be provided by installing a software component from the Component Library. Although this means you must become familiar with the software components first, it will save time later. Generally speaking, if you would have copied an additional SDK file into your project, you will probably find a software component that solves the integration of that file.**

To see the component library, click the <project-name>.slcp tab of your project, and click **Software Components**. A number of filters as well as a keyword search are available to help you explore the various component categories. Note that components for all installed SDKs are presented.

![Explore the various component categories](/transitioning-from-bluetooth-mesh-1x-to-2x/10.0.0/images/sld812-image7.png)

#### Bluetooth Mesh API

The Bluetooth Mesh API changes in Bluetooth Mesh SDK v2.x. The most obvious change is the renaming of all the BGAPI commands and events to align with the unified Silicon Labs coding standard. However, commands have been added and removed, and also new BGAPI classes have been added to make the API more logical and transparent. This section describes all the changes related to the API.

##### Functionality Breaks

###### Provisioning Management

The API for provisioning a device has been changed in order to increase its flexibility to handle different scenarios, such as parallel provisioning or multiple devices, with more ease.

All provisioning events and commands affecting the provisioning of a particular device are linked to a _provisioning session_ by UUID of the device as a parameter. This enables provisioning of multiple devices in parallel.

Provisioning flexibility is improved by events that inform the Provisioner of the state of the provisioning session and the capabilities of the device. A simple Provisioner may still choose to allow the stack to select default values but a more complex implementation has fuller control than before.

Previously, the Provisioner would set up provisioning parameters, such as the address allocation for the new device, at the beginning of provisioning without regard to the properties of the device being provisioned. This has been changed to a more event driven flow where the Provisioner can, at certain points, affect how provisioning a device proceeds. Details for the provisioning process are listed below.

###### Provisioning session control (heading level 7)

If the Provisioner needs to control the provisioning process in detail it must call `sl_btmesh_prov_set_provisioning_suspend_event()` with the status parameter set to 1. This allows the stack to suspend the ongoing provisioning session at stages where the Provisioner could be queried for a decision to continue provisioning, or for a value of a provisioning parameter.

If the Provisioner does not need to control provisioning in detail it can call the function with status parameter set to 0 instead, in which case the stack will use default values and continue provisioning without suspending it.

###### Starting to provision (heading level 7)

The Provisioner first creates a provisioning session by calling `sl_btmesh_prov_create_provisioning_session()`. The device UUID is used to identify which device the provisioning session relates to at this call and any of the following commands and events.

The Provisioner may, immediately after creating a provisioning session, set the desired provisioning authentication methods for the session by calling `sl_btmesh_prov_set_oob_requirements()`, or it can defer that until later if it has requested session suspension.

If provisioning over PB-GATT is needed, the Provisioner must establish a LE connection to the device, as before.

The Provisioner can then start provisioning the device by calling either `sl_btmesh_prov_provision_adv_device()` (for PB-ADV) or `sl_btmesh_prov_provision_gatt_device()` (for PB-GATT). The stack will then start running the provisioning protocol with the specified device.

###### Suspension of provisioning session (heading level 7)

If the Provisioner requested session control, at the time when Provisioning Capabilities PDU is received from the device being provisioned an `sl_btmesh_evt_prov_capabilities()` event will be generated, listing the device capabilities and number of elements the device contains. Furthermore, an `sl_btmesh_prov_provisioning_suspended()` event will be generated to indicate a decision is now needed from the Provisioner

If the Provisioner now wishes to use some particular provisioning authentication method based on device capabilities it can do so by calling `sl_btmesh_prov_set_oob_requirements()`. Otherwise the stack will make a default choice.

If the Provisioner now wishes to set a non-default Mesh address to the device being provisioned it can do so by calling `sl_btmesh_prov_set_device_address()`. Otherwise, the stack will allocate an address to the device automatically.

If the Provisioner decides to stop provisioning the device for some reason (for example, the device does not support a desired authentication method), it can do so by calling `sl_btmesh_prov_abort_provisioning()`. Otherwise, it needs to instruct the stack by calling `sl_btmesh_prov_continue_provisioning()`.

###### OOB authentication data and public key (heading level 7)

If some form of OOB data is involved in the provisioning, the stack will notify the Provisioner when such data is needed, as before.

If the OOB static authentication method or the OOB output authentication method is used when provisioning the device, an `sl_btmesh_evt_prov_oob_auth_request()` event is generated when Provisioner needs to supply authentication data by calling `sl_btmesh_prov_send_oob_auth_response()` as a response to the event.

If the OOB input authentication method is used when provisioning the device, an `sl_btmesh_evt_prov_oob_display_input()` event is generated when the Provisioner needs to display authentication data for the user to enter on the device being provisioned.

If an OOB public key is used when provisioning the device, a `sl_btmesh_evt_prov_oob_pkey_request()` event is generated and the Provisioner must respond with a `sl_btmesh_send_oob_pkey_response()` call.

###### Finalizing a provisioning session (heading level 7)

Once provisioning finalizes successfully, an `sl_btmesh_evt_prov_device_provisioned()` event will be generated. In case of failure, a `sl_btmesh_evt_prov_provisioning_failed()` event will be generated instead.

##### Changes in BGAPI Commands

BGAPI command functions change both their name, to align with Silicon Labs standards, and their structure, to make the error checking and the handling of return values simpler.

In Bluetooth Mesh SDK v2.x BGAPI command function names start with `sl_btmesh*_*` instead of `gecko_cmd_` used in Bluetooth Mesh SDK v1.x. This means that all function name should be changed according to this rule, when migrating a project from v1.x to v2.x.

No compatibility layer is provided due to the additional changes listed below. However, a “Bluetooth API migration helper” component can be found in the Component Library. If this component is installed, a header file is added to the project that provides verbose compiler errors when an old API call is found in the code. A suggestion for the new API is also present in the error message.

In Bluetooth Mesh SDK v1.x command functions returned a complex structure, providing both error code and return values. In Bluetooth Mesh SDK v2.x only a status code is returned, and the return values are passed back using pointer arguments. If the output of a command contains variable size data, the application needs to give the destination for the data as well as the maximum size of the destination. See an example below.

###### Command functions in v1.x

```C
/* Function */
struct gecko_msg_mesh_config_client_add_appkey_rsp_t *
gecko_cmd_mesh_config_client_add_appkey(uint16 enc_netkey_index,
                                        uint16 server_address,
                                        uint16 appkey_index,
                                        uint16 netkey_index);

/* Response structure */
struct gecko_msg_mesh_config_client_add_appkey_rsp_t
{
  uint16 result;
  uint32 handle;
};
```

###### Command functions in v2.0

```C
sl_status_t sl_btmesh_config_client_add_appkey(uint16_t enc_netkey_index,
                                               uint16_t server_address,
                                               uint16_t appkey_index,
                                               uint16_t netkey_index,
                                               uint32_t *handle);;
```

While for most commands the renaming means only changing `gecko_cmd_` to `sl_btmesh_`, many functions are renamed due to changed functionality, changed API class, or simply to make the API more logical. Furthermore, some API functions are split into multiple ones, and some functions are merged. These name changes are listed in the following table.

> **NOTE**: All APIs marked as “deprecated” in the Bluetooth Mesh v1.x have been completely removed from Bluetooth Mesh v2.x. The API change table below does not list them.

|API 1.x|API 2.0|Notes|
|---|---|---|
|CLASS: mesh_config|CLASS: mesh_config|There is no change to this class except the prefix change.|
|cmd_mesh_config_client_add_appkey|sl_btmesh_config_client_add_appkey| |
|cmd_mesh_config_client_add_model_sub|sl_btmesh_config_client_add_model_sub| |
|cmd_mesh_config_client_add_model_sub_va|sl_btmesh_config_client_add_model_sub_va| |
|cmd_mesh_config_client_add_netkey|sl_btmesh_config_client_add_netkey| |
|cmd_mesh_config_client_bind_model|sl_btmesh_config_client_bind_model| |
|cmd_mesh_config_client_cancel_request|sl_btmesh_config_client_cancel_request| |
|cmd_mesh_config_client_clear_model_sub|sl_btmesh_config_client_clear_model_sub| |
|cmd_mesh_config_client_get_beacon|sl_btmesh_config_client_get_beacon| |
|cmd_mesh_config_client_get_dcd|sl_btmesh_config_client_get_dcd| |
|cmd_mesh_config_client_get_default_timeout|sl_btmesh_config_client_get_default_timeout| |
|cmd_mesh_config_client_get_default_ttl|sl_btmesh_config_client_get_default_ttl| |
|cmd_mesh_config_client_get_friend|sl_btmesh_config_client_get_friend| |
|cmd_mesh_config_client_get_gatt_proxy|sl_btmesh_config_client_get_gatt_proxy| |
|cmd_mesh_config_client_get_heartbeat_pub|sl_btmesh_config_client_get_heartbeat_pub| |
|cmd_mesh_config_client_get_heartbeat_sub|sl_btmesh_config_client_get_heartbeat_sub| |
|cmd_mesh_config_client_get_identity|sl_btmesh_config_client_get_identity| |
|cmd_mesh_config_client_get_lpn_polltimeout|sl_btmesh_config_client_get_lpn_polltimeout| |
|cmd_mesh_config_client_get_model_pub|sl_btmesh_config_client_get_model_pub| |
|cmd_mesh_config_client_get_network_transmit|sl_btmesh_config_client_get_network_transmit| |
|cmd_mesh_config_client_get_relay|sl_btmesh_config_client_get_relay| |
|cmd_mesh_config_client_get_request_status|sl_btmesh_config_client_get_request_status| |
|cmd_mesh_config_client_list_appkeys|sl_btmesh_config_client_list_appkeys| |
|cmd_mesh_config_client_list_bindings|sl_btmesh_config_client_list_bindings| |
|cmd_mesh_config_client_list_netkeys|sl_btmesh_config_client_list_netkeys| |
|cmd_mesh_config_client_list_subs|sl_btmesh_config_client_list_subs| |
|cmd_mesh_config_client_remove_appkey|sl_btmesh_config_client_remove_appkey| |
|cmd_mesh_config_client_remove_model_sub|sl_btmesh_config_client_remove_model_sub| |
|cmd_mesh_config_client_remove_model_sub_va|sl_btmesh_config_client_remove_model_sub_va| |
|cmd_mesh_config_client_remove_netkey|sl_btmesh_config_client_remove_netkey| |
|cmd_mesh_config_client_reset_node|sl_btmesh_config_client_reset_node| |
|cmd_mesh_config_client_set_beacon|sl_btmesh_config_client_set_beacon| |
|cmd_mesh_config_client_set_default_timeout|sl_btmesh_config_client_set_default_timeout| |
|cmd_mesh_config_client_set_default_ttl|sl_btmesh_config_client_set_default_ttl| |
|cmd_mesh_config_client_set_friend|sl_btmesh_config_client_set_friend| |
|cmd_mesh_config_client_set_gatt_proxy|sl_btmesh_config_client_set_gatt_proxy| |
|cmd_mesh_config_client_set_heartbeat_pub|sl_btmesh_config_client_set_heartbeat_pub| |
|cmd_mesh_config_client_set_heartbeat_sub|sl_btmesh_config_client_set_heartbeat_sub| |
|cmd_mesh_config_client_set_identity|sl_btmesh_config_client_set_identity| |
|cmd_mesh_config_client_set_model_pub|sl_btmesh_config_client_set_model_pub| |
|cmd_mesh_config_client_set_model_pub_va|sl_btmesh_config_client_set_model_pub_va| |
|cmd_mesh_config_client_set_model_sub|sl_btmesh_config_client_set_model_sub| |
|cmd_mesh_config_client_set_model_sub_va|sl_btmesh_config_client_set_model_sub_va| |
|cmd_mesh_config_client_set_network_transmit|sl_btmesh_config_client_set_network_transmit| |
|cmd_mesh_config_client_set_relay|sl_btmesh_config_client_set_relay| |
|cmd_mesh_config_client_unbind_model|sl_btmesh_config_client_unbind_model| |
| | | |
|CLASS: mesh_friend|CLASS: mesh_ friend|There is no change to this class except the prefix change.|
|cmd_mesh_friend_deinit|sl_btmesh_friend_deinit| |
|cmd_mesh_friend_init|sl_btmesh_friend_init| |
| | | |
|CLASS: mesh_generic_client|CLASS: mesh_generic_client|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_generic_client_get|sl_btmesh_generic_client_get| |
|gecko_cmd_mesh_generic_client_set|sl_btmesh_generic_client_set| |
|gecko_cmd_mesh_generic_client_publish|sl_btmesh_generic_client_publish| |
|gecko_cmd_mesh_generic_client_get_params|sl_btmesh_generic_client_get_params| |
|gecko_cmd_mesh_generic_client_init|sl_btmesh_generic_client_init| |
|gecko_cmd_mesh_generic_client_init_common|sl_btmesh_generic_client_init_common| |
|gecko_cmd_mesh_generic_client_init_on_off|sl_btmesh_generic_client_init_on_off| |
|gecko_cmd_mesh_generic_client_init_level|sl_btmesh_generic_client_init_level| |
|gecko_cmd_mesh_generic_client_init_default_transition_time|sl_btmesh_generic_client_init_default_transition_time| |
|gecko_cmd_mesh_generic_client_init_power_on_off|sl_btmesh_generic_client_init_power_on_off| |
|gecko_cmd_mesh_generic_client_init_power_level|sl_btmesh_generic_client_init_power_level| |
|gecko_cmd_mesh_generic_client_init_battery|sl_btmesh_generic_client_init_battery| |
|gecko_cmd_mesh_generic_client_init_location|sl_btmesh_generic_client_init_location| |
|gecko_cmd_mesh_generic_client_init_property|sl_btmesh_generic_client_init_property| |
|gecko_cmd_mesh_generic_client_init_lightness|sl_btmesh_generic_client_init_lightness| |
|gecko_cmd_mesh_generic_client_init_ctl|sl_btmesh_generic_client_init_ctl| |
|gecko_cmd_mesh_generic_client_init_hsl| |Bluetooth Mesh SDK v2.0 doesn’t support HSL model yet.|
| | | |
|CLASS: mesh_generic_server|CLASS: mesh_generic_server|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_generic_server_response|sl_btmesh_generic_server_respond| |
|gecko_cmd_mesh_generic_server_update|sl_btmesh_generic_server_update| |
|gecko_cmd_mesh_generic_server_publish|sl_btmesh_generic_server_publish| |
|gecko_cmd_mesh_generic_server_init|sl_btmesh_generic_server_init| |
|gecko_cmd_mesh_generic_server_init_common|sl_btmesh_generic_server_init_common| |
|gecko_cmd_mesh_generic_server_init_on_off|sl_btmesh_generic_server_init_on_off| |
|gecko_cmd_mesh_generic_server_init_level|sl_btmesh_generic_server_init_level| |
|gecko_cmd_mesh_generic_server_init_default_transition_time|sl_btmesh_generic_server_init_default_transition_time| |
|gecko_cmd_mesh_generic_server_init_power_on_off|sl_btmesh_generic_server_init_power_on_off| |
|gecko_cmd_mesh_generic_server_init_power_level|sl_btmesh_generic_server_init_power_level| |
|gecko_cmd_mesh_generic_server_init_battery|sl_btmesh_generic_server_init_battery| |
|gecko_cmd_mesh_generic_server_init_location|sl_btmesh_generic_server_init_location| |
|gecko_cmd_mesh_generic_server_init_property|sl_btmesh_generic_server_init_property| |
|gecko_cmd_mesh_generic_server_init_lightness|sl_btmesh_generic_server_init_lightness| |
|gecko_cmd_mesh_generic_server_init_ctl|sl_btmesh_generic_server_init_ctl| |
|gecko_cmd_mesh_generic_server_init_hsl| |Bluetooth Mesh SDK v2.0 doesn’t support HSL model yet.|
| | | |
|CLASS: mesh_health_client|CLASS: mesh_health_client|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_health_client_get|sl_btmesh_health_client_get| |
|gecko_cmd_mesh_health_client_clear|sl_btmesh_health_client_clear| |
|gecko_cmd_mesh_health_client_test|sl_btmesh_health_client_test| |
|gecko_cmd_mesh_health_client_get_period|sl_btmesh_health_client_get_period| |
|gecko_cmd_mesh_health_client_set_period|sl_btmesh_health_client_set_period| |
|gecko_cmd_mesh_health_client_get_attention|sl_btmesh_health_client_get_attention| |
|gecko_cmd_mesh_health_client_set_attention|sl_btmesh_health_client_set_attention| |
| | | |
|CLASS: mesh_health_server|CLASS: mesh_health_server|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_health_server_set_fault|sl_btmesh_health_server_set_fault| |
|gecko_cmd_mesh_health_server_clear_fault|sl_btmesh_health_server_clear_fault| |
|gecko_cmd_mesh_health_server_test_response|sl_btmesh_health_server_send_test_response| |
| | | |
|CLASS s: mesh_lc_client|CLASS: mesh_lc_client|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_lc_client_init|sl_btmesh_lc_client_init| |
|gecko_cmd_mesh_lc_client_get_mode|sl_btmesh_lc_client_get_mode| |
|gecko_cmd_mesh_lc_client_set_mode|sl_btmesh_lc_client_set_mode| |
|gecko_cmd_mesh_lc_client_get_om|sl_btmesh_lc_client_get_om| |
|gecko_cmd_mesh_lc_client_set_om|sl_btmesh_lc_client_set_om| |
|gecko_cmd_mesh_lc_client_get_light_onoff|sl_btmesh_lc_client_get_light_onoff| |
|gecko_cmd_mesh_lc_client_set_light_onoff|sl_btmesh_lc_client_set_light_onoff| |
|gecko_cmd_mesh_lc_client_get_property|sl_btmesh_lc_client_get_property| |
|gecko_cmd_mesh_lc_client_set_property|sl_btmesh_lc_client_set_property| |
| | | |
|CLASS: mesh_lc_server|CLASS: mesh_lc_server|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_lc_server_init|sl_btmesh_lc_server_init| |
|gecko_cmd_mesh_lc_server_deinit|sl_btmesh_lc_server_deinit| |
|gecko_cmd_mesh_lc_server_update_mode|sl_btmesh_lc_server_update_mode| |
|gecko_cmd_mesh_lc_server_update_om|sl_btmesh_lc_server_update_om| |
|gecko_cmd_mesh_lc_server_update_light_onoff|sl_btmesh_lc_server_update_light_onoff| |
|gecko_cmd_mesh_lc_server_init_all_properties|sl_btmesh_lc_server_init_all_properties| |
|gecko_cmd_mesh_lc_server_set_publish_mask|sl_btmesh_lc_server_set_publish_mask| |
|gecko_cmd_mesh_lc_server_set_regulator_interval|sl_btmesh_lc_server_set_regulator_interval| |
|gecko_cmd_mesh_lc_server_set_event_mask|sl_btmesh_lc_server_set_event_mask| |
|gecko_cmd_mesh_lc_server_get_lc_state|sl_btmesh_lc_server_get_lc_state| |
| | | |
|CLASS: mesh_lc_setup_server|CLASS: mesh_lc_setup_server|There is no change to this class except the prefix change.|
|gecko_cmd_mesh_lc_setup_server_update_property|sl_btmesh_lc_setup_server_update_property| |
| | | |
|CLASS: mesh_lpn|CLASS: mesh_lpn| |
|gecko_cmd_mesh_lpn_init|sl_btmesh_lpn_init| |
|gecko_cmd_mesh_lpn_deinit|sl_btmesh_lpn_deinit| |
|gecko_cmd_mesh_lpn_establish_friendship|sl_btmesh_lpn_establish_friendship| |
|gecko_cmd_mesh_lpn_poll|sl_btmesh_lpn_poll| |
|gecko_cmd_mesh_lpn_terminate_friendship|sl_btmesh_lpn_terminate_friendship| |
|gecko_cmd_mesh_lpn_config|sl_btmesh_lpn_config| |
| | | |
|CLASS: mesh_node|CLASS: mesh_node| |
|gecko_cmd_mesh_node_init|sl_btmesh_node_init| |
|gecko_cmd_mesh_node_start_unprov_beaconing|sl_btmesh_node_start_unprov_beaconing| |
|gecko_cmd_mesh_node_stop_unprov_beaconing|sl_btmesh_node_stop_unprov_beaconing| |
|gecko_cmd_mesh_node_rssi|sl_btmesh_node_get_rssi| |
|gecko_cmd_mesh_node_input_oob_request_rsp|sl_btmesh_node_send_input_oob_request_response| |
|gecko_cmd_mesh_node_get_uuid|sl_btmesh_node_get_uuid| |
|gecko_cmd_mesh_node_set_provisioning_data|sl_btmesh_node_set_provisioning_data| |
|gecko_cmd_mesh_node_init_oob|sl_btmesh_node_init_oob| |
|gecko_cmd_mesh_node_set_ivrecovery_mode|sl_btmesh_node_set_ivrecovery_mode| |
|gecko_cmd_mesh_node_get_ivrecovery_mode|sl_btmesh_node_get_ivrecovery_mode| |
|gecko_cmd_mesh_node_set_adv_event_filter|sl_btmesh_node_set_adv_event_filter| |
|gecko_cmd_mesh_node_get_statistics|sl_btmesh_node_get_statistics| |
|gecko_cmd_mesh_node_clear_statistics|sl_btmesh_node_clear_statistics| |
|gecko_cmd_mesh_node_set_net_relay_delay|sl_btmesh_node_set_net_relay_delay| |
|gecko_cmd_mesh_node_get_net_relay_delay|sl_btmesh_node_get_net_relay_delay| |
|gecko_cmd_mesh_node_get_ivupdate_state|sl_btmesh_node_get_ivupdate_state| |
|gecko_cmd_mesh_node_request_ivupdate|sl_btmesh_node_request_ivupdate| |
|gecko_cmd_mesh_node_get_seq_remaining|sl_btmesh_node_get_seq_remaining| |
|gecko_cmd_mesh_node_save_replay_protection_list|sl_btmesh_node_save_replay_protection_list| |
|gecko_cmd_mesh_node_set_uuid|sl_btmesh_node_set_uuid| |
|gecko_cmd_mesh_node_get_element_address|sl_btmesh_node_get_element_address| |
|gecko_cmd_mesh_node_static_oob_request_rsp|sl_btmesh_node_send_static_oob_request_response| |
|gecko_cmd_mesh_node_reset|sl_btmesh_node_reset| |
|gecko_cmd_mesh_node_set_beacon_reporting|sl_btmesh_node_set_beacon_reporting| |
|gecko_cmd_mesh_node_set_iv_update_age|sl_btmesh_node_set_iv_update_age| |
|gecko_cmd_mesh_node_set_model_option|sl_btmesh_node_set_model_option| |
| |sl_btmesh_node_get_replay_protection_list_status| |
| |sl_btmesh_node_get_key_count| |
| |sl_btmesh_node_get_key| |
| |sl_btmesh_node_get_networks| |
| |sl_btmesh_node_get_element_seqnum| |
| |sl_btmesh_node_get_local_dcd| |
| |sl_btmesh_node_erase_mesh_nvm| |
| | | |
|CLASS: mesh_prov|CLASS: mesh_prov| |
|gecko_cmd_mesh_prov_init|sl_btmesh_prov_init| |
|gecko_cmd_mesh_prov_scan_unprov_beacons|sl_btmesh_prov_scan_unprov_beacons| |
|gecko_cmd_mesh_prov_provision_device|sl_btmesh_prov_provision_adv_device| |
|gecko_cmd_mesh_prov_create_network|sl_btmesh_prov_create_network| |
|gecko_cmd_mesh_prov_create_appkey|sl_btmesh_prov_create_appkey| |
|gecko_cmd_mesh_prov_oob_pkey_rsp|sl_btmesh_prov_send_oob_pkey_response| |
|gecko_cmd_mesh_prov_oob_auth_rsp|sl_btmesh_prov_send_oob_auth_response| |
|gecko_cmd_mesh_prov_set_oob_requirements|sl_btmesh_prov_set_oob_requirements| |
|gecko_cmd_mesh_prov_key_refresh_start|sl_btmesh_prov_start_key_refresh| |
|gecko_cmd_mesh_prov_get_key_refresh_blacklist|sl_btmesh_prov_get_key_refresh_exclusion| |
|gecko_cmd_mesh_prov_set_key_refresh_blacklist|sl_btmesh_prov_set_key_refresh_exclusion| |
|gecko_cmd_mesh_prov_provision_gatt_device|sl_btmesh_prov_provision_gatt_device| |
|gecko_cmd_mesh_prov_ddb_get|sl_btmesh_prov_get_ddb_entry| |
|gecko_cmd_mesh_prov_ddb_delete|sl_btmesh_prov_delete_ddb_entry| |
|gecko_cmd_mesh_prov_ddb_add|sl_btmesh_prov_add_ddb_entry| |
|gecko_cmd_mesh_prov_ddb_list_devices|sl_btmesh_prov_list_ddb_entries| |
|gecko_cmd_mesh_prov_provision_device_with_address|sl_btmesh_prov_set_device_address|When provisioning is suspended, use this command to set the address|
|gecko_cmd_mesh_prov_provision_gatt_device_with_address|sl_btmesh_prov_set_device_address|When provisioning is suspended, use this command to set the address|
|gecko_cmd_mesh_prov_initialize_network|sl_btmesh_prov_initialize_network| |
|gecko_cmd_mesh_prov_get_key_refresh_appkey_blacklist|sl_btmesh_prov_get_key_refresh_appkey_exclusion| |
|gecko_cmd_mesh_prov_set_key_refresh_appkey_blacklist|sl_btmesh_prov_set_key_refresh_appkey_exclusion| |
|gecko_cmd_mesh_prov_stop_scan_unprov_beacons|sl_btmesh_prov_stop_scan_unprov_beacons| |
|gecko_cmd_mesh_prov_ddb_update_netkey_index|sl_btmesh_prov_update_device_netkey_index| |
|gecko_cmd_mesh_prov_key_refresh_suspend|sl_btmesh_prov_suspend_key_refresh| |
|gecko_cmd_mesh_prov_key_refresh_resume|sl_btmesh_prov_resume_key_refresh| |
|gecko_cmd_mesh_prov_get_key_refresh_phase|sl_btmesh_prov_get_key_refresh_phase| |
|gecko_cmd_mesh_prov_key_refresh_start_from_phase|sl_btmesh_prov_start_key_refresh_from_phase| |
|gecko_cmd_mesh_prov_flush_key_refresh_state|sl_btmesh_prov_flush_key_refresh_state| |
| |sl_btmesh_prov_create_provisioning_session|Users have to create the provisioning session before configuring or start the provisioning|
| |sl_btmesh_prov_set_provisioning_suspend_event|These APIs give more flexibility in provisioning, now it can suspend and users could use callbacks to feed configuration data during provisioning.|
| |sl_btmesh_prov_continue_provisioning| |
| |sl_btmesh_prov_abort_provisioning| |
| |sl_btmesh_prov_test_identity|API for testing if the node identify matches|
| | | |
|CLASS: mesh_proxy|CLASS: mesh_proxy| |
|gecko_cmd_mesh_proxy_connect|sl_btmesh_proxy_connect| |
|gecko_cmd_mesh_proxy_disconnect|sl_btmesh_proxy_disconnect| |
|gecko_cmd_mesh_proxy_set_filter_type|sl_btmesh_proxy_set_filter_type| |
|gecko_cmd_mesh_proxy_allow|sl_btmesh_proxy_allow| |
|gecko_cmd_mesh_proxy_deny|sl_btmesh_proxy_deny| |
| | | |
|CLASS: mesh_scene_client|CLASS: mesh_scene_client| |
|gecko_cmd_mesh_scene_client_init|sl_btmesh_scene_client_init| |
|gecko_cmd_mesh_scene_client_get|sl_btmesh_scene_client_get| |
|gecko_cmd_mesh_scene_client_get_register|sl_btmesh_scene_client_get_register| |
|gecko_cmd_mesh_scene_client_recall|sl_btmesh_scene_client_recall| |
|gecko_cmd_mesh_scene_client_store|sl_btmesh_scene_client_store| |
|gecko_cmd_mesh_scene_client_delete|sl_btmesh_scene_client_delete| |
| | | |
|CLASS: mesh_scene_server|CLASS: mesh_scene_server| |
|gecko_cmd_mesh_scene_server_init|sl_btmesh_scene_server_init| |
|gecko_cmd_mesh_scene_server_deinit|sl_btmesh_scene_server_deinit| |
|gecko_cmd_mesh_scene_server_reset_register|sl_btmesh_scene_server_reset_register| |
| | | |
|CLASS: mesh_scene_setup_server|CLASS: mesh_scene_setup_server| |
|gecko_cmd_mesh_scene_setup_server_init|sl_btmesh_scene_setup_server_init| |
| | | |
|CLASS: mesh_scheduler_client|CLASS: mesh_scheduler_client| |
|gecko_cmd_mesh_scheduler_client_init|sl_btmesh_scheduler_client_init| |
|gecko_cmd_mesh_scheduler_client_deinit|sl_btmesh_scheduler_client_deinit| |
|gecko_cmd_mesh_scheduler_client_get|sl_btmesh_scheduler_client_get| |
|gecko_cmd_mesh_scheduler_client_get_action|sl_btmesh_scheduler_client_get_action| |
|gecko_cmd_mesh_scheduler_client_set_action|sl_btmesh_scheduler_client_set_action| |
| | | |
|CLASS: mesh_scheduler_server|CLASS: mesh_scheduler_server| |
|gecko_cmd_mesh_scheduler_server_init|sl_btmesh_scheduler_server_init| |
|gecko_cmd_mesh_scheduler_server_deinit|sl_btmesh_scheduler_server_deinit| |
|gecko_cmd_mesh_scheduler_server_get|sl_btmesh_scheduler_server_get| |
|gecko_cmd_mesh_scheduler_server_get_action|sl_btmesh_scheduler_server_get_action| |
|gecko_cmd_mesh_scheduler_server_set_action|sl_btmesh_scheduler_server_set_action| |
| | | |
|CLASS: mesh_sensor_client|CLASS: mesh_sensor_client| |
|gecko_cmd_mesh_sensor_client_init|sl_btmesh_sensor_client_init| |
|gecko_cmd_mesh_sensor_client_deinit|sl_btmesh_sensor_client_deinit| |
|gecko_cmd_mesh_sensor_client_get_descriptor|sl_btmesh_sensor_client_get_descriptor| |
|gecko_cmd_mesh_sensor_client_get|sl_btmesh_sensor_client_get| |
|gecko_cmd_mesh_sensor_client_get_column|sl_btmesh_sensor_client_get_column| |
|gecko_cmd_mesh_sensor_client_get_series|sl_btmesh_sensor_client_get_series| |
|gecko_cmd_mesh_sensor_client_get_cadence|sl_btmesh_sensor_client_get_cadence| |
|gecko_cmd_mesh_sensor_client_set_cadence|sl_btmesh_sensor_client_set_cadence| |
|gecko_cmd_mesh_sensor_client_get_settings|sl_btmesh_sensor_client_get_settings| |
|gecko_cmd_mesh_sensor_client_get_setting|sl_btmesh_sensor_client_get_setting| |
|gecko_cmd_mesh_sensor_client_set_setting|sl_btmesh_sensor_client_set_setting| |
| | | |
|CLASS: mesh_sensor_server|CLASS: mesh_sensor_server| |
|gecko_cmd_mesh_sensor_server_init|sl_btmesh_sensor_server_init| |
|gecko_cmd_mesh_sensor_server_deinit|sl_btmesh_sensor_server_deinit| |
|gecko_cmd_mesh_sensor_server_send_descriptor_status|sl_btmesh_sensor_server_send_descriptor_status| |
|gecko_cmd_mesh_sensor_server_send_status|sl_btmesh_sensor_server_send_status| |
|gecko_cmd_mesh_sensor_server_send_column_status|sl_btmesh_sensor_server_send_column_status| |
|gecko_cmd_mesh_sensor_server_send_series_status|sl_btmesh_sensor_server_send_series_status| |
| | | |
|CLASS: mesh_sensor_setup_server|CLASS: mesh_sensor_setup_server| |
|gecko_cmd_mesh_sensor_setup_server_send_cadence_status|sl_btmesh_sensor_setup_server_send_cadence_status| |
|gecko_cmd_mesh_sensor_setup_server_send_settings_status|sl_btmesh_sensor_setup_server_send_settings_status| |
|gecko_cmd_mesh_sensor_setup_server_send_setting_status|sl_btmesh_sensor_setup_server_send_setting_status| |
| | | |
|CLASS: mesh_test|CLASS: mesh_test| |
|gecko_cmd_mesh_test_get_nettx|sl_btmesh_test_get_nettx| |
|gecko_cmd_mesh_test_set_nettx|sl_btmesh_test_set_nettx| |
|gecko_cmd_mesh_test_get_relay|sl_btmesh_test_get_relay| |
|gecko_cmd_mesh_test_set_relay|sl_btmesh_test_set_relay| |
|gecko_cmd_mesh_test_set_adv_scan_params|sl_btmesh_test_set_adv_scan_params| |
|gecko_cmd_mesh_test_set_ivupdate_test_mode|sl_btmesh_test_set_ivupdate_test_mode| |
|gecko_cmd_mesh_test_get_ivupdate_test_mode|sl_btmesh_test_get_ivupdate_test_mode| |
|gecko_cmd_mesh_test_set_segment_send_delay|sl_btmesh_test_set_segment_send_delay| |
|gecko_cmd_mesh_test_set_ivupdate_state|sl_btmesh_test_set_ivupdate_state| |
|gecko_cmd_mesh_test_send_beacons|sl_btmesh_test_send_beacons| |
|gecko_cmd_mesh_test_bind_local_model_app|sl_btmesh_test_bind_local_model_app| |
|gecko_cmd_mesh_test_unbind_local_model_app|sl_btmesh_test_unbind_local_model_app| |
|gecko_cmd_mesh_test_add_local_model_sub|sl_btmesh_test_add_local_model_sub| |
|gecko_cmd_mesh_test_del_local_model_sub|sl_btmesh_test_remove_local_model_sub| |
|gecko_cmd_mesh_test_add_local_model_sub_va|sl_btmesh_test_add_local_model_sub_va| |
|gecko_cmd_mesh_test_del_local_model_sub_va|sl_btmesh_test_remove_local_model_sub_va| |
|gecko_cmd_mesh_test_get_local_model_sub|sl_btmesh_test_get_local_model_sub| |
|gecko_cmd_mesh_test_set_local_model_pub|sl_btmesh_test_set_local_model_pub| |
|gecko_cmd_mesh_test_set_local_model_pub_va|sl_btmesh_test_set_local_model_pub_va| |
|gecko_cmd_mesh_test_get_local_model_pub|sl_btmesh_test_get_local_model_pub| |
|gecko_cmd_mesh_test_set_local_heartbeat_subscription|sl_btmesh_test_set_local_heartbeat_subscription| |
|gecko_cmd_mesh_test_get_local_heartbeat_subscription|sl_btmesh_test_get_local_heartbeat_subscription| |
|gecko_cmd_mesh_test_get_local_heartbeat_publication|sl_btmesh_test_get_local_heartbeat_publication| |
|gecko_cmd_mesh_test_set_local_heartbeat_publication|sl_btmesh_test_set_local_heartbeat_publication| |
|gecko_cmd_mesh_test_set_local_config|sl_btmesh_test_set_local_config| |
|gecko_cmd_mesh_test_get_local_config|sl_btmesh_test_get_local_config| |
|gecko_cmd_mesh_test_add_local_key|sl_btmesh_test_add_local_key| |
|gecko_cmd_mesh_test_del_local_key|sl_btmesh_test_remove_local_key| |
|gecko_cmd_mesh_test_update_local_key|sl_btmesh_test_update_local_key| |
|gecko_cmd_mesh_test_set_sar_config|sl_btmesh_test_set_sar_config| |
|gecko_cmd_mesh_test_get_element_seqnum| | |
|gecko_cmd_mesh_test_set_adv_bearer_state|sl_btmesh_test_set_adv_bearer_state| |
|gecko_cmd_mesh_test_get_key_count| |Moved to mesh_node class|
|gecko_cmd_mesh_test_get_key| | |
|gecko_cmd_mesh_test_prov_get_device_key|sl_btmesh_test_prov_get_device_key| |
|gecko_cmd_mesh_test_prov_prepare_key_refresh|sl_btmesh_test_prov_prepare_key_refresh| |
|gecko_cmd_mesh_test_cancel_segmented_tx|sl_btmesh_test_cancel_segmented_tx| |
|gecko_cmd_mesh_test_set_iv_index|sl_btmesh_test_set_iv_index| |
|gecko_cmd_mesh_test_set_element_seqnum|sl_btmesh_test_set_element_seqnum| |
|gecko_cmd_mesh_test_set_model_option|sl_btmesh_test_set_model_option| |
|gecko_cmd_mesh_test_get_local_model_app_bindings|sl_btmesh_test_get_local_model_app_bindings| |
|gecko_cmd_mesh_test_get_replay_protection_list_entry|sl_btmesh_test_get_replay_protection_list_entry| |
|gecko_cmd_mesh_test_clear_replay_protection_list_entry|sl_btmesh_test_clear_replay_protection_list_entry| |
| | | |
|CLASS: mesh_time_client|CLASS: mesh_time_client| |
|gecko_cmd_mesh_time_client_init|sl_btmesh_time_client_init| |
|gecko_cmd_mesh_time_client_deinit|sl_btmesh_time_client_deinit| |
|gecko_cmd_mesh_time_client_get_time|sl_btmesh_time_client_get_time| |
|gecko_cmd_mesh_time_client_set_time|sl_btmesh_time_client_set_time| |
|gecko_cmd_mesh_time_client_get_time_zone|sl_btmesh_time_client_get_time_zone| |
|gecko_cmd_mesh_time_client_set_time_zone|sl_btmesh_time_client_set_time_zone| |
|gecko_cmd_mesh_time_client_get_tai_utc_delta|sl_btmesh_time_client_get_tai_utc_delta| |
|gecko_cmd_mesh_time_client_set_tai_utc_delta|sl_btmesh_time_client_set_tai_utc_delta| |
|gecko_cmd_mesh_time_client_get_time_role|sl_btmesh_time_client_get_time_role| |
|gecko_cmd_mesh_time_client_set_time_role|sl_btmesh_time_client_set_time_role| |
| | | |
|CLASS: mesh_time_server|CLASS: mesh_time_server| |
|gecko_cmd_mesh_time_server_init|sl_btmesh_time_server_init| |
|gecko_cmd_mesh_time_server_deinit|sl_btmesh_time_server_deinit| |
|gecko_cmd_mesh_time_server_get_time|sl_btmesh_time_server_get_time| |
|gecko_cmd_mesh_time_server_set_time|sl_btmesh_time_server_set_time| |
|gecko_cmd_mesh_time_server_get_time_zone_offset_new|sl_btmesh_time_server_get_time_zone_offset_new| |
|gecko_cmd_mesh_time_server_set_time_zone_offset_new|sl_btmesh_time_server_set_time_zone_offset_new| |
|gecko_cmd_mesh_time_server_get_tai_utc_delta_new|sl_btmesh_time_server_get_tai_utc_delta_new| |
|gecko_cmd_mesh_time_server_set_tai_utc_delta_new|sl_btmesh_time_server_set_tai_utc_delta_new| |
|gecko_cmd_mesh_time_server_get_time_role|sl_btmesh_time_server_get_time_role| |
|gecko_cmd_mesh_time_server_set_time_role|sl_btmesh_time_server_set_time_role| |
|gecko_cmd_mesh_time_server_get_datetime|sl_btmesh_time_server_get_datetime| |
| | | |
|CLASS: mesh_vendor_model|CLASS: mesh_vendor_model| |
|gecko_cmd_mesh_vendor_model_send|sl_btmesh_vendor_model_send| |
|gecko_cmd_mesh_vendor_model_set_publication|sl_btmesh_vendor_model_set_publication| |
|gecko_cmd_mesh_vendor_model_clear_publication|sl_btmesh_vendor_model_clear_publication| |
|gecko_cmd_mesh_vendor_model_publish|sl_btmesh_vendor_model_publish| |
|gecko_cmd_mesh_vendor_model_init|sl_btmesh_vendor_model_init| |
|gecko_cmd_mesh_vendor_model_deinit|sl_btmesh_vendor_model_deinit| |

##### Changes in BGAPI events

Just like BGAPI commands, BGAPI events are also renamed. In Bluetooth Mesh SDK v2.x event IDs start with `sl_btmesh_evt_instead` of `gecko_evt_`. Similarly, the event struct types start with `sl_btmesh_evt_instead` of `gecko_msg_evt`, although these types are rarely referenced in the application.

Additionally, some events are renamed because of changing BGAPI class. In the following table contains all the events that have more than just the name change.

|API 1.x|API 2.0|Notes|
|---|---|---|
|CLASS: mesh_config|CLASS: mesh_config|There is no change to this class except the prefix change.|
|gecko_evt_mesh_config_client_appkey_list_id struct gecko_msg_mesh_config_client_appkey_list_evt_t|sl_btmesh_evt_config_client_appkey_list_id sl_btmesh_evt_config_client_appkey_list_t| |
|gecko_evt_mesh_config_client_request_modified_id gecko_msg_mesh_config_client_request_modified_evt_t|sl_btmesh_evt_config_client_request_modified_id sl_btmesh_evt_config_client_request_modified_t| |
|gecko_evt_mesh_config_client_netkey_status_id gecko_msg_mesh_config_client_netkey_status_evt_t|sl_btmesh_evt_config_client_netkey_status_id sl_btmesh_evt_config_client_netkey_status_t| |
|gecko_evt_mesh_config_client_netkey_list_id gecko_msg_mesh_config_client_netkey_list_evt_t|sl_btmesh_evt_config_client_netkey_list_id sl_btmesh_evt_config_client_netkey_list_t| |
|gecko_evt_mesh_config_client_netkey_list_end_id gecko_msg_mesh_config_client_netkey_list_end_evt_t|sl_btmesh_evt_config_client_netkey_list_end_id sl_btmesh_evt_config_client_netkey_list_end_t| |
|gecko_evt_mesh_config_client_appkey_status_id gecko_msg_mesh_config_client_appkey_status_evt_t|sl_btmesh_evt_config_client_appkey_status_id sl_btmesh_evt_config_client_appkey_status_t| |
|gecko_evt_mesh_config_client_appkey_list_id gecko_msg_mesh_config_client_appkey_list_evt_t|sl_btmesh_evt_config_client_appkey_list_id sl_btmesh_evt_config_client_appkey_list_t| |
|gecko_evt_mesh_config_client_appkey_list_end_id gecko_msg_mesh_config_client_appkey_list_end_evt_t|sl_btmesh_evt_config_client_appkey_list_end_id sl_btmesh_evt_config_client_appkey_list_end_t| |
|gecko_evt_mesh_config_client_binding_status_id gecko_msg_mesh_config_client_binding_status_evt_t|sl_btmesh_evt_config_client_binding_status_id sl_btmesh_evt_config_client_binding_status_t| |
|gecko_evt_mesh_config_client_bindings_list_id gecko_msg_mesh_config_client_bindings_list_evt_t|sl_btmesh_evt_config_client_bindings_list_id sl_btmesh_evt_config_client_bindings_list_t| |
|gecko_evt_mesh_config_client_bindings_list_end_id gecko_msg_mesh_config_client_bindings_list_end_evt_t|sl_btmesh_evt_config_client_bindings_list_end_id sl_btmesh_evt_config_client_bindings_list_end_t| |
|gecko_evt_mesh_config_client_model_pub_status_id gecko_msg_mesh_config_client_model_pub_status_evt_t|sl_btmesh_evt_config_client_model_pub_status_id sl_btmesh_evt_config_client_model_pub_status_t| |
|gecko_evt_mesh_config_client_model_sub_status_id gecko_msg_mesh_config_client_model_sub_status_evt_t|sl_btmesh_evt_config_client_model_sub_status_id sl_btmesh_evt_config_client_model_sub_status_t| |
|gecko_evt_mesh_config_client_subs_list_id gecko_msg_mesh_config_client_subs_list_evt_t|sl_btmesh_evt_config_client_subs_list_id sl_btmesh_evt_config_client_subs_list_t| |
|gecko_evt_mesh_config_client_subs_list_end_id gecko_msg_mesh_config_client_subs_list_end_evt_t|sl_btmesh_evt_config_client_subs_list_end_id sl_btmesh_evt_config_client_subs_list_end_t| |
|gecko_evt_mesh_config_client_heartbeat_pub_status_id gecko_msg_mesh_config_client_heartbeat_pub_status_evt_t|sl_btmesh_evt_config_client_heartbeat_pub_status_id sl_btmesh_evt_config_client_heartbeat_pub_status_t| |
|gecko_evt_mesh_config_client_heartbeat_sub_status_id gecko_msg_mesh_config_client_heartbeat_sub_status_evt_t|sl_btmesh_evt_config_client_heartbeat_sub_status_id sl_btmesh_evt_config_client_heartbeat_sub_status_t| |
|gecko_evt_mesh_config_client_beacon_status_id gecko_msg_mesh_config_client_beacon_status_evt_t|sl_btmesh_evt_config_client_beacon_status_id sl_btmesh_evt_config_client_beacon_status_t| |
|gecko_evt_mesh_config_client_default_ttl_status_id gecko_msg_mesh_config_client_default_ttl_status_evt_t|sl_btmesh_evt_config_client_default_ttl_status_id sl_btmesh_evt_config_client_default_ttl_status_t| |
|gecko_evt_mesh_config_client_gatt_proxy_status_id gecko_msg_mesh_config_client_gatt_proxy_status_evt_t|sl_btmesh_evt_config_client_gatt_proxy_status_id sl_btmesh_evt_config_client_gatt_proxy_status_t| |
|gecko_evt_mesh_config_client_relay_status_id gecko_msg_mesh_config_client_relay_status_evt_t|sl_btmesh_evt_config_client_relay_status_id sl_btmesh_evt_config_client_relay_status_t| |
|gecko_evt_mesh_config_client_network_transmit_status_id gecko_msg_mesh_config_client_network_transmit_status_evt_t|sl_btmesh_evt_config_client_network_transmit_status_id sl_btmesh_evt_config_client_network_transmit_status_t| |
|gecko_evt_mesh_config_client_identity_status_id gecko_msg_mesh_config_client_identity_status_evt_t|sl_btmesh_evt_config_client_identity_status_id sl_btmesh_evt_config_client_identity_status_t| |
|gecko_evt_mesh_config_client_friend_status_id gecko_msg_mesh_config_client_friend_status_evt_t|sl_btmesh_evt_config_client_friend_status_id sl_btmesh_evt_config_client_friend_status_t| |
|gecko_evt_mesh_config_client_lpn_polltimeout_status_id gecko_msg_mesh_config_client_lpn_polltimeout_status_evt_t|sl_btmesh_evt_config_client_lpn_polltimeout_status_id sl_btmesh_evt_config_client_lpn_polltimeout_status_t| |
|gecko_evt_mesh_config_client_dcd_data_id gecko_msg_mesh_config_client_dcd_data_evt_t|sl_btmesh_evt_config_client_dcd_data_id sl_btmesh_evt_config_client_dcd_data_t| |
|gecko_evt_mesh_config_client_dcd_data_end_id gecko_msg_mesh_config_client_dcd_data_end_evt_t|sl_btmesh_evt_config_client_dcd_data_end_id sl_btmesh_evt_config_client_dcd_data_end_t| |
|gecko_evt_mesh_config_client_reset_status_id gecko_msg_mesh_config_client_reset_status_evt_t|sl_btmesh_evt_config_client_reset_status_id sl_btmesh_evt_config_client_reset_status_t| |
| | | |
|CLASS: mesh_friend|CLASS: mesh_ friend|There is no change to this class except the prefix change.|
|gecko_evt_mesh_friend_friendship_established_id gecko_msg_mesh_friend_friendship_established_evt_t|sl_btmesh_evt_friend_friendship_established_id sl_btmesh_evt_friend_friendship_established_t| |
|gecko_evt_mesh_friend_friendship_terminated_id gecko_msg_mesh_friend_friendship_terminated_evt_t|sl_btmesh_evt_friend_friendship_terminated_id sl_btmesh_evt_friend_friendship_terminated_t| |
| | | |
|CLASS: mesh_generic_client|CLASS: mesh_generic_client|There is no change to this class except the prefix change.|
|gecko_evt_mesh_generic_client_server_status_id gecko_msg_mesh_generic_client_server_status_evt_t|sl_btmesh_evt_generic_client_server_status_id sl_btmesh_evt_generic_client_server_status_t| |
| | | |
|CLASS: mesh_generic_server|CLASS: mesh_generic_server|There is no change to this class except the prefix change.|
|gecko_evt_mesh_generic_server_client_request_id gecko_msg_mesh_generic_server_client_request_evt_t|sl_btmesh_evt_generic_server_client_request_id sl_btmesh_evt_generic_server_client_request_t| |
|gecko_evt_mesh_generic_server_state_changed_id gecko_msg_mesh_generic_server_state_changed_evt_t|sl_btmesh_evt_generic_server_state_changed_id sl_btmesh_evt_generic_server_state_changed_t| |
|gecko_evt_mesh_generic_server_state_recall_id gecko_msg_mesh_generic_server_state_recall_evt_t|sl_btmesh_evt_generic_server_state_recall_id sl_btmesh_evt_generic_server_state_recall_t| |
| | | |
|CLASS: mesh_health_client|CLASS: mesh_health_client|There is no change to this class except the prefix change.|
|gecko_evt_mesh_health_client_server_status_id gecko_msg_mesh_health_client_server_status_evt_t|sl_btmesh_evt_health_client_server_status_id sl_btmesh_evt_health_client_server_status_t| |
|gecko_evt_mesh_health_client_server_status_period_id gecko_msg_mesh_health_client_server_status_period_evt_t|sl_btmesh_evt_health_client_server_status_period_id sl_btmesh_evt_health_client_server_status_period_t| |
|gecko_evt_mesh_health_client_server_status_attention_id gecko_msg_mesh_health_client_server_status_attention_evt_t|sl_btmesh_evt_health_client_server_status_attention_id sl_btmesh_evt_health_client_server_status_attention_t| |
| | | |
|CLASS: mesh_health_server|CLASS: mesh_health_server|There is no change to this class except the prefix change.|
|gecko_evt_mesh_health_server_attention_id gecko_msg_mesh_health_server_attention_evt_t|sl_btmesh_evt_health_server_attention_id sl_btmesh_evt_health_server_attention_t| |
|gecko_evt_mesh_health_server_test_request_id gecko_msg_mesh_health_server_test_request_evt_t|sl_btmesh_evt_health_server_test_request_id sl_btmesh_evt_health_server_test_request_t| |
| | | |
|CLASS: mesh_lc_client|CLASS: mesh_lc_client|There is no change to this class except the prefix change.|
|gecko_evt_mesh_lc_client_mode_status_id gecko_msg_mesh_lc_client_mode_status_evt_t|sl_btmesh_evt_lc_client_mode_status_id sl_btmesh_evt_lc_client_mode_status_t| |
|gecko_evt_mesh_lc_client_om_status_id gecko_msg_mesh_lc_client_om_status_evt_t|sl_btmesh_evt_lc_client_om_status_id sl_btmesh_evt_lc_client_om_status_t| |
|gecko_evt_mesh_lc_client_light_onoff_status_id gecko_msg_mesh_lc_client_light_onoff_status_evt_t|sl_btmesh_evt_lc_client_light_onoff_status_id sl_btmesh_evt_lc_client_light_onoff_status_t| |
|gecko_evt_mesh_lc_client_property_status_id gecko_msg_mesh_lc_client_property_status_evt_t|sl_btmesh_evt_lc_client_property_status_id sl_btmesh_evt_lc_client_property_status_t| |
| | | |
|CLASS: mesh_lc_server|CLASS: mesh_lc_server|There is no change to this class except the prefix change.|
|gecko_evt_mesh_lc_server_mode_updated_id gecko_msg_mesh_lc_server_mode_updated_evt_t|sl_btmesh_evt_lc_server_mode_updated_id sl_btmesh_evt_lc_server_mode_updated_t| |
|gecko_evt_mesh_lc_server_om_updated_id gecko_msg_mesh_lc_server_om_updated_evt_t|sl_btmesh_evt_lc_server_om_updated_id sl_btmesh_evt_lc_server_om_updated_t| |
|gecko_evt_mesh_lc_server_light_onoff_updated_id gecko_msg_mesh_lc_server_light_onoff_updated_evt_t|sl_btmesh_evt_lc_server_light_onoff_updated_id sl_btmesh_evt_lc_server_light_onoff_updated_t| |
|gecko_evt_mesh_lc_server_occupancy_updated_id gecko_msg_mesh_lc_server_occupancy_updated_evt_t|sl_btmesh_evt_lc_server_occupancy_updated_id sl_btmesh_evt_lc_server_occupancy_updated_t| |
|gecko_evt_mesh_lc_server_ambient_lux_level_updated_id gecko_msg_mesh_lc_server_ambient_lux_level_updated_evt_t|sl_btmesh_evt_lc_server_ambient_lux_level_updated_id sl_btmesh_evt_lc_server_ambient_lux_level_updated_t| |
|gecko_evt_mesh_lc_server_linear_output_updated_id gecko_msg_mesh_lc_server_linear_output_updated_evt_t|sl_btmesh_evt_lc_server_linear_output_updated_id sl_btmesh_evt_lc_server_linear_output_updated_t| |
|gecko_evt_mesh_lc_server_state_updated_id gecko_msg_mesh_lc_server_state_updated_evt_t|sl_btmesh_evt_lc_server_state_updated_id sl_btmesh_evt_lc_server_state_updated_t| |
|gecko_evt_mesh_lc_server_regulator_debug_info_id gecko_msg_mesh_lc_server_regulator_debug_info_evt_t|sl_btmesh_evt_lc_server_regulator_debug_info_id sl_btmesh_evt_lc_server_regulator_debug_info_t| |
| | | |
|CLASS: mesh_lc_setup_server|CLASS: mesh_lc_setup_server|There is no change to this class except the prefix change.|
|gecko_evt_mesh_lc_setup_server_set_property_id gecko_msg_mesh_lc_setup_server_set_property_evt_t|sl_btmesh_evt_lc_setup_server_set_property_id sl_btmesh_evt_lc_setup_server_set_property_t| |
| | | |
|CLASS: mesh_lpn|CLASS: mesh_lpn|There is no change to this class except the prefix change.|
|gecko_evt_mesh_lpn_friendship_established_id gecko_msg_mesh_lpn_friendship_established_evt_t|sl_btmesh_evt_lpn_friendship_established_id sl_btmesh_evt_lpn_friendship_established_t| |
|gecko_evt_mesh_lpn_friendship_failed_id gecko_msg_mesh_lpn_friendship_failed_evt_t|sl_btmesh_evt_lpn_friendship_failed_id sl_btmesh_evt_lpn_friendship_failed_t| |
|gecko_evt_mesh_lpn_friendship_terminated_id gecko_msg_mesh_lpn_friendship_terminated_evt_t|sl_btmesh_evt_lpn_friendship_terminated_id sl_btmesh_evt_lpn_friendship_terminated_t| |
| | | |
|CLASS: mesh_node|CLASS: mesh_node| |
|gecko_evt_mesh_node_initialized_id gecko_msg_mesh_node_initialized_evt_t|sl_btmesh_evt_node_initialized_id sl_btmesh_evt_node_initialized_t| |
|gecko_evt_mesh_node_provisioned_id gecko_msg_mesh_node_provisioned_evt_t|sl_btmesh_evt_node_provisioned_id sl_btmesh_evt_node_provisioned_t| |
|gecko_evt_mesh_node_config_get_id gecko_msg_mesh_node_config_get_evt_t|sl_btmesh_evt_node_config_get_id sl_btmesh_evt_node_config_get_t| |
|gecko_evt_mesh_node_config_set_id gecko_msg_mesh_node_config_set_evt_t|sl_btmesh_evt_node_config_set_id sl_btmesh_evt_node_config_set_t| |
|gecko_evt_mesh_node_display_output_oob_id gecko_msg_mesh_node_display_output_oob_evt_t|sl_btmesh_evt_node_display_output_oob_id sl_btmesh_evt_node_display_output_oob_t| |
|gecko_evt_mesh_node_input_oob_request_id gecko_msg_mesh_node_input_oob_request_evt_t|sl_btmesh_evt_node_input_oob_request_id sl_btmesh_evt_node_input_oob_request_t| |
|gecko_evt_mesh_node_provisioning_started_id gecko_msg_mesh_node_provisioning_started_evt_t|sl_btmesh_evt_node_provisioning_started_id sl_btmesh_evt_node_provisioning_started_t| |
|gecko_evt_mesh_node_provisioning_failed_id gecko_msg_mesh_node_provisioning_failed_evt_t|sl_btmesh_evt_node_provisioning_failed_id sl_btmesh_evt_node_provisioning_failed_t| |
|gecko_evt_mesh_node_key_added_id gecko_msg_mesh_node_key_added_evt_t|sl_btmesh_evt_node_key_added_id sl_btmesh_evt_node_key_added_t| |
|gecko_evt_mesh_node_model_config_changed_id gecko_msg_mesh_node_model_config_changed_evt_t|sl_btmesh_evt_node_model_config_changed_id sl_btmesh_evt_node_model_config_changed_t| |
|gecko_evt_mesh_node_reset_id gecko_msg_mesh_node_reset_evt_t|sl_btmesh_evt_node_reset_id|No event anymore|
|gecko_evt_mesh_node_ivrecovery_needed_id gecko_msg_mesh_node_ivrecovery_needed_evt_t|sl_btmesh_evt_node_ivrecovery_needed_id sl_btmesh_evt_node_ivrecovery_needed_t| |
|gecko_evt_mesh_node_changed_ivupdate_state_id gecko_msg_mesh_node_changed_ivupdate_state_evt_t|sl_btmesh_evt_node_changed_ivupdate_state_id sl_btmesh_evt_node_changed_ivupdate_state_t| |
|gecko_evt_mesh_node_static_oob_request_id gecko_msg_mesh_node_static_oob_request_evt_t|sl_btmesh_evt_node_static_oob_request_id|No event anymore|
|gecko_evt_mesh_node_key_removed_id gecko_msg_mesh_node_key_removed_evt_t|sl_btmesh_evt_node_key_removed_id sl_btmesh_evt_node_key_removed_t| |
|gecko_evt_mesh_node_key_updated_id gecko_msg_mesh_node_key_updated_evt_t|sl_btmesh_evt_node_key_updated_id sl_btmesh_evt_node_key_updated_t| |
|gecko_evt_mesh_node_heartbeat_id gecko_msg_mesh_node_heartbeat_evt_t|sl_btmesh_evt_node_heartbeat_id sl_btmesh_evt_node_heartbeat_t| |
|gecko_evt_mesh_node_heartbeat_start_id gecko_msg_mesh_node_heartbeat_start_evt_t|sl_btmesh_evt_node_heartbeat_start_id sl_btmesh_evt_node_heartbeat_start_t| |
|gecko_evt_mesh_node_heartbeat_stop_id gecko_msg_mesh_node_heartbeat_stop_evt_t|sl_btmesh_evt_node_heartbeat_stop_id sl_btmesh_evt_node_heartbeat_stop_t| |
|gecko_evt_mesh_node_beacon_received_id gecko_msg_mesh_node_beacon_received_evt_t|sl_btmesh_evt_node_beacon_received_id sl_btmesh_evt_node_beacon_received_t| |
| |sl_btmesh_evt_node_local_dcd_data_id sl_btmesh_evt_node_local_dcd_data_t|sl_btmesh_node_get_local_dcd will trigger this event, and it carries the DCD data|
| |sl_btmesh_evt_node_local_dcd_data_end_id sl_btmesh_evt_node_local_dcd_data_end_t|sl_btmesh_node_get_local_dcd will trigger this event, and it indicates all DCD data is reported|
| | | |
|CLASS: mesh_prov|CLASS: mesh_prov| |
|gecko_evt_mesh_prov_initialized_id gecko_msg_mesh_prov_initialized_evt_t|sl_btmesh_evt_prov_initialized_id sl_btmesh_evt_prov_initialized_t| |
|gecko_evt_mesh_prov_provisioning_failed_id gecko_msg_mesh_prov_provisioning_failed_evt_t|sl_btmesh_evt_prov_provisioning_failed_id sl_btmesh_evt_prov_provisioning_failed_t| |
|gecko_evt_mesh_prov_device_provisioned_id gecko_msg_mesh_prov_device_provisioned_evt_t|sl_btmesh_evt_prov_device_provisioned_id sl_btmesh_evt_prov_device_provisioned_t| |
|gecko_evt_mesh_prov_unprov_beacon_id gecko_msg_mesh_prov_unprov_beacon_evt_t|sl_btmesh_evt_prov_unprov_beacon_id sl_btmesh_evt_prov_unprov_beacon_t| |
|gecko_evt_mesh_prov_oob_pkey_request_id gecko_msg_mesh_prov_oob_pkey_request_evt_t|sl_btmesh_evt_prov_oob_pkey_request_id sl_btmesh_evt_prov_oob_pkey_request_t| |
|gecko_evt_mesh_prov_oob_auth_request_id gecko_msg_mesh_prov_oob_auth_request_evt_t|sl_btmesh_evt_prov_oob_auth_request_id sl_btmesh_evt_prov_oob_auth_request_t| |
|gecko_evt_mesh_prov_oob_display_input_id gecko_msg_mesh_prov_oob_display_input_evt_t|sl_btmesh_evt_prov_oob_display_input_id sl_btmesh_evt_prov_oob_display_input_t| |
|gecko_evt_mesh_prov_ddb_list_id gecko_msg_mesh_prov_ddb_list_evt_t|sl_btmesh_evt_prov_ddb_list_id sl_btmesh_evt_prov_ddb_list_t| |
|gecko_evt_mesh_prov_uri_id gecko_msg_mesh_prov_uri_evt_t|sl_btmesh_evt_prov_uri_id sl_btmesh_evt_prov_uri_t| |
|gecko_evt_mesh_prov_key_refresh_phase_update_id gecko_msg_mesh_prov_key_refresh_phase_update_evt_t|sl_btmesh_evt_prov_key_refresh_phase_update_id sl_btmesh_evt_prov_key_refresh_phase_update_t| |
|gecko_evt_mesh_prov_key_refresh_node_update_id gecko_msg_mesh_prov_key_refresh_node_update_evt_t|sl_btmesh_evt_prov_key_refresh_node_update_id sl_btmesh_evt_prov_key_refresh_node_update_t| |
|gecko_evt_mesh_prov_key_refresh_complete_id gecko_msg_mesh_prov_key_refresh_complete_evt_t|sl_btmesh_evt_prov_key_refresh_complete_id sl_btmesh_evt_prov_key_refresh_complete_t| |
| |sl_btmesh_evt_prov_provisioning_suspended_id sl_btmesh_evt_prov_provisioning_suspended_t|Provisioning suspended, needs user input the configuration data to continue|
| |sl_btmesh_evt_prov_capabilities_id sl_btmesh_evt_prov_capabilities_t| |
| | | |
|CLASS: mesh_proxy|CLASS: mesh_proxy| |
|gecko_evt_mesh_proxy_connected_id gecko_msg_mesh_proxy_connected_evt_t|sl_btmesh_evt_proxy_connected_id sl_btmesh_evt_proxy_connected_t| |
|gecko_evt_mesh_proxy_disconnected_id gecko_msg_mesh_proxy_disconnected_evt_t|sl_btmesh_evt_proxy_disconnected_id sl_btmesh_evt_proxy_disconnected_t| |
|gecko_evt_mesh_proxy_filter_status_id gecko_msg_mesh_proxy_filter_status_evt_t|sl_btmesh_evt_proxy_filter_status_id sl_btmesh_evt_proxy_filter_status_t| |
| | | |
|CLASS: mesh_scene_client|CLASS: mesh_scene_client| |
|gecko_evt_mesh_scene_client_status_id gecko_msg_mesh_scene_client_status_evt_t|sl_btmesh_evt_scene_client_status_id sl_btmesh_evt_scene_client_status_t| |
|gecko_evt_mesh_scene_client_register_status_id gecko_msg_mesh_scene_client_register_status_evt_t|sl_btmesh_evt_scene_client_register_status_id sl_btmesh_evt_scene_client_register_status_t| |
| | | |
|CLASS: mesh_scene_server|CLASS: mesh_scene_server| |
|gecko_evt_mesh_scene_server_get_id gecko_msg_mesh_scene_server_get_evt_t|sl_btmesh_evt_scene_server_get_id sl_btmesh_evt_scene_server_get_t| |
|gecko_evt_mesh_scene_server_register_get_id gecko_msg_mesh_scene_server_register_get_evt_t|sl_btmesh_evt_scene_server_register_get_id sl_btmesh_evt_scene_server_register_get_t| |
|gecko_evt_mesh_scene_server_recall_id gecko_msg_mesh_scene_server_recall_evt_t|sl_btmesh_evt_scene_server_recall_id sl_btmesh_evt_scene_server_recall_t| |
|gecko_evt_mesh_scene_server_publish_id gecko_msg_mesh_scene_server_publish_evt_t|sl_btmesh_evt_scene_server_publish_id sl_btmesh_evt_scene_server_publish_t| |
| | | |
|CLASS: mesh_scene_setup_server|CLASS: mesh_scene_setup_server| |
|gecko_evt_mesh_scene_setup_server_store_id gecko_msg_mesh_scene_setup_server_store_evt_t|sl_btmesh_evt_scene_setup_server_store_id sl_btmesh_evt_scene_setup_server_store_t| |
|gecko_evt_mesh_scene_setup_server_delete_id gecko_msg_mesh_scene_setup_server_delete_evt_t|sl_btmesh_evt_scene_setup_server_delete_id sl_btmesh_evt_scene_setup_server_delete_t| |
|gecko_evt_mesh_scene_setup_server_publish_id gecko_msg_mesh_scene_setup_server_publish_evt_t|sl_btmesh_evt_scene_setup_server_publish_id sl_btmesh_evt_scene_setup_server_publish_t| |
| | | |
|CLASS: mesh_scheduler_client|CLASS: mesh_scheduler_client| |
|gecko_evt_mesh_scheduler_client_status_id gecko_msg_mesh_scheduler_client_status_evt_t|sl_btmesh_evt_scheduler_client_status_id sl_btmesh_evt_scheduler_client_status_t| |
|gecko_evt_mesh_scheduler_client_action_status_id gecko_msg_mesh_scheduler_client_action_status_evt_t|sl_btmesh_evt_scheduler_client_action_status_id sl_btmesh_evt_scheduler_client_action_status_t| |
| | | |
|CLASS: mesh_scheduler_server|CLASS: mesh_scheduler_server| |
|gecko_evt_mesh_scheduler_server_action_changed_id gecko_msg_mesh_scheduler_server_action_changed_evt_t|sl_btmesh_evt_scheduler_server_action_changed_id sl_btmesh_evt_scheduler_server_action_changed_t| |
| | | |
|CLASS: mesh_sensor_client|CLASS: mesh_sensor_client| |
|gecko_evt_mesh_sensor_client_descriptor_status_id gecko_msg_mesh_sensor_client_descriptor_status_evt_t|sl_btmesh_evt_sensor_client_descriptor_status_id sl_btmesh_evt_sensor_client_descriptor_status_t| |
|gecko_evt_mesh_sensor_client_cadence_status_id gecko_msg_mesh_sensor_client_cadence_status_evt_t|sl_btmesh_evt_sensor_client_cadence_status_id sl_btmesh_evt_sensor_client_cadence_status_t| |
|gecko_evt_mesh_sensor_client_settings_status_id gecko_msg_mesh_sensor_client_settings_status_evt_t|sl_btmesh_evt_sensor_client_settings_status_id sl_btmesh_evt_sensor_client_settings_status_t| |
|gecko_evt_mesh_sensor_client_setting_status_id gecko_msg_mesh_sensor_client_setting_status_evt_t|sl_btmesh_evt_sensor_client_setting_status_id sl_btmesh_evt_sensor_client_setting_status_t| |
|gecko_evt_mesh_sensor_client_status_id gecko_msg_mesh_sensor_client_status_evt_t|sl_btmesh_evt_sensor_client_status_id sl_btmesh_evt_sensor_client_status_t| |
|gecko_evt_mesh_sensor_client_column_status_id gecko_msg_mesh_sensor_client_column_status_evt_t|sl_btmesh_evt_sensor_client_column_status_id sl_btmesh_evt_sensor_client_column_status_t| |
|gecko_evt_mesh_sensor_client_series_status_id gecko_msg_mesh_sensor_client_series_status_evt_t|sl_btmesh_evt_sensor_client_series_status_id sl_btmesh_evt_sensor_client_series_status_t| |
|gecko_evt_mesh_sensor_client_publish_id gecko_msg_mesh_sensor_client_publish_evt_t|sl_btmesh_evt_sensor_client_publish_id sl_btmesh_evt_sensor_client_publish_t| |
| | | |
|CLASS: mesh_sensor_server|CLASS: mesh_sensor_server| |
|gecko_evt_mesh_sensor_server_get_request_id gecko_msg_mesh_sensor_server_get_request_evt_t|sl_btmesh_evt_sensor_server_get_request_id sl_btmesh_evt_sensor_server_get_request_t| |
|gecko_evt_mesh_sensor_server_get_column_request_id gecko_msg_mesh_sensor_server_get_column_request_evt_t|sl_btmesh_evt_sensor_server_get_column_request_id sl_btmesh_evt_sensor_server_get_column_request_t| |
|gecko_evt_mesh_sensor_server_get_series_request_id gecko_msg_mesh_sensor_server_get_series_request_evt_t|sl_btmesh_evt_sensor_server_get_series_request_id sl_btmesh_evt_sensor_server_get_series_request_t| |
|gecko_evt_mesh_sensor_server_publish_id gecko_msg_mesh_sensor_server_publish_evt_t|sl_btmesh_evt_sensor_server_publish_id sl_btmesh_evt_sensor_server_publish_t| |
| | | |
|CLASS: mesh_sensor_setup_server|CLASS: mesh_sensor_setup_server| |
|gecko_evt_mesh_sensor_setup_server_get_cadence_request_id gecko_msg_mesh_sensor_setup_server_get_cadence_request_evt_t|sl_btmesh_evt_sensor_setup_server_get_cadence_request_id sl_btmesh_evt_sensor_setup_server_get_cadence_request_t| |
|gecko_evt_mesh_sensor_setup_server_set_cadence_request_id gecko_msg_mesh_sensor_setup_server_set_cadence_request_evt_t|sl_btmesh_evt_sensor_setup_server_set_cadence_request_id sl_btmesh_evt_sensor_setup_server_set_cadence_request_t| |
|gecko_evt_mesh_sensor_setup_server_get_settings_request_id gecko_msg_mesh_sensor_setup_server_get_settings_request_evt_t|sl_btmesh_evt_sensor_setup_server_get_settings_request_id sl_btmesh_evt_sensor_setup_server_get_settings_request_t| |
|gecko_evt_mesh_sensor_setup_server_get_setting_request_id gecko_msg_mesh_sensor_setup_server_get_setting_request_evt_t|sl_btmesh_evt_sensor_setup_server_get_setting_request_id sl_btmesh_evt_sensor_setup_server_get_setting_request_t| |
|gecko_evt_mesh_sensor_setup_server_set_setting_request_id gecko_msg_mesh_sensor_setup_server_set_setting_request_evt_t|sl_btmesh_evt_sensor_setup_server_set_setting_request_id sl_btmesh_evt_sensor_setup_server_set_setting_request_t| |
|gecko_evt_mesh_sensor_setup_server_publish_id gecko_msg_mesh_sensor_setup_server_publish_evt_t|sl_btmesh_evt_sensor_setup_server_publish_id sl_btmesh_evt_sensor_setup_server_publish_t| |
| | | |
|CLASS: mesh_test|CLASS: mesh_test| |
|gecko_evt_mesh_test_local_heartbeat_subscription_complete_id gecko_msg_mesh_test_local_heartbeat_subscription_complete_evt_t|sl_btmesh_evt_test_local_heartbeat_subscription_complete_id sl_btmesh_evt_test_local_heartbeat_subscription_complete_t| |
| | | |
|CLASS: mesh_time_client|CLASS: mesh_time_client| |
|gecko_evt_mesh_time_client_time_status_id gecko_msg_mesh_time_client_time_status_evt_t|sl_btmesh_evt_time_client_time_status_id sl_btmesh_evt_time_client_time_status_t| |
|gecko_evt_mesh_time_client_time_zone_status_id gecko_msg_mesh_time_client_time_zone_status_evt_t|sl_btmesh_evt_time_client_time_zone_status_id sl_btmesh_evt_time_client_time_zone_status_t| |
|gecko_evt_mesh_time_client_tai_utc_delta_status_id gecko_msg_mesh_time_client_tai_utc_delta_status_evt_t|sl_btmesh_evt_time_client_tai_utc_delta_status_id sl_btmesh_evt_time_client_tai_utc_delta_status_t| |
|gecko_evt_mesh_time_client_time_role_status_id gecko_msg_mesh_time_client_time_role_status_evt_t|sl_btmesh_evt_time_client_time_role_status_id sl_btmesh_evt_time_client_time_role_status_t| |
| | | |
|CLASS: mesh_time_server|CLASS: mesh_time_server| |
|gecko_evt_mesh_time_server_time_updated_id gecko_msg_mesh_time_server_time_updated_evt_t|sl_btmesh_evt_time_server_time_updated_id sl_btmesh_evt_time_server_time_updated_t| |
|gecko_evt_mesh_time_server_time_zone_offset_updated_id gecko_msg_mesh_time_server_time_zone_offset_updated_evt_t|sl_btmesh_evt_time_server_time_zone_offset_updated_id sl_btmesh_evt_time_server_time_zone_offset_updated_t| |
|gecko_evt_mesh_time_server_tai_utc_delta_updated_id gecko_msg_mesh_time_server_tai_utc_delta_updated_evt_t|sl_btmesh_evt_time_server_tai_utc_delta_updated_id sl_btmesh_evt_time_server_tai_utc_delta_updated_t| |
|gecko_evt_mesh_time_server_time_role_updated_id gecko_msg_mesh_time_server_time_role_updated_evt_t|sl_btmesh_evt_time_server_time_role_updated_id sl_btmesh_evt_time_server_time_role_updated_t| |
| | | |
|CLASS: mesh_vendor_model|CLASS: mesh_vendor_model| |
|gecko_evt_mesh_vendor_model_receive_id gecko_msg_mesh_vendor_model_receive_evt_t|sl_btmesh_evt_vendor_model_receive_id sl_btmesh_evt_vendor_model_receive_t| |

##### Migration Example

The following code snippets show an example how a Bluetooth Mesh v1.x application is to be updated to work in the Bluetooth Mesh v2.x environment, considering all the changes mentioned above. The sample code simply starts unprovisioned device beacon.

<table>
    <thead>
    </thead>
    <tbody>
        <tr>
            <td>
                <pre><strong>#include</strong> "native_gecko.h"<br>
<strong>void</strong> appMain(gecko_configuration_t* pconfig)
{
  initLog();
  gecko_stack_init(&amp;config);
  gecko_bgapi_classes_init();<br>
  <strong>while</strong> (1)<br> {
    <strong>struct</strong> gecko_cmd_packet* evt;
    evt = gecko_peek_event();<br>
    // Handle stack events
    <strong>switch</strong> (BGLIB_MSG_ID(evt-&gt;header)) {
      <strong>case</strong> gecko_evt_system_boot_id:
        // Initialize Mesh stack in Node operation mode, wait for initialized event
        result = gecko_cmd_mesh_node_init()-&gt;result;
        if (result != bg_err_success) {
          /* handle errors here */
        }
        <strong>break;</strong><br><br>
      <strong>case</strong> gecko_evt_mesh_node_initialized_id:
        if (!evt-&gt;data.evt_mesh_node_initialized.provisioned) {
          gecko_cmd_mesh_node_start_unprov_beaconing(0x3);
        }
        <strong>break;</strong><br>
      <strong>default:</strong>
        <strong>break;</strong>
    }
  }
}
        </pre>
            </td>
            <td>
                <pre><strong>#include</strong> "sl_btmesh_api.h"<br>
<strong>void</strong> sl_btmesh_on_event(sl_bt_msg_t* evt)
{
  sl_status_t sc;
  // Handle stack events
  <strong>switch</strong> (SL_BT_MSG_ID(evt-&gt;header)) {
    <strong>case</strong> sl_bt_evt_system_boot_id:
      sl_app_log("Node init\n");
      sc = sl_btmesh_node_init();
      sl_app_assert(sc == SL_STATUS_OK,
          "[E: 0x%04x] Failed to init node\n",
          (int)sc);
      <strong>break;</strong><br>
    <strong>case</strong> sl_btmesh_evt_node_initialized_id:
      sl_app_log("Initialized\n");
      sc = sl_btmesh_node_start_unprov_beaconing(0x3);
      sl_app_assert(sc == SL_STATUS_OK,
          "[E: 0x%04x] Failed to start unprovisioned beaconing\n",
          (int)sc);
      <strong>break;</strong><br>
    <strong>default:</strong>
      <strong>break;</strong>
  }
}
        </pre>
            </td>
        </tr>
    </tbody>
</table>

#### Migrating NCP projects

Migrating an NCP application is usually easy, since the stack and the application are well-separated. While the stack is running on the NCP target, the application is running on the NCP host. Therefore, a stack update usually does not affect the application except that the API changes must be respected.

An SDK update in the NCP use case means that:

1. The NCP target device must be programmed with the **Bluetooth Mesh - NCP Empty** sample app of the new SDK.
2. UART pins must be configured in the sample app.
3. The GATT database must be imported in the sample app.  
   Furthermore,
4. The NCP host device must include the new BGAPI header files, so that it can communicate with the target.
5. Deprecated API calls must be updated, if there are any.

Upgrading the NCP target code from Bluetooth Mesh SDK v1.x to v2.x is easy. A new **Bluetooth Mesh - NCP Empty** project must be generated with Bluetooth Mesh SDK v2.x. The UART pins can be easily configured with the Pin Tool, and the GATT database can be easily imported with the GATT Configurator. Should you use deep sleep mode in the NCP target, you must install the Wake Lock component and configure it. For more information about the NCP mode, see [Using the Silicon Labs v3.x Bluetooth® Stack in Network Co-Processor Mode](/btmesh/11.0.0/bluetooth-network-coprocessor-mode).

The NCP host update involves more changes. After updating the header files, not only the full Bluetooth Mesh API has to be updated but also some BGLIB commands and macros.

An NCP host code using Bluetooth Mesh SDK v1.x must contain the following header files:

- **bg_errorcodes.h**
- **bg_types.h**
- **host_gecko.h**
- **gecko_bglib.h**

and the following source file:

- **gecko_bglib.c**

An NCP host code using Bluetooth Mesh SDK v2.x must contain the following header files:

- **sl_status.h** (in _SDK_DIR/platform/common/inc_)
- **sl_bt_types.h** (in _SDK_DIR/protocol/bluetooth/inc_)
- **sl_bt_api.h** (in _SDK_DIR/protocol/bluetooth/inc_)
- **sl_btmesh_api.h** (in _SDK_DIR/protocol/bluetooth/inc_)
- **sl_bt_ncp_host.h** (in _SDK_DIR/protocol/bluetooth/inc_)

and the following source files:

- **sl_bt_ncp_host_api.c** (in _SDK_DIR/protocol/bluetooth/src_)
- **sl_bt_ncp_host.c** (in _SDK_DIR/protocol/bluetooth/src_)

The new header files use the new nomenclature (commands/events starting with sl_bt_...) even if the underlying BGAPI packet content, which is sent to the target device via UART, may be unchanged in some cases. Therefore NCP host code must be completely updated according the description in [Bluetooth Mesh API](04-bluetooth-mesh-api), using the new BGAPI.

Beside the changes in BGAPI (Bluetooth commands and events), the host API is also changed similarly to the changes in C API. The following table summarizes the changes in the host API:

**Table Changes in the Host API**

|API 1.x|API 2.0|Notes|
|---|---|---|
|BGLIB_DEFINE|SL_BT_API_DEFINE| |
|BGLIB_INITIALIZE|SL_BT_API_INITIALIZE| |
|BGLIB_INITIALIZE_NONBLOCK|SL_BT_API_INITIALIZE_NONBLOCK| |
|struct gecko_cmd_packet|sl_bt_msg_t| |
|BGLIB_MSG_ID|SL_BT_MSG_ID| |
|struct gecko_cmd_packet* **gecko_wait_event**()|sl_status_t **sl_bt_wait_event**(sl_bt_msg_t* evt)|In API 2.0, an event object is copied into the memory provided by application.|
|struct gecko_cmd_packet* **gecko_peek_event**()|sl_status_t **sl_bt_pop_event**(sl_bt_msg_t* evt)| |
|int **gecko_event_pending**()|bool **sl_bt_event_pending**()| |

The NCP host code must be updated according to these changes. For example fetching an event changes from:

```C
struct gecko_cmd_packet *p;
p = gecko_wait_event();
switch (BGLIB_MSG_ID(p->header)) {…}
```

to:

```C
sl_bt_msg_t evt;
sl_bt_msg_t *p = &evt;
sl_bt_wait_event(&evt);
switch (SL_BT_MSG_ID(p->header)) {…}
```

Regarding the software architecture, the **empty host example** created for PCs (in <SDK_DIR>/app/bluetooth/example_host/empty) is updated to align with the new SoC software architecture. While it is not necessary to update the architecture on the NCP host, it is recommended to use this new architecture on newly created NCP host projects, so that it aligns with SoC code.

## Developer's Guide

### Bluetooth Mesh Developers Guide

The Developer's Guide content is organized in the following groups:

- [**Developing and Debugging**](/btmesh/11.0.0/btmesh-developing-debugging-overview): Describes development resources as well as detailed information on a variety of topics.
- [**Bluetooth Mesh Models**](/btmesh/11.0.0/btmesh-models-overview): Provides links to documents regarding Bluetooth Mesh models and demos.
- [**Co-Processors (NCP/RCP)**](/btmesh/11.0.0/bluetooth-coprocessors-overview): Discusses the two co-processor models and how they are used.
- [**Bootloading**](/btmesh/11.0.0/btmesh-bootloading-overview): Includes information on using the Gecko Bootloader with Bluetooth Mesh applications.
- [**Provisioning**](/btmesh/11.0.0/btmesh-provisioning-overview): Provides information remote and certificate-based provisioning.
- [**Performance**](/btmesh/11.0.0/btmesh-performance-overview): Provides performance testing and measurement tools and techniques as well as results.
- [**Non-Volatile Data Storage**](/btmesh/11.0.0/bluetooth-memory-use-overview): Provides background on managing device memory.
- [**Security**](/btmesh/11.0.0/btmesh-security-overview): Describes Silicon Labs security resources and how to manage Bluetooth Mesh security.
- [**Coexistence**](/btmesh/11.0.0/bluetooth-coexistence-overview): Contains background on coexistence issues and strategies for improving performance in the presence of other protocol traffic.
- [**iOS and Android ADK**](/btmesh/11.0.0/btmesh-adk-overview): Provides a link to a document on how to get started with Bluetooth Mesh application development for iOS and Android smart phones and tablets using the Silicon Labs Bluetooth Mesh for iOS and Android Application Development Kit (ADK).

### Developing and Debugging

#### Developing and Debugging Silicon Labs Bluetooth Mesh Applications

These pages provide details on developing and debugging Bluetooth Mesh applications. Content includes:

- [**Bluetooth Mesh C Application Developer's Guide for SDK v2.x and Higher**](/btmesh/11.0.0/btmesh-c-app-developer-guide-for-sdk2-and-higher): Covers Bluetooth Mesh stack architecture, application development flow, use and limitations of the MCU core and peripherals, stack configuration options, and the stack’s resource usage.
- [**GATT Configurator User’s Guide for Bluetooth LE and Bluetooth Mesh**](/btmesh/11.0.0/gatt-configurator-users-guide-ble-btmesh): Describes how to use the Simplicity Studio 5 GATT Configurator, an intuitive interface providing access to all the Profiles, Services, Characteristics, and Descriptors as defined in the Bluetooth specification.
- [**Bluetooth Mesh Stack and Bluetooth Mesh Configurator User's Guide for SDK v2.x and Higher (PDF)**](https://www.silabs.com/documents/public/user-guides/ug472-bluetooth-mesh-v2x-node-configuration-users-guide.pdf): Describes the components, stack, and DCD (Device Composition Data) configuration options for the Bluetooth Mesh SDK.
- [**Bluetooth Mesh Stack and Bluetooth Mesh Configurator User's Guide for SDK v5.0 and Higher**](/btmesh/11.0.0/btmesh-node-configuration-v5x-and-higher): Describes the components, stack, and DCD (Device Composition Data) configuration options for the Bluetooth Mesh SDK.
- [**Using Network Analyzer with Bluetooth Low Energy and Mesh**](/btmesh/11.0.0/network-analyzer-with-ble-btmesh): Describes using Simplicity Studio 5's Network Analyzer to debug Bluetooth Mesh and Low Energy applications. It can be read jointly with [**AN958: Debugging and Programming Interfaces for Customer Designs (PDF)**](https://www.silabs.com/documents/public/application-notes/an958-mcu-stk-wstk-guide.pdf) for more information on using Packet Trace Interface with custom hardware.

##### Development Tools

**Simplicity Studio and the Simplicity IDE**: Simplicity Studio is the unified development environment for all Silicon Labs technologies, SoCs, and modules. It provides you with access to the target device-specific web and SDK resources, software and hardware configuration tools, and an integrated development environment (IDE) featuring industry-standard code editors, compilers, and debuggers. See the silabs.com [Simplicity Studio page](https://www.silabs.com/developers/simplicity-studio) to download the tools and for more information.

**Bluetooth GATT Configurator**: Bluetooth GATT Configurator, installed with Simplicity Studio, is a simple-to-use tool to help build a customized Bluetooth GATT database for Bluetooth projects. See the [Simplicity Studio User's Guide GATT Configurator section](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-developing-with-project-configurator/bluetooth-gatt-configurator) of the Simplicity Studio 5 User's Guide for more information.

**Bluetooth Mesh Configurator**: The Bluetooth Mesh Configurator provides access to a Bluetooth Mesh node's Device Composition Data (DCD). See the [Simplicity Studio User's Guide Bluetooth Mesh Configurator section](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-developing-with-project-configurator/bluetooth-mesh-configurator).

**Network Analyzer**: Simplicity Studio® 5 (SSv5)'s Network Analyzer enables debugging of complex wireless systems. This tool captures a trace of wireless network activity that can be examined in detail live or at a later time. See the [Simplicity Studio User's Guide Network Analyzer section](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-network-analyzer/) of the Simplicity Studio 5 User's Guide for more information.

**Energy Profiler**: Simplicity Studio® 5 (SSv5)'s Energy Profiler enables you to visualize the energy consumption of individual devices, multiple devices on one target system, or a network of interacting wireless devices to analyze and improve the power performance of these systems. Real-time information on current consumption is correlated with the program counter providing advanced energy software monitoring capabilities. It also provides a basic level of integration with the Network Analyzer network analysis tool. See the [Simplicity Studio User's Guide Energy Profiler section](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-energy-profiler/) of the Simplicity Studio 5 User's Guide for more information.

**Simplicity Commander**: Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple Command Line Interface (CLI) that is also scriptable. Simplicity Commander enables customers to complete essential tasks such as configuring and building applications and bootloaders and flashing images to their devices. Simplicity Commander is available through Simplicity Studio or can be downloaded through [system-specific installers](https://www.silabs.com/developers/mcu-programming-options#programming). The [**Simplicity Commander User's Guide**](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) provides more information.

**Silicon Labs Configurator (SLC)**: SLC offers command-line access to application configuration and generation functions. [**Software Project Generation and Configuration with SLC-CLI**](https://docs.silabs.com/d/ss-5-users-guide-tools-slc-cli/0.1/) provides instructions on downloading and using the SLC-CLI tool.

#### Bluetooth Mesh Stack and Bluetooth Mesh Configurator User's Guide for SDK v2.x and Higher (PDF)

- [Bluetooth Mesh Stack and Bluetooth Mesh Configurator User's Guide for SDK v2.x and Higher (PDF)](https://www.silabs.com/documents/public/user-guides/ug472-bluetooth-mesh-v2x-node-configuration-users-guide.pdf)
#### Bluetooth Mesh C Application Developer Guide for SDK v2.x and Higher

##### Silicon Labs Bluetooth® Mesh C Application Developer’s Guide for SDK v2.x and Higher

**NOTE: This section replaces _UG295: Silicon Labs Bluetooth® Mesh C Application Developer’s Guide for SDK v2.x and Higher_ for Simplicity SDK 2024.12.2 and up. Further updates to this application note will be provided here.**

These pages are a C developer’s guide for the Silicon Labs Bluetooth Mesh stack. It covers various aspects of development and is an important reference for anyone developing in C for Wireless Gecko products that are running the Bluetooth stack.

They are a companion to [Silicon Labs Bluetooth C Application Developer's Guide for SDK v10.x](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x/) and contains content specific to mesh application development. The guide covers both Bluetooth Mesh stack architecture, application development flow, use and limitations of the MCU core and peripherals, stack configuration options, and the stack's resource usage. This version applies to the Silicon Labs Bluetooth Mesh SDK version 2.x and higher.

The purpose of the document is to capture and fill in the blanks between the Bluetooth Mesh Stack API reference, Simplicity/Gecko SDK API reference, and Wireless Gecko reference manuals, when developing Bluetooth Mesh applications for the Wireless Geckos. This document exposes details that will help developers make the most out of the available hardware resources.

- [Application Development Flow](02-application-development-flow#application-development-flow) discusses the application development flow.
- [Project Structure](03-project-structure#project-structure) reviews project structure.
- [Bluetooth Mesh Stack Event Handling](04-bluetooth-mesh-stack-event-handling#bluetooth-mesh-stack-event-handling) is an important piece for everyone developing with the Silicon Labs Bluetooth stack, as it explains how the application runs in sync with the stack in an event-based architecture.
- [NVM Layout](05-nvm-layout#nvm-layout) describes memory allocation for Bluetooth LE and mesh.
- [Bluetooth Mesh Features](06-bluetooth-mesh-features#bluetooth-mesh-features) reviews functionality provided by Bluetooth mesh features.
- [Bluetooth Mesh Stacks and Wireless Gecko Configuration and Resources](07-bluetooth-mesh-stacks-and-wireless-gecko-configuration-and-resources#bluetooth-mesh-stacks-and-wireless-gecko-configuration-and-resources) touches on the topics of peripherals and the chipset resources, covers what is reserved for the stack usage, how interrupts should be handled, and the stack’s memory footprint and available memory for the application. It also covers radio TX/RX monitoring.

###### About This Version

The current version of Silicon Labs' Bluetooth Mesh SDK is v{browser-docspace-version}. Currently supported compilers and IDE version are:

- IDE: Simplicity Studio 5.11.2.0 or newer.
- Compiler: IAR v9.40.1 and GCC 12.2.2023.

###### Prerequisites

This document assumes the current version of Silicon Labs’ Bluetooth SDK has been properly installed to the development machine (Windows, macOS, or Linux), and that you are familiar with [Getting Started with Silicon Labs Bluetooth Mesh Development](/btmesh/11.0.0/btmesh-getting-started-overview) and with the SDK’s examples. Also, you should have a basic understanding of Bluetooth technology. For more information, see [Bluetooth LE Fundamentals](https://docs.silabs.com/bluetooth/latest/bluetooth-le-fundamentals).

##### Application Development Flow

The following figure describes the high-level firmware structure. The developer creates an application on top of the stack, which Silicon Labs provides as a precompiled object-file, enabling the Bluetooth Mesh connectivity for the end-device. The application for Bluetooth Mesh has typically been running on bare metal, but starting from Simplicity SDK 2024.12 there has been OS support with selected RTOS examples for FreeRTOS and Micrium OS.

![Firmware Architecture](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image1.png)

The Bluetooth Mesh stack contains the following blocks:

- **Bootloader**: The Gecko Bootloader is not part of the stack but is provided with the Bluetooth SDK. For more information, see [UG266: Silicon Labs Gecko Bootloader  
  User’s Guide for GSDK 3.2 and Lower]([https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)), [Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4), or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher), and [Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps). For information on bootloading in general, see [Bootloader Fundamentals](https://docs.silabs.com/bluetooth/latest/bootloader-fundamentals).
- **Bluetooth stack**: Bluetooth functionality consisting of link layer, generic access profile, security manager, attribute protocol, and generic attribute profile.
- **Bluetooth AppLoader**: An application that starts after the bootloader. It checks if the user application is valid and, if it is, starts the application. If the application image is not valid or DFU mode is requested, AppLoader starts the Bluetooth Low Energy OTA process to try to receive an application image. This requires using the Gecko Bootloader. AppLoader is not generally used with Mesh examples and only supported on Series 1 and 2 devices.
- **Bluetooth Mesh Stack**: The Bluetooth Mesh functionality consisting of the network layer, lower and upper transport layer, and access layer. Models are also provided as part of the stack.

###### Application Build Flow

![Bluetooth Mesh Project Build Flow](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image2.png)

Building a Bluetooth Mesh project starts with selecting the right base project that is to be generated and adding any extra required components. Models and elements can be added to the project using the Bluetooth Mesh Configurator. If the GATT bearer is used, the Bluetooth Mesh services and characteristics can be viewed just like any other GATT services and characteristics in the Bluetooth GATT Configurator. For more information on the Bluetooth GATT Configurator and Bluetooth application development, see [Getting Started with Silicon Labs Bluetooth LE Development](https://docs.silabs.com/bluetooth/latest/bluetooth-getting-started-overview).

Compiling the project generates an object file, which is then linked with the pre-compiled libraries provided in the SDK. The output of the linking is a flash image that can be programmed to the supported Wireless Gecko devices.

###### Bluetooth Mesh API documentation

The Bluetooth Mesh API documentation can be found in HTML format along with all Application Notes and User Guide pdf files on the Simplicity Studio's DOCUMENTATION tab:

![Bluetooth DOCUMENTATION](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image11.png)

The API reference is under `Silicon Labs Bluetooth Mesh API Reference Guide`.

![Bluetooth Mesh API Reference](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image3.png)

###### Bluetooth Mesh Application Build Flow

Following the Simplicity Studio v5 software approach, the Bluetooth Mesh stack is configured using components. Typically, items such as models, stack parameters, and features can be tuned through the SOFTWARE COMPONENTS menu. All component dependencies are handled internally by Simplicity Studio. Components and models can be configured, added, or removed.

![Bluetooth Mesh Configurable Component](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image4.png)

Installing a model is shown in the following figure.

![Bluetooth Mesh Model Installation](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image5.png)

##### Project Structure

This section explains the application project structure and the mandatory and optional resources available in the project.

A Bluetooth Mesh project is a collection of C source and header files that is built using makefiles. The Simplicity Studio 6 installation generates build files and either generates, copies, or links all SDK or component source files, based on the selection made during project creating. After a project is created, the following directories are created:

- The `config` directory: This directory is autogenerated and aggregates the component configuration files. Files are all headers and contain macros that are specific to each component. The UI tools used to generate the GATT database as well as the DCD for Bluetooth Mesh are in this directory.
- The `autogen` directory: This directory aggregates the C code generated by Simplicity Studio and the SDK. It is a mix of header and source files that constitute the skeleton of the project. Silicon Labs recommends that you do not edit the files in this directory, as they will be overwritten the next time files are generated.
- The `simplicity_sdk_<0.0.0>` or `gecko_sdk_<0.0.0>` directory: This directory copies or links to the SDK resources. Only sources that are relevant to your project and how it is configured are copied or linked (Simplicity Studio 6 hides this).
- The `GNU ARM v<0.0.0> – Debug/Release/Default` or `cmake_gcc` directory: This is the build directory when the GCC compiler is used.

Application code is implemented at the root of the project in `app.c/h`, `app_bm/micriumos/freertos.c` and `main.c`. The following table shows the typical layout of a project (Simplicity Studio 6 and Visual Studio Code):

![Bluetooth Mesh Project Directories](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image6.png)
![Bluetooth Mesh Project Directories](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image14.png)

###### Bluetooth Mesh Library Files

###### Gecko SDK (Series 0/1) (heading level 7)

- **binapploader.o**: Binary image of the Bluetooth AppLoader for Series 1, provides the optional Bluetooth LE Over-the-Air (OTA) functionality.
- **binapploader_nvm3.o**: Binary image of the Bluetooth AppLoader for Series 1 with NVM3 support.
- **libbluetooth.a**: Bluetooth stack library.
- **libbluetooth_mesh.a**: This library includes the radio driver layer and the Bluetooth LE stack, with the Bluetooth Mesh stack built on top of it.

###### Simplicity SDK (Series 2/3) (heading level 7)

- **libapploader.a**: Bluetooth AppLoader library for Series 2 devices.
- **libbgcommon.a**: BLE common library to be used by upper BLE components.
- **libble_host/bgapi.a**: BLE host libraries to be used by the Bluetooth stack.
- **libbtmesh_core.a**: Bluetooth Mesh core library.

###### Both (heading level 7)

- **libnvm3_CMxx_gcc.a**: NVM3 functionality for Bluetooth LE and Bluetooth Mesh stacks. NVM3 is the unique memory management system used for non-volatile memory. For more information on how to use NVM3, see [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](/btmesh/11.0.0/using-third-generation-nonvolatile-memory).

**RAIL (Radio Application Interface Layer)**: The Bluetooth LE and mesh stacks use RAIL to access the radio. RAIL libraries are linked to the Bluetooth Mesh stack under libbluetooth_mesh.a/libbtmesh_core.a. RAIL has separate libraries for each device family and for single- and multiprotocol environments. RAIL libraries are provided in the Gecko Platform. For more information, refer to [RAIL Fundamentals](https://docs.silabs.com/rail/latest/rail-fundamentals) and other RAIL documentation.

**mbedTLS**: The mbedTLS security library is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems.

Among other header files generated by the SDK, the following defines the APIs for both the Bluetooth Mesh and LE stack. These files serve two purposes: first they contain the actual Bluetooth LE and mesh stack API and the commands and events for the stack, and second they provide configuration, event, and sleep management API to the Bluetooth LE and mesh stack.

**sl_btmesh_api.h**: This file is part of the SDK directory and defines the Bluetooth mesh API available to the user. It contains all routine definitions as well as types, structures and event definitions needed in order to write a Bluetooth Mesh application.

**sl_bt_api.h**: This file is part of the SDK directory and defines the API available to the user. It contains all routine definitions as well as types, structures and event definitions needed in order to write a Bluetooth LE application.

Note that an application may use both APIs if the developer wished to use both Bluetooth LE and mesh in the project.

###### Stack (heading level 7)

The Bluetooth Mesh stack initialization is autogenerated and takes place in `sl_btmesh.c` under the `autogen` directory. Sequentially, in the user application code, a system init function `sl_system_init()` is called in `main.c`. This function is defined in the generated file `sl_system_init.c`. The stack is then initialized from there.

```C
void sl_system_init(void)
{
  sl_platform_init();
  sl_driver_init();
  sl_service_init();
  sl_stack_init();
  sl_internal_app_init();
}
```

The `sl_stack_init()` function initializes the radio transmitter/receiver and makes the call to both the Bluetooth LE and mesh stack initialization functions (`sl_event_handler.c`).

```C
void sl_stack_init(void)
{
  sl_rail_util_pa_init();
  sl_rail_util_power_manager_init();
  sl_rail_util_pti_init();
  sl_bt_init();
  sl_btmesh_init();
}
```

Additionally, the default Bluetooth LE stack configuration structure and macros can be found under the config directory, in the `sl_bluetooth_config.h` file. The content of that file is generated by the SDK via the Bluetooth LE and mesh components. For more information on how to configure the Bluetooth Mesh stack, refer to [Bluetooth® Mesh Stack and Bluetooth® Mesh Configurator User's Guide for SDK v5.0 and Higher](/btmesh/11.0.0/bluetooth-mesh-v5x-node-configuration).

```C
/** @brief Structure that specifies the Bluetooth configuration */
static const sl_bt_configuration_t bt_config = SL_BT_CONFIG_DEFAULT;

// Initialize the Bluetooth stack.
sl_status_t sl_bt_stack_init()
{
  // Initialize the Bluetooth stack with the given configuration, features, and BGAPI classes
  return sli_bt_init_stack(&bt_config, bt_used_features, bt_bgapi_classes);
}
```

The internal function takes a specific argument: a pointer to a `sl_bt_configuration_t` struct. Its purpose is to configure and initialize the Bluetooth stack with the parameters provided in the struct. More information on the `sl_bt_stack_init()` routine is available in the HTML API documentation.

###### Node (heading level 7)

A device configured as a node in a Bluetooth Mesh network is initialized by the `sl_btmesh_node_init()` routine. The call to that function is usually done in the `sl_btmesh_provisionee.c` file, added to the project with the **Btmesh Provisionee** component (or has to be called on the user application level, in case of **Btmesh Custom Role**):

```C
sl_status_t sl_btmesh_node_init();
```

No Bluetooth Mesh API routine can be called before this one. Additionally, the provisioner-initializing routine `sl_btmesh_prov_init()` must not be called on a node. The user is notified with the `sl_btmesh_provisionee_on_init` callback on the application level.

![Btmesh Provisionee](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image12.png)

Each node can be configured in various ways. Some nodes may support a set of models and features that other nodes are not meant to support. This is specific to the user and the network.

In order to make a model or feature functional, make sure the corresponding initialization class routine are called. For example, if a node supports the same generic server and/or client models (On/Off, Level, and so on), follow this procedure.

1. Make sure that the corresponding model components are installed in your project. When a component is installed, a blue check symbols appears in front of it. If the component is configurable, a Configure control (gear symbol) is available next to the component name, and as a button in the top right corner. First to be installed is the Generic Base component.  
   ![Generic Base](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image7.png)
2. Enter the Configuration menu and enable the Generic Server/Client Models as well es the specific model you would like to use. This ensures the proper initialization of the model.  
   ![Bluetooth Mesh Configurator](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image13.png)
3. Then, install the Generic Server Models component.  
   ![Generic Server Models](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image15.png)
4. Make sure the models are properly added to your DCD configuration. If the model is not supported as a component, it has to be manually added to the corresponding element using the Bluetooth Mesh Configurator.  
   ![Bluetooth Mesh Configurator](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image8.png)
5. Make sure the corresponding Bluetooth Mesh classes are properly initialized.

```C
/** @brief Table of used BGAPI classes */
static const struct sli_bgapi_class * const btmesh_class_table[] =
{
  SL_BTMESH_BGAPI_CLASS(health_server),
  SL_BTMESH_BGAPI_CLASS(proxy),
  SL_BTMESH_BGAPI_CLASS(proxy_server),
  SL_BTMESH_BGAPI_CLASS(node),
  NULL
};
```

```C
void sl_btmesh_init(void)
{
  sl_btmesh_init_classes(btmesh_class_table);
  sl_btmesh_generic_base_init();
  mesh_advertiser_legacy();
}
```

> **Note**: This section only describes the common pitfalls that you might encounter when setting up a node using generic client/server as an illustration. It is not an exhaustive list of steps that are necessary to have a generic On/Off or Battery client/server up and running, which would require a much longer description. The components are taking care of this under the hood. These are snippets from the `sl_btmesh_generic_onoff_server.c` file.

In the case of a generic On/Off server model for example, the following steps would need to be implemented on the server:

- Register a generic server handler.

```C
/*******************************************************************************
 * Initialization of the models supported by this node.
 * This function registers callbacks for each of the supported models.
 ******************************************************************************/
static void init_models(void)
{
  generic_server_register_handler(MESH_GENERIC_ON_OFF_SERVER_MODEL_ID,
                                  BTMESH_GENERIC_ONOFF_SERVER_MAIN,
                                  onoff_request,
                                  onoff_change,
                                  onoff_recall);
}
```

- Populate the corresponding request/change/recall functions.

```C
static void onoff_request(uint16_t model_id,
                          uint16_t element_index,
                          uint16_t client_addr,
                          uint16_t server_addr,
                          uint16_t appkey_index,
                          const struct mesh_generic_request *request,
                          uint32_t transition_ms,
                          uint16_t delay_ms,
                          uint8_t request_flags)

static void onoff_change(uint16_t model_id,
                         uint16_t element_index,
                         const struct mesh_generic_state *current,
                         const struct mesh_generic_state *target,
                         uint32_t remaining_ms)

static void onoff_recall(uint16_t model_id,
                         uint16_t element_index,
                         const struct mesh_generic_state *current,
                         const struct mesh_generic_state *target,
                         uint32_t transition_ms)
```

Note that this is only an example based on the generic On/Off model. It is commonly more difficult to start from scratch with generic models as it would require a very good understanding of both the Bluetooth Mesh technology and the stack.

To set up a working node configured as a light client/server model, Silicon Labs recommends using the sample application in Simplicity Studio. For more information, refer to [Understanding the Silicon Labs Bluetooth® Mesh SDK v6.x or Higher Lighting Demonstration](/btmesh/11.0.0/btmesh-sdk6-or-higher-lighting-demo).

###### Provisioner (heading level 7)

To configure a device as a provisioner, first install the **Provisioner** and **Btmesh Provisioner** components.

A provisioner must support the Configuration Client model. As a result the corresponding model should be added in the Bluetooth Mesh Configurator as well as the **Configuration Client** component has to be installed. Check that the Configuration Client model is part of the Bluetooth Mesh init class table, generated by the SDK, in the `sl_btmesh.c` file:

```C
/** @brief Table of used BGAPI classes */
static const struct sli_bgapi_class * const btmesh_class_table[] =
{
  SL_BTMESH_BGAPI_CLASS(config_client),
  SL_BTMESH_BGAPI_CLASS(health_server),
  SL_BTMESH_BGAPI_CLASS(prov),
  SL_BTMESH_BGAPI_CLASS(proxy),
  SL_BTMESH_BGAPI_CLASS(proxy_server),
  SL_BTMESH_BGAPI_CLASS(node),
  NULL
};
```

This should also now be visible in the Bluetooth Mesh Configurator user interface.

Additionally, configure the **Bluetooth Mesh Stack** component so that the following parameters are set to values corresponding to your network:

- Maximum number of provisioned devices allowed
- Maximum number of Application Keys allowed for each Provisioned Device
- Maximum number of Network Keys allowed for each Provisioned Device
- Maximum number of Client Commands for the Foundation Model

These four are required for successful provisioning in any network size, and may be enough for a very small network consisting of one or two nodes. In more complicated networks, provisioner configuration depends on many other parameters. For more information on Bluetooth Mesh stack parameters, refer to [UG472: Bluetooth® Mesh Stack and Bluetooth® Mesh Configurator User's Guide for SDK v2.x and Higher](https://www.silabs.com/documents/public/user-guides/ug472-bluetooth-mesh-v2x-node-configuration-users-guide.pdf).

The following table shows an example. Note that the parameters are set to 4 as an example, not as a recommendation.

![Bluetooth Mesh Stack Component - Provisioner Settings](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image9.png)

The Provisioner is initialized using the following routine. The call to that function is usually done in the `sl_btmesh_provisioner.c` file, added to the project with the **Btmesh Provisioner** component (or has to be called on the user application level, in case of **Btmesh Custom Role**):

```C
sl_status_t sl_btmesh_prov_init();
```

No Bluetooth Mesh API routine can be called before this one. Additionally, the node-initializing routine `sl_btmesh_node_init()` must not be called on a provisioner. The user is notified with the `sl_btmesh_provisioner_on_init` callback on the application level.

###### Custom Role (heading level 7)

For more customized projects and ones with both roles, the **Btmesh Custom Role** component is provided. This component makes it possible to initialize a mesh device as a provisionee or provisioner based on application logic. For example an application could be implemented in a way that the device becomes a provisioner permanently when button is pressed at power up, otherwise it is just a provisionee. The `sl_btmesh_custom_role_init` weak callback function is called on boot event and the application is able to override this function to call one of the following initializer BT Mesh stack APIs:

- sl_btmesh_node_init()
- sl_btmesh_node_init_oob()
- sl_btmesh_prov_init()

###### GATT Database (heading level 7)

The GATT (Generic Attribute Profile) database is a standardized way of describing a Bluetooth device’s profiles, services, and characteristics. With the Silicon Labs Bluetooth stack, the GATT definitions are either directly edited in the Bluetooth GATT Configurator in Simplicity Studio or are written in XML. For more information on how to create GATT databases and the syntax, refer to the [Bluetooth Profile Toolkit Developer's Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-profile-toolkit-developers-guide).

**gatt_db.c and gatt_db.h**

The `gatt_db.c` file defines the GATT database structure and content. It is autogenerated by the Bluetooth GATT Configurator. `gatt_db.h` includes this database and the handles of local characteristics and services. Type definitions of GATT are automatically included from `gatt_db_def.h` to `gatt_db.h`. In the case of Bluetooth Mesh, only the Bluetooth Mesh services are relevant:

- Mesh Proxy Service (UUID 0x1828): The Bluetooth Mesh Proxy Service is used to enable a server to send and receive Proxy PDUs with a proxy client.  
  - Mesh Proxy Data In (UUID 0x2ADD)  
  - Mesh Proxy Data Out (UUID 0x2ADE)
- Mesh Provisioning Service (UUID 0x1827): The Bluetooth Mesh Provisioning Service allows a Provisioning Client to provision a Provisioning Server to allow it to participate in the Bluetooth Mesh network.  
  - Mesh Provisioning Data In (UUID 0x2ADB)  
  - Mesh Provisioning Data Out (UUID 0x2ADC)

Those services and characteristics can be thought of as duplex communication channels for provisioning and proxy PDUs. The "data in" and "out" characteristics are then the Tx and Rx channel, respectively.

A device may support the Bluetooth Mesh Provisioning Service or the Mesh Proxy Service or both. If both are supported, only one of these services should be exposed in the GATT database at a time.

###### Bluetooth Mesh Device Composition Data (heading level 7)

The device composition data, or DCD, is a set of data indicating which features are supported, how many elements are present on a node with their description, and a set of identifiers defining the model layout across the elements of the node.

The Composition Data state contains information about a node, the elements it includes, and the supported models. The Composition Data is composed of a number of pages of information. Composition Data Page 0 is mandatory. All other pages are optional. All Composition Data Pages not defined in this specification are reserved for future use. The size of the state must not exceed the maximum useful access payload size.

The following code snippet illustrate how this is defined for the Bluetooth Mesh stack:

```C
const uint8_t __mesh_dcd[] = {
  U16TOA(0x02FF), /* Company ID */
  U16TOA(0x0001), /* Product ID */
  U16TOA(0x0902), /* Version Number */
  U16TOA(SL_BTMESH_CONFIG_RPL_SIZE), /* Capacity of Replay Protection List */
  U16TOA(SL_BTMESH_FEATURE_BITMASK), /* Features Bitmask */
  /* Main */
    U16TOA(0x0000), /* Location */
    0x03, /* Number of SIG Models = 3 */
    0x00, /* Number of Vendor Models = 0 */
    /* SIG Models */
      U16TOA(0x0000), /* Configuration Server */
      U16TOA(0x0002), /* Health Server */
      U16TOA(0x0001), /* Configuration Client */
};

const size_t __mesh_dcd_len = sizeof(__mesh_dcd);
const uint8_t *__mesh_dcd_ptr = __mesh_dcd;
```

The structure called __mesh_dcd is passed via a pointer to the C Bluetooth Mesh library.

After provisioning, the Provisioner typically retrieves the DCD of the newly provisioned node in order to determine the node’s features and functionalities so that it can be configured to operate in the network.

###### RTOS Support (heading level 7)

Typical Bluetooth Mesh examples have been running on bare metal. RTOS support has been available for the Bluetooth Mesh starting from Simplicity SDK 2024.12. There are selected examples also running on FreeRTOS and Micrium OS.

Note that multiprotocol applications are not supported by the Bluetooth Mesh protocol.

##### Bluetooth Mesh Stack Event Handling

The Bluetooth Mesh Stack for the Wireless Geckos is an event-driven architecture, where events are handled in the main while loop. The Bluetooth Mesh Stack runs on top of the Silicon Labs Bluetooth Stack.

###### Bluetooth LE versus Bluetooth Mesh Event

The Bluetooth Mesh protocol is built on top of Bluetooth Low Energy. This means that a device running a Bluetooth LE Stack will be able to receive a Bluetooth Mesh PDU but will not be able to interpret the data that it contains. Nevertheless, a node or device can run both. In effect, it is possible to have Bluetooth LE and Bluetooth Mesh events treated separately in an application.

In this particular case, Bluetooth LE and Bluetooth Mesh event application state machines need to be separate. In other words, the Bluetooth LE and Bluetooth Mesh events cannot be treated in a unique switch-case statement.

At the application level, the Silicon Labs Bluetooth Mesh API provides a way to differentiate Bluetooth Mesh events from Bluetooth LE events. This is done through the Bluetooth Mesh listener.

The Bluetooth Mesh events in the stack are handled similarly to the regular Bluetooth LE events. In a freshly created project, the Bluetooth Mesh switch case statement is performed by the routine `sl_btmesh_step()` and the `sl_btmesh_pop_event(&evt)` - `sl_btmesh_process_event(&evt)` combo within it.

- Application level event-handler for the Bluetooth LE Stack

```C
void sl_bt_on_event(struct sl_bt_msg *evt)
{
  switch (SL_BT_MSG_ID(evt->header)) {
    ///////////////////////////////////////////////////////////////////////////
    // Add additional event handlers here as your application requires!      //
    ///////////////////////////////////////////////////////////////////////////

    // -------------------------------
    // Default event handler.
    default:
      break;
  }
}
```

- Application level event-handler for the Bluetooth Mesh Stack

```C
void sl_btmesh_on_event(sl_btmesh_msg_t *evt)
{
  switch (SL_BT_MSG_ID(evt->header)) {
    ///////////////////////////////////////////////////////////////////////////
    // Add additional event handlers here as your application requires!      //
    ///////////////////////////////////////////////////////////////////////////

    // -------------------------------
    // Default event handler.
    default:
      break;
  }
}
```

For more information on how events are processed in the Bluetooth LE Stack, refer to the [Bluetooth Stack Event Handling](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x/05-bluetooth-stack-event-handling).

##### NVM Layout

The Non-Volatile Memory management system, called Non-Volatile Memory 3 (NVM3), is a data storage driver for storing persistent data primarily -but not only- in internal flash. The term "non-volatile" and "NVM3" are synonymous in this section.

[Using Third Generation Non-Volatile Memory (NVM3) Data Storage](/btmesh/11.0.0/using-third-generation-nonvolatile-memory) describes in detail how NVM3 operates. The NVM3 subsystem allocates a certain range of address to both the user, the Bluetooth LE and Bluetooth Mesh Stacks, among other things. The following table shows what key ranges are dedicated to the stack and the user:

|Domain|NVM3 Key Range|
|---|---|
|User|0x00000 - 0x0FFFF|
|Bluetooth stack|0x40000 - 0x4FFFF|

The Bluetooth stack key range is shared between regular Bluetooth Low Energy and Bluetooth Mesh. Within this key range, the distribution is laid out as follow:

|Domain|NVM3 Key Range|
|---|---|
|Bluetooth internal stack data (bonding, etc.)|0x40000 - 0x40FFF|
|Bluetooth mesh stack data|0x41000 - 0x44000|
|Reserved for future use|0x48000 - 0x4FFFF|

There are some user-configurable special keys within the Mesh Stack range. Change these carefully, to avoid any possible address conflicts.

|Name|Variable|Address|
|---|---|---|
|NVM key of the IV Update age|SL_BTMESH_IV_UPDATE_AGE_NVM_KEY_CFG_VAL|0x3000|

##### Bluetooth Mesh Features

Optional networking or energy features may also be implemented in a Bluetooth Mesh application. The Bluetooth Mesh profile specification refers to those simply as features. There are four Bluetooth Mesh features: Proxy, Relay, Friends, and Low Power nodes. This section describes all four.

> **Note**: These features are specific to nodes, that is, devices in a Bluetooth Mesh network. The provisioner of a network is not subject to features support.

###### Proxy

The Proxy feature allows a node to receive and transmit Bluetooth Mesh messages between GATT and advertising bearers. The proxy feature is used to forward Network packets received by a node between GATT bearer and advertising bearers. This feature is optional and can be enabled/disabled at runtime. When this feature is enabled, the corresponding GATT Proxy service must be exposed.

The proxy feature defines two roles, the proxy client and the server. The proxy server is a node that supports both the GATT bearer and the advertising bearer. In practice, the proxy client is a node that supports only the GATT bearer.

For a proxy feature to run, the corresponding proxy routine class must be part of the stack initialization table. The following code snippet gives a proxy server example.

```C
static const struct sli_bgapi_class * const btmesh_class_table[] =
{
  SL_BTMESH_BGAPI_CLASS(health_server),
  SL_BTMESH_BGAPI_CLASS(proxy),
  SL_BTMESH_BGAPI_CLASS(proxy_server),
  SL_BTMESH_BGAPI_CLASS(node),
  NULL
};
```

###### Relay

The Relay feature allows a node to receive and retransmit Bluetooth Mesh messages over the advertising bearer to enable larger networks.

The provisioner can enable the relay feature on a particular node (if supported) via the following routine:

```C
sl_status_t sl_btmesh_config_client_set_relay(uint16_t enc_netkey_index,
                                              uint16_t server_address,
                                              uint8_t value,
                                              uint8_t retransmit_count,
                                              uint16_t retransmit_interval_ms,
                                              uint32_t *handle);
```

A getter function is also available. For more details, refer to the Bluetooth Mesh Configuration Client section of the API HTML documentation.

> **Note**: In large networks, it is in general a good practice to limit the number of nodes supporting the relay feature. Otherwise, the data traffic can increase very rapidly to undesired levels.

###### Friend

The Friend feature allows a node to help a node supporting the Low Power feature to operate by storing messages destined for that node. Friendship is used by Low Power Nodes to limit the amount of time that they need to listen.

The application code for nodes supporting that feature need to enable it using:

- `sl_status_t sl_btmesh_friend_init(void)` for enabling the feature.
- `sl_status_t sl_btmesh_friend_deinit(void)` for disabling the feature.

For more information, refer to the HTML API Reference delivered with the SDK.

###### Low Power Node

The Low Power Node (LPN) feature allows a node to operate within a Bluetooth Mesh network at significantly reduced receiver duty cycles, only in conjunction with a node supporting the Friend feature.

Similarly to the Friend feature, the application code for nodes supporting the Low Power Node feature needs to enable it:

- `sl_status_t sl_btmesh_lpn_init(void)`
- `sl_status_t sl_btmesh_lpn_deinit(void)`

When the feature has been enabled on a node, and if a node offering friendship is within radio range, the friendship can be established and terminated using the following routines with the associated network key index:

- `sl_status_t sl_btmesh_lpn_establish_friendship(uint16_t netkey_index)`
- `sl_status_t sl_btmesh_lpn_terminate_friendship(uint16_t netkey_index)`

The Silicon Labs Bluetooth Mesh API allows the user to configure the time interval at which the LPN will poll the friend as well as other time variables:

- `sl_status_t sl_btmesh_lpn_config(uint8_t setting_id, uint32_t value)`

The following arrays describes the setting id enum used by the stack to aggregates the LPN configuration values `(enum sl_btmesh_lpn_settings_t)`:

|id enum|Value|Description|
|---|---|---|
|`sl_btmesh_lpn_queue_length`|`0x0`|Minimum queue length that the friend must support. Choose an appropriate length based on the expected message frequency and LPN sleep period because messages that do not fit into the friend queue are dropped. Note that the given value is rounded up to the nearest power of 2. Range: 2..128.|
|`sl_btmesh_lpn_poll_timeout`|`0x1`|Poll timeout in milliseconds, which is the longest time that LPN sleeps in between querying its friend for queued messages. Long poll timeout allows the LPN to sleep for longer periods, at the expense of increased latency for receiving messages. Note that the given value is rounded up to the nearest 100 ms Range: 1 s to 95 h 59 min 59 s 900 ms.|
|`sl_btmesh_lpn_receive_delay`|`0x2`|Receive delay in milliseconds. Receive delay is the time between the LPN sending a request and listening for a response. Receive delay allows the friend node time to prepare the message and LPN to sleep. Range: 10 ms to 255 ms The default receive delay in 10 ms.|
|`sl_btmesh_lpn_request_retries`|`0x3`|Request retry is the number of retry attempts to repeat e.g., the friend poll message if the friend update was not received by the LPN. Range is from 0 to 10, default is 3.|
|`sl_btmesh_lpn_retry_interval`|`0x4`|Time interval between retry attempts in milliseconds. Range is 0 to 100 ms.|
|`sl_btmesh_lpn_clock_accuracy`|`0x5`|Clock accuracy in ppm, which will be taken into account when opening and closing the receive window, and determining the poll timeout. Should be used with care, because inaccurate clock can increase the receive window length to up to 2.5 times in some cases. Default value is 0.|

Additionally, a friend poll request can be sent from the LPN at any time using the flowing routine with the appropriate network key index:

`sl_status_t sl_btmesh_lpn_poll(uint16_t netkey_index)`

However, it is not required for correct operation, because the procedure will be performed automatically before the poll timeout expires.

For more information on the friend and LPN API, refer to the HTML API documentation.

###### Bitmask

From a practical standpoint, the device composition data of each node contains a 2-byte field indicating the supported features. The following array illustrates the features field:

|Bit|Feature|Notes|
|---|---|---|
|0|Relay|Relay feature supported if set to 1. 0 otherwise.|
|1|Proxy|Proxy feature supported if set to 1. 0 otherwise.|
|2|Friend|Friend feature supported if set to 1. 0 otherwise.|
|3|Low Power Node (LPN)|LPN feature supported if set to 1. 0 otherwise.|
|4 - 15|Reserved for future use.|Reserved for future use.|

As mentioned in section [Bluetooth Mesh Device Composition Data](03-project-structure#bluetooth-mesh-device-composition-data), each node, after provisioning, sends its composition data page 0 to the provisioner. In the code example presented in that section, the macro SL_BTMESH_FEATURE_BITMASK is used with the default value of 3:

**sl_btmesh_dcd.c**

```C
const uint8_t __mesh_dcd[] = {
  U16TOA(0x02FF), /* Company ID */
  U16TOA(0x0001), /* Product ID */
  U16TOA(0x0700), /* Version Number */
  U16TOA(SL_BTMESH_CONFIG_RPL_SIZE), /* Capacity of Replay Protection List */
  U16TOA(SL_BTMESH_FEATURE_BITMASK), /* Features Bitmask */
  /* Main */
    U16TOA(0x0000), /* Location */
    0x02, /* Number of SIG Models = 2 */
    0x00, /* Number of Vendor Models = 0 */
    /* SIG Models */
      U16TOA(0x0000), /* Configuration Server */
      U16TOA(0x0002), /* Health Server */
};
```

**sl_btmesh_.h**

`#define SL_BTMESH_FEATURE_BITMASK 3`

In this example, that macro enables the relay and proxy features (3) in the Bluetooth Mesh stack. This is the default setting.

##### Bluetooth Mesh Stacks and Wireless Gecko Configuration and Resources

To run the Bluetooth stack and an application on a Wireless Gecko, the MCU and its peripherals have to be properly configured. Once the hardware is initialized, the stack also has to be initialized using the `sl_btmesh_init()` function as described in section [Stack](03-project-structure#stack). This process is automated by the SDK.

**sl_system_init()**

The `sl_system_init()` function is used to initialize the system. It will call platform, driver, service, stack, and internal app init functions, located in the autogen folder.

**app_init()**

This function is used to initialize application-specific features.

###### Wireless Gecko MCU and Peripherals Configuration

If the specific configuration is supported under Bluetooth Mesh, its detailed explanation can be found in the _Wireless Gecko MCU and Peripherals Configuration_ section of [Configuring the Bluetooth Stack and a Wireless Gecko Device](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x/04-configuring-bluetooth-stack-and-wireless-gecko-device#wireless-gecko-mcu-and-peripherals-configuration).

|Configuration|Bluetooth Mesh|
|---|---|
|Adaptive Frequency Hopping|Not supported when using the advertising bearer, as all data traffic uses the primary advertising channels. If the GATT bearer is used, Bluetooth mesh data are sent and received via the Proxy protocol, which uses a Bluetooth Low Energy connection with dedicated Bluetooth mesh services.|
|Bluetooth Clocks|Supported.|
|DC-DC Configuration|Supported.|
|LNA|Supported.|
|Periodic Advertising|Not supported. Legacy advertising (31 bytes long) only, as per the profile specification.|
|PTI|Supported.|
|Transmit Power|Supported.|
|Filter Accept List|Supported.|
|Wi-Fi Coexistence|Supported.|
|OTA Configuration|Supported using Bluetooth LE services.|
|Even Connection Distribution Algorithm|Not supported.|
|Interrupts|Supported|

###### Wireless Gecko Resources

The Bluetooth mesh stack uses some of the Wireless Gecko’s resources, which are not available to the application. The following table lists the resources and describes their use by the stack. The first four resources are always used by the Bluetooth stack.

|Category|Resource|Used in software|Notes|
|---|---|---|---|
|PRS|PRS7|PROTIMER RTC synchronization|PRS7 always used by the Bluetooth stack.|
|Timers|RTCC|EM2|The sleep timer uses RTCC in the default configuration.|
|“|PROTIMER|Bluetooth (LE and mesh)|The application does not have access to PROTIMER.|
|Radio|RADIO|Bluetooth|Always used and all radio registers are reserved for the Bluetooth LE and mesh stack.|
|GPIO|NCP|Host communication|Up to 4 I/O pin. Optional.|
|“|PTI|Packet trace|2 to N I/O pins. Optional.|
|“|TX ACTIVE|TX activity indication|1 I/O pin. Optional.|
|“|RX ACTIVE|RX activity indication|1 I/O pin. Optional.|
|“|COEX PTA|Wi-Fi Coexistence|Up to 4 I/O pins. Optional.|
|CRC|GPCRC|NVM3|Can be used in application, but application should always reconfigure GPCRC before use, and GPCRC clock must not be disabled in CMU.|
|Flash|MSC|NVM3|Can be used by the application.|
|Crypto|CRYPTO|Bluetooth Link encryption|The CRYPTO peripheral can only be accessed through the mbedTLS crypto library, not through any other means. The library should be able to do the scheduling between the stack and application access.|
|“|RADIO AES|Bluetooth Link encryption|The application does not have access to RADIOAES|

###### Internal Flash and SRAM (heading level 7)

For more information, refer to the Wireless Gecko Resources section in [Silicon Labs Bluetooth C Application Developer's Guide for SDK v10.x](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x).

###### Monitoring Radio RX and TX State Using PRS (Peripheral Reflex System) (heading level 7)

It is sometimes useful, for debugging purposes, to monitor the state of the radio transmitter/receiver. This can be done by outputting on pins the RX_ACTIVE and TX_ACTIVE signals. An example is provided here on how to do that on Series 2 devices (EFR32xG24-based Wireless Gecko starter kit).

First, make sure the **Platform → Peripheral → EMLIB → PRS** component is installed in the project. Then the following configuration example indicates how PRS can be used to output the RX_ACTIVE and TX_ACTIVE signals.

- Install two instances of the **RAIL-SDK → Utility → PRS Debug Signal Support** component:

![PRS Debug Signal Support](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image16.png)

- Configure both of them:  
  - Note: As indicated in the table in section [Wireless Gecko Resources](#wireless-gecko-resources), PRS channel 7 is used by the Bluetooth LE stack and cannot be used in this example.

![TX_ACTIVE](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image17.png)
![RX_ACTIVE](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image18.png)

These configurations define which PRS signals coming from the radio source should be used. Those signals will then be routed to the desired pins, in this case PC05 (EXP PIN15) for the TX_ACTIVE signal and PC07 (EXP PIN16) for the RX_ACTIVE signal.
Then the following function sets up the pins and configure the PRS module (generated automatically in `autogen/sl_radioprs_init_instances.c`):

```C
void sl_radioprs_init_instances(void)
{
  sl_status_t clock_status = SL_STATUS_OK;

  clock_status = sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_PRS);
  if (clock_status != SL_STATUS_OK){
#ifdef SL_CATALOG_APP_LOG_PRESENT
    app_log_warning("Clock manager returned with error code: %lu\n", clock_status);
#endif
    return;
  }

  clock_status = sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
  if (clock_status != SL_STATUS_OK){
#ifdef SL_CATALOG_APP_LOG_PRESENT
    app_log_warning("Clock manager returned with error code: %lu\n", clock_status);
#endif
    return;
  }

  // radioprs instance(s) init(s) 
  
  //begin radioprs_init_rx_active();
  PRS_ConnectSignal(RADIOPRS_RX_ACTIVE_CHANNEL, prsTypeAsync, RADIOPRS_RX_ACTIVE_SOURCESEL);
  PRS_PinOutput(RADIOPRS_RX_ACTIVE_CHANNEL, prsTypeAsync, RADIOPRS_RX_ACTIVE_PORT, RADIOPRS_RX_ACTIVE_PIN);
  GPIO_PinModeSet(RADIOPRS_RX_ACTIVE_PORT, RADIOPRS_RX_ACTIVE_PIN, gpioModePushPullAlternate, 0);
  //end radioprs_init_rx_active();
  
  //begin radioprs_init_tx_active();
  PRS_ConnectSignal(RADIOPRS_TX_ACTIVE_CHANNEL, prsTypeAsync, RADIOPRS_TX_ACTIVE_SOURCESEL);
  PRS_PinOutput(RADIOPRS_TX_ACTIVE_CHANNEL, prsTypeAsync, RADIOPRS_TX_ACTIVE_PORT, RADIOPRS_TX_ACTIVE_PIN);
  GPIO_PinModeSet(RADIOPRS_TX_ACTIVE_PORT, RADIOPRS_TX_ACTIVE_PIN, gpioModePushPullAlternate, 0);
  //end radioprs_init_tx_active();
  
}
```

The radio state can then be monitored using the defined pins on a logic analyzer or oscilloscope. In this example, the radio is running a simple Bluetooth Mesh SoC Empty example, waiting to be provisioned. On each of the three primary advertising channels, data is first transmitted (Channel 1 - long logic high) then the radio switches to the receive state (Channel 2 - short logic high), which is repeated on each channel.

![Radio State Monitored](/btmesh-c-app-developer-guide-for-sdk2-and-higher/10.0.0/images/sld599-image10.png)

#### GATT Configurator User's Guide for Bluetooth LE and Bluetooth Mesh

##### GATT Configurator User’s Guide for Bluetooth LE and Bluetooth Mesh

> **Note: This section replaces _UG438: GATT Configurator User’s Guide for Bluetooth LE and Bluetooth Mesh_. Further updates to this user guide will be provided here**.

This guide provides the information needed to effectively use the Bluetooth GATT Configurator provided as a part of Simplicity Studio® 5 with Bluetooth SDK 3.x and Bluetooth Mesh SDK 2.x. The GATT Configurator is an intuitive interface providing access to all the Profiles, Services, Characteristics, and Descriptors as defined in the Bluetooth specification. It also supports creating, importing, or exporting custom GATT profiles for Bluetooth applications. This guide reviews the user interface and covers some of the most common uses of the Configurator, and the usage of the Dynamic GATT Configurator.

##### GATT Configurator Overview

The GATT Configurator is a simple-to-use tool to help you build your own GATT database. A list of project Profiles/Services/Characteristics/Descriptors is shown on the left and details about the selected item is shown on the right.

The GATT Configurator is composed of a Custom GATT editor on the left, showing a list of project Profiles/Services/Characteristics/Descriptors, and a Settings editor on the right. A SIG selector allows you to add standard elements to the profile.

An options menu is provided at the top of the Custom GATT editor.

The Custom GATT editor is always visible, and the Settings editor opens by default.

![GATT Configurator with Settings Editor](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image1.png)

The GATT Configurator menu is:

![screenshot](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image2.png)

From left the right, the buttons are for the following:

1. Add an item.
2. Duplicate the selected item.
3. Move the selected item up.
4. Move the selected item down.
5. Import a GATT database.
6. Add Predefined (opens the SIG editor).
7. Delete the selected item.

Click Add Predefined to open the SIG selector.

![GATT Configurator with SIG Selector](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image3.png)

###### SIG Selector

The SIG Selector displays a list of predefined Profiles, Services, Characteristics, and Descriptors. These items can be filtered, using the filter pane. Tabs allow you to switch between different lists. As shown in the following figure, the pane on the right side of the list displays textual information about the latest selection. To add an item to the Custom GATT editor, mouse over it and click + on the right. The item can then be edited in the Settings Section. The selected SIG service/characteristic/descriptor will be added under the highlighted profile/service/characteristic. Click **< BACK** to return to the Setting Editor.

![SIG Selector](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image4.png)

###### Custom GATT Editor

The Custom GATT Editor displays the items present in the current configuration file. This includes a Custom GATT Profile, Services, Characteristics, and Descriptors displayed as a hierarchical list. The order of items shown reflects the order in which they exist in the GATT database. When the Settings Editor is open, select an item to see its properties and configuration.

![GATT Custom GATT Editor with Characteristic Selected](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image5.png)

The * next to the configuration file name indicates unsaved changes in the configuration.

> **Note**: The Generic Attribute Service is not listed in the Custom GATT database structure (on the left in the previous figure). This is a special service that is maintained by the stack, and can be added by enabling the **Generic Attribute Service** slider in the settings of the Custom BLE GATT profile. Once enabled, the service will be part of the database. It still will not appear in the Custom GATT database structure, nor on iOS devices as iOS hides this service, but you may see it on Android devices, for example.

![Generic Attribute Service Enabled](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image6.png)

###### Contributed Items (heading level 7)

Some services are listed in the configurator as “contributed items”. This means that their content is defined in other components, and they cannot be edited from this view.

###### Settings Section

The Settings editor allows you to configure the properties of items such as Profiles, Services, Characteristics and Descriptors that are present in the Custom GATT editor. Selecting an item populates the relevant configuration options such as the name, ID, properties and capabilities. Any changes made in this section reflect immediately for the selected item. You can minimize the Custom GATT editor while editing if you want. All Characteristics for a Service are included in the same Settings editor pane.

![Settings Editor](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image7.png)

###### Generating the GATT Database

Database generation happens automatically when the configuration is saved. The generated source files can be found in the directory named “autogen”.

![Generated Files](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image8.png)

##### Use Cases

This chapter describes common tasks performed with the GATT Configurator.

###### Drag and Drop

To include predefined items from the source list in your application, drag and drop the item from the Source Section to the Custom GATT section. When you drag and drop a profile or a service, all the Characteristics and Descriptors in the levels underneath get included automatically. Maintaining the hierarchical structure, Descriptors can only be included under Characteristics, which go under Services.

![Drag and Drop a Service to Include all the Items](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image9.png)

Within the Custom GATT section, drag and drop can be used to reorder items. This saves the trouble of including and configuring the item again. Similarly, an item can be duplicated and moved around in the section.

###### Create New Item

Use the Add an item (1) menu option to add a new item in the Custom GATT editor. If the profile is selected, a new Service will be created. If a Service is selected, a new Characteristics is created under the selected item. Descriptors can only be created when you have selected a Characteristic.

When a new item is selected, the Settings section displays the default properties of the item. Here the item can be configured as per the requirements.

![Default Values for a Newly Created Characteristic](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image10.png)

The application gets local access to the GATT database using the characteristic ID. You can enter this by selecting the checkbox and entering a unique ID.

![Characteristic ID Enabled](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image11.png)

Upon generation, this ID gets a macro in the `gatt_db.h` file as shown below.

```C
extern const struct bg_gattdb_def bg_gattdb_data;
#define gattdb_service_changed_char             3
#define gattdb_device_name                      7
#define gattdb_ota_control                     21
#define gattdb_custom_characteristic           24
```

UUID or Universally Unique identifier are numbers used to identify Services, Characteristics, and Descriptors uniquely. There are two types of UUID:

1. **16 bit**: These 16-bit UUIDs are predefined by the Bluetooth SIG. Being short they are energy and memory efficient. For example, the Blood Pressure Service has a UUID of 0x1810 whereas the Battery level Characteristic has a UUID of 0x2A19.
2. **128 bit**: This overcomes the limitation of running out of 16-bit UUIDs and gives the power to declare your own UUIDs for Custom Services and Characteristics. These randomly generated UUIDs in the GATT Configurator are of version 4 (random) variant 1. You can use any UUID for a custom Service or Characteristic if it does not overlap with Bluetooth base UUID: xxxxxxxx-0000-1000-8000-00805F9B34FB.

While there is no central authority ensuring other devices don’t use the same UUID, there is very little chance (1 in 340 undecillion) that two devices end up with the same UUID.

###### Adding Permissions

Permissions define what actions can be performed for a given Characteristic or Descriptor. For example, in the Blood Pressure Profile, the Blood Pressure Feature has a Mandatory Read property. For more information about access types and security requirements see the Properties section of [Blue Gecko Bluetooth Profile Toolkit Developer's Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-profile-toolkit-developers-guide/).

First the required access types can be enabled with the sliders, and then the security requirements can be selected with the checkboxes.

![Setting Permission for a Characteristic or Descriptor](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image12.png)

> **Note**: The _notify_ and _indicate_ attribute is stored in the SIG defined Client Characteristic Configuration Descriptor (a descriptor with the UUID 0x2902, which will be autogenerated when notifications are enabled). If you manually add a CCCD to the characteristic, the descriptor’s value will overwrite this setting. A warning will be displayed on the UI for this case.

###### Adding Capabilities

Bluetooth SDK 2.4 introduced a new feature called Polymorphic GATT that can be used to dynamically show or hide GATT Services and Characteristics. The GATT Configurator implements this feature using GATT capabilities. This section describes how to do it.

To summarize how capabilities work, each Service/Characteristic can declare several capabilities and the state of the capabilities (enable/disable) determines the visibility of those Services/Characteristics as a bit-wise OR operation. For example, the Service/Characteristic is visible when at least one of its capabilities is enabled and it is not visible when all its capabilities are disabled.

Always start by declaring the GATT-level capabilities and defining their default value. Select the Custom BLE GATT profile, and click the **+** control in the **Capability declarations** table. After adding a capability, you can change the name and default value. For example, Appearance, Temperature_Measure and Tx_power are added to the profile as shown in the following figure.

![Declaring GATT-level Capabilities](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image6.png)

Once those capabilities are added, they become available on each of the services and characteristics. They can be declared from the dropdown list in the **Characteristic capabilities** section.

On the Service and Characteristic level declared capabilities count as enabled, and the ones which were not selected are disabled.

![Including GATT-level Capabilities in a Characteristic](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image13.png)

> **Note**: The capabilities state should not be changed during a connection, as that can cause misbehavior. The safest way is to change the capabilities when no devices are connected.

###### Including Services

In a Service definition, you can add one or more references to other services, using the Service includes feature. Include definitions consist of a single attribute (the include declaration) that contains all the details required for the client to reference the included service.

Included services can help avoid duplicating data in a GATT server. If a service will be referenced by other services, you can use this mechanism to save memory and simplify the layout of the GATT server.

Start by declaring an ID for each service that needs to be included. Services without an ID cannot be referenced. This is done by selecting the ID checkbox and providing an identifier text for the Service. Next, select the Service to be referenced from the dropdown list, named “Service includes”.

![Referencing a Service using Service Includes](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image14.png)

###### Import and Export a GATT Database

###### Import (heading level 7)

The Import control in the Custom GATT toolbar allows you to import an existing GATT database, using a .btconf file. Note that this will overwrite the existing GATT data.

![Importing a GATT database](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image15.png)

###### Export (heading level 7)

There is no separate export function. Another project can directly import the GATT database of this project (named gatt_configuration.btconf)

##### Dynamic GATT Configuration

###### Overview

Silicon Labs Bluetooth SDK v3.2 introduced the ability to create the GATT database dynamically with Bluetooth APIs. These dynamically-created GATT attributes can coexist with a static database generated from a GATT XML file. In this case, the attribute table of the static database is placed at the beginning of the database. When new services and characteristics are created dynamically, they are added into the attribute table after the attributes of the static database.

This feature is recommended for NCP projects. With this method, the target application where the GATT database is located does not need to be modified. Therefore, the database can be built from the host side with the APIs. In other cases, the GATT Configurator is the preferred solution.

###### Usage

The “Dynamic GATT Database” feature is not included in projects by default. It needs to be installed from the Software Components tab.

![ the Dynamic GATT Database](/gatt-configurator-users-guide-ble-btmesh/0.1/images/sld713-image16.png)

Operations on the GATT database are done in a “session”. The changes are saved when a session is finished by “committing” the changes. Unsaved changes are invisible to a connected remote GATT client. The modifications only takes effect when the session is finished.

Each added service and characteristic needs to be started with the appropriate API, or they will not be visible to the connected clients. This start and stop mechanism can be used to have a polymorphic GATT database, as the capability feature is not supported in the dynamic GATT databases.

The following code snippet shows how to add the Health Thermometer Service and the Temperature Measurement characteristic dynamically to the database. See the Bluetooth API reference manual section "GATT Database" for more details.

```C
//create a session for the database update
  sl_bt_gattdb_new_session(&session);
  //add the Thermometer service (UUID: 0x1809) to the database, as an advertised primary service
  sl_bt_gattdb_add_service(session, sl_bt_gattdb_primary_service,
                                    SL_BT_GATTDB_ADVERTISED_SERVICE,2,uuid_service, &service);
  //add the Temperature measurement (UUID:0x2A1C) characteristic to the service
  sl_bt_gattdb_add_uuid16_characteristic(session, service, SL_BT_GATTDB_CHARACTERISTIC_INDICATE,
                                         0, 0, uuid_characteristic, sl_bt_gattdb_fixed_length_value,
                                         1, 1, 0, &characteristic);
  //activate the new service
  sl_bt_gattdb_start_service(session, service);
  //activate the new characteristic
  sl_bt_gattdb_start_characteristic(session, characteristic);
  //save changes and close the database editing session
sl_bt_gattdb_commit(session);
```

#### Bluetooth Mesh Stack and Configurator User's Guide For SDK v5.0 and Higher

##### Bluetooth® Mesh Stack and Bluetooth® Mesh Configurator User's Guide for SDK v5.0 and Higher

> **NOTE: This section replaces _UG572: Bluetooth® Mesh Stack and Bluetooth® Mesh Configurator User's Guide for SDK v5.0 and Higher_. Further updates to this user guide will be provided here**.

This user guide describes the components, stack and DCD (Device Composition Data) configuration options for the Bluetooth Mesh SDK.

###### Key Points

- Introduction to Simplicity Studio 5 Bluetooth Mesh components.
- Modifying the Device Composition Data, including device information, elements, and models.
- Setting stack configuration options to optimize the RAM and persistent storage usage.

##### Introduction

A new way of configuring the Bluetooth Mesh stack, namely through components and the Bluetooth Mesh Configurator tool, was introduced beginning with Bluetooth Mesh SDK v2.0 and Simplicity Studio 5.

###### Terminology

The following table gathers the Bluetooth mesh-specific terms in use in this document. Those terms are defined in the [SIG Bluetooth Mesh Protocol specification](https://www.bluetooth.com/specifications/mesh-specifications/).

|**Term**|**Definition**|
|---|---|
|Address|The identity of one or more elements in one or more nodes.|
|Configuration Client|A node that implements the Configuration Client model.|
|Destination|The address to which a message is sent.|
|Device|An entity that is capable of being provisioned onto a mesh network.|
|Element|An addressable entity within a device. A device is required to have at least one element.|
|Message|A sequence of octets that is sent from a source to a destination.|
|Network|A group of nodes sharing a common address space.|
|Node|A provisioned device.|
|Provision|The process of authenticating and providing basic information (including unicast addresses and a network key) to a device. A device must be provisioned to become a node. Once provisioned, a node can transmit or receive messages in a mesh network.|
|Provisioner|A node that is capable of adding a device to a mesh network.|
|Relay|A node that receives and then retransmits messages.|
|Source|The address from which a message is sent.|
|State|A value representing a condition of an element that is exposed by an element of a node.|
|Subnet|A group of nodes that can communicate with each other.|

##### Simplicity Studio 5 and Bluetooth Mesh

A number of new features and architecture changes were introduced beginning with Bluetooth Mesh SDK v2.0 and Simplicity Studio 5. The features supported are backward compatible with applications built with the Bluetooth Mesh SDK v1.x, although the API in use is different. Projects generated with the Bluetooth Mesh SDK v2.0 and higher can be configured via the three following input parameter tools:

- Project file, using the slcp extension (silicon labs component project) (For the Mesh components)
- Bluetooth mesh configurator (for DCD configuration)
- Bluetooth GATT configurator (for Mesh services)

![Bluetooth Configuration Overview](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image1.png)

> **Note**: Unlike versions 1.x and lower, the current version of the Bluetooth Mesh SDK does not have a Generate control. Project files are generated and updated as you make changes and save the updates in the Component Configurator.

###### Bluetooth Mesh Components

Upon creation of a Bluetooth Mesh project in Simplicity Studio 5, at least three tabs open automatically:

- The GATT Configurator (gatt_configuration.btconf)
- The slcp file or Project Configurator (<projectname>.slcp
- The Bluetooth Mesh Configurator (dcd_config.btmeshconf).

If the example has documentation, the project opens on a readme tab.

![Bluetooth Mesh Configuration Tools](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image2.png)

The **GATT Configurator** is the same for both Bluetooth and Bluetooth mesh projects. [GATT Configurator User’s Guide for Bluetooth® LE and Bluetooth Mesh](/btmesh/11.0.0/gatt-configurator-users-guide-ble-btmesh) describes how to configure the GATT database.

The **Project Configurator** and associated component editor allows you to install/uninstall and configure components.

![Project Configurator, Software Components Tab](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image3.png)

The **Bluetooth Mesh Configurator** provides access to Device Composition Data (DCD). This contains information about a Bluetooth mesh node, the elements it includes, and the supported models. DCD exposes the node information to a configuration client so that it knows the potential functionalities the node supports and, based on that, can configure the node.

![Bluetooth Mesh Configurator](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image4.png)

###### Bluetooth Mesh Configurator

To access Device Composition Data, open the Bluetooth Mesh Configurator on the dcd_config.btmeshconf tab. The Device Composition data is presented in three areas: device information, elements, and models.

###### Device Information (heading level 7)

The device information card contains four fields, shown in the following figure.

![Device Information Card](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image5.png)

The Company field is linked to the Company ID field, changing one will automatically change the other as a result. The meaning of each field is shown in the following table.

|**Field Name**|**Notes**|
|---|---|
|Company|The company name in the list containing all the registered companies in Bluetooth SIG|
|Company ID|16-bit company identifier assigned by the Bluetooth SIG|
|Product ID|16-bit vendor-assigned product identifier, vendor-specific|
|Version Number|16-bit vendor-assigned product version identifier, vendor-specific|

A list of companies and their unique identifier can be found [on the Bluetooth SIG site](https://www.bluetooth.com/specifications/assigned-numbers/company-Identifiers).

###### Elements (heading level 7)

An element is an addressable entity within a node. Each node can have one or more elements, the first called the primary element and the others called secondary elements. Each element is assigned a unicast address during provisioning, so that it can be used to identify which node is transmitting or receiving a message. The primary element is addressed using the first unicast address assigned to the node, and the secondary elements are addressed using the subsequent addresses. Both primary and secondary elements have a dedicated card, such as that shown in the following figure, through which they can be configured. Click the green plus symbol to add an element or select an element and click the red X symbol to remove it.

![Primary Element Card](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image6.png)

###### Models (heading level 7)

A model defines the basic functionality of a node. A node may include multiple models. A model defines the required states, the messages that act upon those states, and any associated behaviors.

Models may be defined and adopted by the Bluetooth SIG and may also be defined by vendors. Models defined by the Bluetooth SIG are known as SIG-adopted models, and models defined by vendors are known as vendor models. SIG-adopted models are identified by a 16-bit model identifier and vendor models are identified by a 16-bit vendor identifier and a 16-bit model identifier.

The Bluetooth Mesh Configurator supports configuring both SIG-adopted models and vendor models through separate editors selected by the SIG models and Vendor models selector just below the Bluetooth Mesh Configurator -text.

###### SIG-Adopted Model Editor (heading level 7)

###### Add SIG Models via Components (heading level 8)

If you are using the provided model components that automatically bring in the source/header files, libraries, and configurations to the project, and also contribute the model to the DCD, you cannot edit or delete the model from the DCD manually. The model is greyed out, as shown in the following figure. In this case, all the model implementations will be generated to the project. You can modify the callbacks to adjust the application to your use case.

![SIG-Adopted Model Editor with Components](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image7.png)

###### Edit SIG Models Manually (heading level 8)

The DCD editor displays the information list of available models in SSv5 on the left side. Because models are added and configured as  components, they are not editable in the Mesh configurator. To build the DCD from a clean slate, for example when adding specific models to an element, uninstall all model components manually and then edit the DCD.

To delete a model, select it and click the red X symbol. To add a SIG-adopted model, drag and drop the model from the left model pool to the SIG Models table in the correct element. A list of all the SIG-adopted models is displayed, and you can choose the one that is needed. Note that, although all the SIG-adopted models are listed, not all of them are currently supported by the Bluetooth Mesh SDK. For the information on the supported models, see the SDK release notes.

![SIG-Adopted Model Editor](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image8.png)

Due to the extension mechanism of models mentioned above, attention must be paid when adding models to your project:

1. When adding a model that is not a root model, in other words an extended model, all the models it extends from should also be added. The Bluetooth Mesh Model Specification has the detailed definition of the models’ relationships. For example, to add a Light Lightness Server model, the Generic Power On/Off Server model and the Generic Level Server model must also be present in the settings, because the Light Lightness Server model is extended from them.
2. One element can only have one instance of a model. For example, if both model A and Model B are extended from Model C, you cannot add them both to a single element because it would require two Model C instances. The appropriate way to achieve this is to have two elements, and put model A and model C in one element and model B and model C in the other element. For example, the light example in the Bluetooth Mesh SDK has two elements in order to have two Generic Level Server model instances.

In addition to the above points, follow the points below when editing the model setting of a node.

1. The configuration server model must be supported by a primary element and must not be supported by any secondary elements.
2. To develop a provisioner, add at least the configuration client model in your project, and it should be in the primary element.
3. The health server model must be supported by a primary element and may be supported by any secondary elements.
4. If the health client model is supported, it must be supported by a primary element and may be supported by any secondary elements.

###### Vendor Model Editor (heading level 7)

The Vendor models give you more flexibility when developing products not covered by the SIG-adopted models. Vendors can define their own specification in these models, including states, messages, and the associated behaviors. The vendor model editor is shown in the following figure. The ID field contains the 32-bit vendor identifier and model identifier. The two least significant bytes of the ID are the vendor ID and the two most significant bytes are the model ID. In the following figure, 0x02FF is the vendor ID for Silicon Labs, and 0x0021 and 0x0022 is the model ID.

![Vendor Model Editor](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image9.png)

Do one of the following:

- Click **New Vendor Model** to create a new vendor model
- Select a model to edit it
- Click the + symbol to add it to a element
- Click the red X from the element to remove it.

###### Bluetooth Mesh Stack

The Bluetooth Mesh SDK provides several SRAM and internal flash consumption optimization options. Memory should be configured to allocate the appropriate amount of resource needed, so the space left for application usage is optimized. The stack memory configuration can be tuned by configuring the Bluetooth Mesh Stack component.

The following figure shows the available configuration options:

![Bluetooth Mesh Stack Configuration](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image10.png)

All configuration options affect RAM consumption. The stack allocates various structures at startup based on the values entered and uses the allocated memory during operation.

Some configuration options also affect consumption of persistent storage in internal flash. The stack allocates space in persistent storage based on the configuration option values at start up. The persistent storage implementation used by the Bluetooth Mesh stack is either NVM3 (recommended, default on series 2) or PS Store. For more details, see [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](/btmesh/11.0.0/using-third-generation-nonvolatile-memory).

The following table summarizes the configuration options:

|**Configuration Option**|**Description**|**Stored Persistently**|**Notes**|
|---|---|---|---|
|Maximum number of Network Keys allowed|The maximum number of network keys that can be stored (see 2.2.1 Network and subnets and 2.3.9 Security of Mesh Protocol 1.1).|Yes|No larger than 4.|
|Maximum number of Application Keys allowed|The maximum number of application keys that can be stored (see 2.2.1 Network and subnets and 2.3.10 Security of Mesh Protocol 1.1.).|Yes|No larger than 4.|
|Maximum number of application bindings allowed|The maximum number of application keys that can be bound to a model.|Yes|No larger than the value of ‘Maximum number of Application Keys allowed’.|
|Maximum number of subscriptions allowed|The maximum number of addresses that the device can subscribe to (see 3.7.5.2 Subscribe of Mesh Protocol 1.1).|Yes|No larger than 255.|
|Maximum number of provisioned devices allowed|The maximum number of devices that can be provisioned by this device.|Yes|Only applicable if the device is in provisioner role, no larger than 512. Set to 0 for node role.|
|Replay Protection List size|The replay protection list size (see 3.9.8 Message replay protection of Mesh Protocol 1.1).|Yes|Set to equal or greater than the expected number of elements the device will communicate with. Otherwise, the node cannot receive a message from any new node if the list is already full. Must be no larger than 4096 and divisible by 16.|
|Maximum number of virtual addresses|The maximum number of virtual addresses the models on the device can publish or subscribe to (see 2.3.5 Addresses and 3.4.2.3 Virtual address of Mesh Protocol 1.1).|Yes|Set to 0 if virtual address not used.|
|Maximum number of Network Keys allowed for each Provisioned Device|The maximum number of network keys on the peers provisioned by this device.|Yes|Only applicable if the device is in provisioner role.|
|Maximum number of Application Keys allowed for each Provisioned Device|The maximum number of application keys on the peers provisioned by this device|Yes|Only applicable if the device is in provisioner role.|
|Maximum number of simultaneous segmented receptions|The maximum number of segmented messages that can be received in parallel (see 3.5.3 Segmentation and reassembly of Mesh Protocol 1.1).|No|Set to a low number if little segmentation is used.|
|Maximum number of simultaneous segmented transmissions|The maximum number of segmented messages that can be sent in parallel (see 3.5.3 Segmentation and reassembly of Mesh Protocol 1.1).|No|Set to a low number if little reassembly is used.|
|Maximum number of provisioning sessions allowed|The maximum number of simultaneous provisioning sessions the device supports.|No|Set to 1 if the device is in node role. For the provisioner role, set to greater than 1 if provisioning multiple devices simultaneously.|
|Maximum number of Client Commands for the Foundation Model|The maximum number of commands that Configuration and Health client can send in parallel (see 4 Foundation models of Mesh Protocol 1.1).|No|Only applicable if the device is in provisioner role.|
|Network Cache size|The network message cache size (see 3.4.6.5 Network Message Cache of Mesh Protocol 1.1).|No|Network density-dependent.|
|Number of connections to reserve for GATT Proxies|The maximum number of GATT connections for PB-GATT and GATT bearers.|No|Can be 0 if PB-GATT and GATT bearers are not supported.|
|Maximum number of provisioning bearers allowed|Number of provisioning bearers (see 5.2 Provisioning bearer layer of Mesh Protocol 1.1).|No|Number of supported provisioning bearers, PB-ADV, PB-GATT and/or PB-REMOTE. Not greater than 3.|
|Maximum number of Friendships allowed|The maximum number of friendships that can be established (see 2.3.12 Friendship of Mesh Protocol 1.1).|No|Only applicable for friend node.|
|Maximum size of Total Friend Cache|The maximum number of messages a friend node can cache. (see 3.5.5 Friend Queue of Mesh Protocol 1.1).|No|Only applicable for friend node.|
|Maximum size of Cache for a single Friendship|The maximum number of messages a friend node can cache for a single low-power node (see 3.5.5 Friend Queue of Mesh Protocol 1.1).|No|Only applicable for friend node.|
|Maximum size of Friendship Subscription List|The maximum number of addresses that can be stored in the Friend Subscription List.|No|Only applicable for friend node.|
|GATT TX Queue size|Queue size for messages over GATT bearer.|No|Connection interval-dependent.|
|Access Layer TX Queue Size|The maximum number of messages that can be queued in the Access layer (see 3.7.3.1 Transmitting an access message of Mesh Protocol 1.1).|No|Default 5|
|Element sequence number write interval exponent|The latest Network PDU sequence numbers are stored into flash from time to time as defined by this setting for reset or power off situations.| |From 0 to 23, default 16.|
|Size of RAM cache for persistent keys stored within PSA ITS|PSA ITS (internal trusted storage) Mesh encryption keys RAM cache to increase runtime performance.| |From 0 to 544, default 16.|
|Maximum number of proxy access control list entries|Define the number of proxy access control list entries.| |Default 8|
|Maximum number of Key Refresh requests pending for the Provisioner|Define the maximum number of concurrent config client requests to nodes during Key Refresh| |Default 16|

To download Mesh Protocol 1.1 (currently a draft version d1.1r20), go to [https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=554899](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=554899).

###### Maximum Number of Network Keys Allowed (heading level 7)

The value determines the maximum number of network keys that can be stored in the device. For the Bluetooth Mesh SDK v5.x, the maximum is 4, which means a device can support no more than 4 subnets. A node should stay in the network(s) it was in after a power cycle, so the network keys and the related information should be stored persistently. Because of the key refresh procedure requirements, each network key will hold 2 values – the current network key and the old network key.

###### Maximum Number of Application Keys Allowed (heading level 7)

The value determines the maximum number of application keys that can be stored in the device. For the Bluetooth Mesh SDK v5.x, the maximum number is 4, which means a device can support no more than 4 application keys no matter which network keys they are bound to. The application keys and the related information should be stored persistently. Because of key refresh procedure requirements, each application key will hold 2 values – the current application key and the old application key.

The maximum application key number should be set close to the expected number of application keys that will be used in a network.

###### Maximum Number of Application Bindings Allowed (heading level 7)

If a message is successfully decrypted by the upper transport layer with an application key, the decrypted message and the application key information will be delivered to the access layer. The access layer will check if the message is used by the model on the node, and then check if the application key is bound to the model. This value decides the maximum number of application keys that can be bound to a single model. The binding information will be stored persistently. Because the bindings are model-specific, the total amount of flash usage is multiplied by the number of models on the node.

The number of bindings should not be set larger than the number of application keys that can be stored on the device. It can be set to a smaller number if it is expected that each model will be bound to only one or a few keys.

###### Maximum Number of Subscriptions Allowed (heading level 7)

Each model can have a separate or a shared subscription list, if it supports subscription. This value determines the subscription list size, in other words, how many addresses can be subscribed by a model. All the subscription lists will be stored persistently, because the extended models share the same subscription list with their root model. The real amount of space depends on what models are on the device.

The number of subscriptions should be set to the maximum expected number of subscriptions to be made to each model, or slightly larger.

###### Maximum Number of Provisioned Devices Allowed (heading level 7)

This setting is applicable only when the device is in the provisioner role. The value determines the maximum number of devices the provisioner can provision to the network. The best number for this setting should be the maximum expected network size. For Bluetooth Mesh SDK v5.x, the maximum value is 512, which means the maximum network size supported by the stack is 512 nodes.

Because a node cannot provision any devices into the network and doesn’t have the device database, set to 0 for devices in node role.

###### Replay Protection List Size (heading level 7)

A message sent by a legitimate originating element can be passively received by an attacker and then replayed later without modification. This is called a replay attack. Because the originating element has encrypted and authenticated the message using the correct keys, the receiver cannot determine whether it is under a replay attack solely by performing the message integrity checks.

To increase protection against replay attacks, each element increases the sequence number for each new message that it sends, and the receivers keep track of the largest sequence number they have received from each originating element. This bookkeeping is called the replay protection list. If a valid message has been received from an originating element with a specific sequence number, any future messages from the same originating element containing sequence numbers less than or equal to the last valid sequence number are very likely replayed messages and should be discarded. Therefore, messages are delivered to the access layer in sequence number order.

Due to security concerns, entries in the replay protection list cannot be reused, which means there is no way to delete or clear an entry if it has already been used. No Least Recently Used algorithm is used in this list because it brings potential security risks. It is explicitly specified in the Mesh Protocol 1.1. If a node does not have enough resources to perform replay protection for a given source address, then the node shall discard the message immediately upon reception.

Furthermore, because nodes could be removed from the network and new devices will be added to the network, the replay protection list should be set to the maximum number of elements the device will communicate with, which could be larger than the maximum network size in this case. For example, assume the network size is 5, contains devices 1-5, and they have already communicated with each other. The replay protection list on device 1 should contains device 2-5, which occupies 4 entries. Then, if devices 2-5 are removed from the network and devices 6-9 are added to the network, device 1 will need 4 more entries in the replay protection list to be able to communicate with devices 6-9. In this scenario, device 1 needs 8 replay protection entries, which is larger than the network size of 5.

The replay protection list is stored persistently. The number of replay protection list entries should be set to the number of peers a node is expected to communicate with, rounded up to the nearest number divisible by 16.

###### Maximum Number of Virtual Addresses (heading level 7)

This setting determines the maximum number of virtual addresses the models on the device can publish or subscribe to. A virtual address is a multicast address and can represent multiple elements on one or more nodes. Each virtual address logically represents a Label UUID, which is a 128-bit value that does not have to be managed centrally. Each message sent to a Label UUID includes a message integrity check value containing the full Label UUID that is used to authenticate the message. To reduce the overhead of checking every known Label UUID, a hash of the Label UUID is used. Although the virtual address is 2 bytes, the 128-bit label UUID value should be stored persistently because the full data needs to be used for decrypting the messages sent to virtual addresses.

The number of virtual addresses should be set to as small a number as possible, or zero if it is expected that virtual addresses are not used. The current Mesh Model specification does not require the use of virtual addresses, so at the moment they are used only in vendor-specific contexts.

###### Maximum Number of Network Keys Allowed for each Provisioned Device (heading level 7)

This setting is only used during the key refresh procedure. The provisioner should persistently store the states of network keys of the nodes participating in the key refresh procedure. This value determines the maximum number of network keys that can be included in the key refresh procedure, in other words, how many network keys can be refreshed one time.

This only applies to a provisioner. Set to 1 if you only want to refresh one network key at a time, or a higher value if the use case needs to refresh more than one network key at once. Set to 0 for devices in node role.

###### Maximum Number of Application Keys Allowed for each Provisioned Device (heading level 7)

This setting is only used during the key refresh procedure. The provisioner should persistently store the states of application keys of the nodes participating in the key refresh procedure. This value determines the maximum number of application keys that can be included in the key refresh procedure, in other words, how many application keys can be refreshed one time.

This only applies to a provisioner. Set to 1 if you only want to refresh one application key at a time, or a higher value if the use case needs to refresh more than one application key at once. Set to 0 for devices in node role.

###### Maximum Number of Simultaneous Segmented Receptions (heading level 7)

Due to the packet size limitation in Bluetooth Mesh, a message may be sent unsegmented or segmented, depending on the message payload size. For the transport layer to receive the segmented message, it has to cache the received segments before all the segments are received successfully. This setting determines the maximum segmented messages that can be received concurrently. Note, this does not define how many segmented packets in a message, but how many segmented messages no matter how many packets the message is segmented into. For example, if the setting is 3, the node is able to receive segmented message A, B, and C simultaneously, no matter how messages A, B, and C are segmented into A1, B1, C1 … An, Bn, Cn. The maximum number that a message can be segmented into is defined in the Mesh Protocol specification.

A device with standard models rarely receives segmented messages (encryption key deployment being one example) so a low number can be used if none of the vendor models need segmentation.

###### Maximum Number of Simultaneous Segmented Transmissions (heading level 7)

Due to the packet size limitation in Bluetooth Mesh, a message may be sent unsegmented or segmented, depending on the message payload size. For the transport layer to send the segmented message, it has to cache the whole message before all the segments are sent and acknowledged successfully. This setting determines the maximum segmented messages that can be sent concurrently. Note, this does not define how many segmented packets are in a message, but how many segmented messages no matter how many packets the message is segmented into. For example, if the setting is 3, the node is able to send segmented message A, B, and C simultaneously, no matter how messages A, B, and C are segmented into A1, B1, C1 … An, Bn, Cn. The maximum number that a message can be segmented into is defined in the Mesh Protocol specification.

A device with standard models rarely sends segmented messages (encryption key deployment being one example) so a low number can be used if none of the vendor models need segmentation.

###### Maximum Number of Provisioning Sessions Allowed (heading level 7)

Provisioning is session-based. A provisioner does not necessarily need to provision the devices serially, but instead can provision the devices in parallel. This setting determines the maximum number of provisioning sessions that can happen concurrently. For example, in an ideal scenario, if the value is 1 and each provisioning takes 3 seconds, then provisioning 100 devices takes 300 seconds. If you set this value to 5, then it takes 60 seconds in total to provision all 100 nodes. Although in practice the time will be affected by packet collision, it should still be much less than 300 seconds.

This does not need to be over 1 for devices in node role because a device cannot be provisioned by multiple provisioners at the same time. It may be over 1 for a provisioner that provisions devices concurrently and it significantly reduces the time for provisioning a large network.

###### Maximum Number of Client Commands for the Foundation Model (heading level 7)

After provisioning a device into a network, the first step is probably to configure the node because an unconfigured node is not functional. The configuration starts by the configuration client model sending a command to the configuration server on the node, followed by a reverse status message if applicable. The current Mesh Protocol 1.1 specification only defines several foundation client models. This setting determines how many commands can be sent by the foundation client models concurrently before the status message is received. For example, in an ideal scenario, if the value is 1 and the configuration to add an application key to a node takes 3 seconds, then adding the application key to 100 devices takes 300 seconds. If you set this value to 5, then it takes 60 seconds in total to add the application key to all 100 nodes. Although in practice the time will be affected by packet collision, it should still be much less than 300 seconds.

This is not applicable and should be set to 0 for devices that do not have foundation client models. It may be over 1 for a provisioner that configures devices concurrently and it significantly reduces the time for configuring a large network.

###### Network Cache Size (heading level 7)

The network message cache is used to reduce unnecessary security checks and excessive relaying. It is a list of all the information about recently seen network packets. When a network PDU is received and already in the network message cache, for example because of network retransmission, it will be discarded immediately without processing. If a received network PDU is not in the network message cache, its information should be added to the network message cache and be further processed.

Note, this network message cache is different from the replay protection list. It is not for security. When the Network Message Cache is full and an incoming new Network PDU needs to be cached, an incoming new Network PDU should replace the oldest Network PDU that is already in the Network Message Cache.

The suitable value is dependent on expected network density, node configuration, and traffic frequency. For example, if network layer repetition is configured on, with an interval that allows multiple messages to be injected to the network by other nodes during the interval, the cache should be large enough to handle this and not flush the previous Tx before the repetition.

###### Number of Connections to Reserve for GATT Proxies (heading level 7)

This setting determines the maximum number of GATT connections the device can establish concurrently. For devices in an unprovisioned state, the GATT connections can be used for establishing the PB-GATT bearer so that provisioning can be done over GATT. For devices in a provisioned state and supporting Proxy, the GATT connections can be used for establishing the proxy connections so that all the communication can go over GATT bearers.

If devices do not support the Proxy feature or provisioning over a GATT connection, it can be set to 0. The number of proxy filters is limited to 16 per connection.

###### Maximum Number of Provisioning Bearers Allowed (heading level 7)

Three provisioning bearers are defined in the Mesh Protocol 1.1: PB-ADV, PB-GATT, and PB-REMOTE. This setting should be consistent with the number of provisioning bearers supported by the device. An unprovisioned device may support PB-ADV and may support PB-GATT. Supporting both PB-ADV and PB-GATT is strongly recommended. A Provisioner must support at least one of PB-ADV or PB-GATT. Supporting PB-ADV is strongly recommended. PB-REMOTE is required for the remote provisioning in the provisioner (the remote provisioning client controlling the remote provisioning operation) and the remote provisioning server (communicating with the unprovisioned node using PB-ADV or PB-GATT).

The value should not be set to larger than 3 as only 3 available provisioning bearers are defined in Mesh Protocol 1.1. It is also not recommended to set it to 0, as provisioning is mandatory for devices to be added to a network.

###### Maximum Number of Friendships Allowed (heading level 7)

In principle, all the nodes in the Bluetooth Mesh network should listen for incoming packets at the highest possible duty cycle to avoid losing packets. But a battery-powered device must sleep to save power, so it must be associated with an always-on device that stores and relays messages on its behalf. The relationship between the always-on node and the battery-powered nodes is friendship.

This setting is only applicable for nodes that support the friend feature. It determines the maximum number of friendships it can establish, in other words, the maximum number of low-power nodes it can establish the friendship with concurrently. Set to 0 if the node does not support the friend feature.

###### Maximum Size of Total Friend Cache (heading level 7)

As mentioned in Section [Maximum number of Friendships allowed](#maximum-number-of-friendships-allowed) , a low-power node needs to establish a friendship with a neighboring friend node. The friend node will cache the message targeted to the low-power node and the low-power node can periodically poll the friend node for messages. All the cached messages are stored in the Friend Queue. This setting determines the Friend Queue size, that is, how many messages in total it can store for all the low-power nodes it established friendship with. It is only applicable for nodes which support the friend feature.  Set to 0 if the node does not support friend feature.

###### Maximum Size of Cache for a Single Friendship (heading level 7)

The _**Maximum size of Total Friend Cache**_ setting (section [Maximum number of Friendships allowed](#maximum-number-of-friendships-allowed) ) determines the maximum number of messages that can be stored in the Friend Queue in total. This setting determines the maximum number of messages that can be stored in the Friend Queue for a single Friendship. Because of the difference among use cases, the requirement for the number of messages to be stored could vary from one low-power node to another. This setting and the _**Maximum size of Total Friend Cache**_ setting make the allocation of the Friend Queue dynamic when establishing friendships, and the use of the Friend Queue more efficient. This setting is only applicable for nodes that support the friend feature and must be set equal to or less than the _**Maximum size of Total Friend Cache**_ setting. Set to 0 if the node does not support the friend feature.

###### Maximum Size of Friendship Subscription List (heading level 7)

As mentioned in section [Maximum number of Friendships allowed](#maximum-number-of-friendships-allowed), the friend node needs to cache the message targeted to the low-power node that it established the friendship with. The low-power node would like to receive two types of messages. One is the message with the destination address to be the unicast address(s) on the low-power node. The other is the addresses that the low-power node subscribes to. In order to cache the messages designated for the addresses that the low-power node subscribes to, the friend node needs to maintain a list of the low-power node’s subscription addresses. A low-power node could update the subscription list by adding addresses to the list or removing addresses from the list. This setting determines the maximum addresses that can be stored in the subscription list on the friend node for a single low-power node.

###### GATT TX Queue Size (heading level 7)

This setting determines the number of PDUs that may be pending transmit on the GATT bearer. The value may be small for a node that is only configured over a GATT proxy bearer (default is 4). It may need to be larger for a node that acts as a GATT proxy between the network and a legacy device, and where the connection interval for the GATT connection is long.

###### Access Layer TX Queue Size (heading level 7)

As defined in 3.7.3.1 Transmitting an access message of [Mesh Protocol 1.1](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=554899), the message in response to a received message should be sent after a random delay. Those messages need to be queued in the stack waiting for the timing to be sent. This setting determines the maximum number of access layer messages that can be queued, in other words, how many replies can be queued for sending concurrently. For nodes that do not have server models, this value can be set to a low value as messages will only be cached during the configuration phase. For server model nodes, this value should be set according to the requirements of the actual use case.

###### Element Sequence Number Write Interval Exponent (heading level 7)

Each network PDU originating from a device must be sent with an increasing sequence number. To maintain this when the device is reset or powered off, the latest sequence numbers are stored in flash with a frequency defined by this setting. The setting defines the sequence number writing interval as a power of two exponent. For example, a value of 10 would mean 1024 (2 to the 10th power). To avoid excessive flash wear, the interval should be relatively high on a device that generates a lot of traffic, and it can be set relatively low on a device that generates little traffic. Range from 0 to 23, the default is 16.

###### Size of RAM Cache for Persistent Keys stored within PSA ITS (heading level 7)

When PSA internal trusted storage (ITS) is used to store the Mesh encryption keys, a RAM cache should be set up to increase runtime performance. The size of the cache should be set according to the expected use of application and device keys. For a node, it can be set to the number of application keys times two (to accommodate both key variants during a key refresh); for a Provisioner, it should be set to the number of application keys times two (to accommodate both key variants during a key refresh) plus a fraction of the expected number of device keys that will be stored. For devices that do not use PSA ITS, the setting is ignored. Range from 0 to 544, the default is 16.

###### Maximum Number of Proxy Access Control List Entries (heading level 7)

Define the number of proxy access control list entries. The default is 8.

###### Maximum Number of Key Refresh Requests Pending for the Provisioner (heading level 7)

Define the maximum number of concurrent config client requests to nodes during Key Refresh. Uses sizeof(pointer) per request statically, each pending request is dynamically allocated. The default is 16.

###### Bluetooth GATT Configurator

The Bluetooth Mesh technology is primarily based on BLE advertisements that use a specific Mesh Message AD (Advertising Data) type. Some nodes, though, might not be able to advertise using the Mesh Message AD type, and instead require a GATT connection to send and receive network packets, provisioning data and so on.

The Bluetooth Mesh specification defines two GATT services dedicated to mesh networks for good operation in a connected context:

- The Mesh Provisioning service (0x1827)
- The Mesh Proxy service (0x1828)

A device may support the Mesh Provisioning Service or the Mesh Proxy Service or both. If both are supported, only one of these services should be exposed in the GATT database at a time. For more details on those services, refer to the [Bluetooth Mesh Protocol specification (section 7).](https://www.bluetooth.com/specifications/mesh-specifications/)

In the current Silicon Labs’ Bluetooth Mesh SDK, both services are present in the GATT database by default when creating a project.

The services have their capabilities disabled by default because they are Bluetooth Mesh-specific.

In certain cases, typically when provisioning through a gateway running a third party or open source stack like BlueZ or Zephyr OS, it is necessary to have the services advertised. This simply indicates to the provisioner that the Mesh services are supported by the node.

Note that, by default, when working with the current Bluetooth Mesh SDK, this is not necessary.

![Bluetooth GATT Configurator](/btmesh-node-configuration-v5x-and-higher/10.0.0/images/sld825-image11.png)

Enabling and disabling service advertisement can be done through just editing the service.

##### Bluetooth Mesh SDK and EFR32BG Series 1 and 2

The Bluetooth Mesh SDK v2.0 and higher supports both EFR32BG series 1 and series 2 products. Some products may not support all features.

###### Series 1 Support

Only EFR32xG13 and EFR32xG12 products support the Bluetooth Mesh stack.

###### Series 2 Support

Bluetooth Mesh is fully supported by EFR32xG21, EFR32xG24, and EFR32xG27 products. Due to memory considerations, EFR32xG22 chips have limited support for the Bluetooth Mesh stack (LPN and Proxy features available only).

###### Bare Metal and OS Support

Typically, examples are running on bare metal, but since Simplicity SDK 2024.12, the selected RTOS version examples using FreeRTOS and Micrium OS for the devices listed above and with more than 64 kB of RAM are also available.

#### Using Network Analyzer With Bluetooth Low Energy And Mesh

##### Using Network Analyzer with Bluetooth® Low Energy and Mesh

> **Note: This section replaces _AN1317: Using Network Analyzer with Bluetooth® Low Energy and Mesh_. Further updates to this application note will be provided here**.

This document briefly describes the features of the Simplicity Studio 5 Network Analyzer for Bluetooth Low Energy and Mesh. It can be used and read jointly with the _AN958: Debugging and Programming Interfaces for Customer Designs_ for more information on PTI usage with custom hardware.

This document assumes familiarity with the basic Network Analyzer information in the [Simplicity Studio 5 User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-network-analyzer/)

###### Key Points

- Packet Trace Interface
- Wireless Network Analysis
- ISD capture files
- Bluetooth mesh networks
- Bluetooth mesh security keys
- Bluetooth Low Energy

##### Introduction

Network Analyzer is a tool for analyzing wireless network traffic. It supports a wide variety of short-range wireless protocols like Bluetooth Low Energy, Zigbee, proprietary protocols and others. It is provided as part of the Simplicity Studio tool set.

###### Debugging a Wireless Network

Silicon Labs’ tool set provides the user with a comprehensive way to analyze wireless traffic. With it, the user can tap into the data buffers of the radio transceiver via a dedicated serial hardware interface called the Packet Trace Interface (PTI). PTI data can be then transferred via USB or Ethernet to a computer running Simplicity Studio. Finally, the time-stamped data can be interpreted and displayed in Network Analyzer.

Most Silicon Labs’ development kits, such as the Wireless Starter Kit (WSTK), have the PTI embedded and ready to use. Note that it is also possible to use the network analysis features when working on custom hardware if the PTI pins are exposed via a debug interface.

##### Hardware and Packet Trace Interface (PTI)

On the EFR32 series 1 and 2, a mechanism is provided for the user to be able to tap into the data buffers at the radio transmitter/receiver level. From the embedded software perspective, this is available through the **RAIL Utility, PTI** component in Simplicity Studio. That component is effectively a simple packet trace interface driver.

###### Packet Trace Interface

The Packet Trace Interface (PTI) is an interface giving serial data access directly to the radio transmitter/receiver frame controller. The following figure describes at a high level the architecture of the radio transceiver.

![RadioTransceiver Architecture](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image1.png)

A clock and data signal are connected to the frame controller to monitor all packets received/transmitted by the chip. At the chip level, a signal is dedicated to trigger the timestamping of each PTI frame by the WSTK board controller. The PTI is a non-intrusive sniffer of data, radio state and time stamp information.

A single-pin UART signal is used for PTI data transfer. This can be configured in the **RAIL Utility,** **PTI** component. The baud rate is selectable. The default baud rate is 1.6 Mbps. The maximum baud rate is 3.2 Mbps.

When using 2M PHY with Bluetooth Low Energy, the default PTI-over-UART speed (1.6 Mbps) must be increased to a higher baud rate. The following shows an example:

![Using 2M PHY with Bluetooth Low Energy](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image2.png)

Additionally, the speed at which the PTI frames are forwarded from the EFR32 back to USB/UART must also be increased. This is done by setting the PTI config corresponding to your adapter at the correct baud rate through the Admin Console interface.

In the Debug Adapters view, right-click the device. In the context menu, select **Launch Console…**

![Launch Console](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image3.png)

Select the Admin tab, and execute the command:

`pti config 0 efruart 3200000`

![Execute Command](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image4.png)

###### Hardware Kit and PTI

As described previously, the WSTK can be used to monitor the wireless traffic. The WSTK can be connected to the PC via USB or Ethernet:

- USB - The simplest solution. This is used throughout this document.
- Ethernet - Recommended for best performance and scalability.

![WSTK Board](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image5.jpg)

Alternatively, it is possible to use the PTI on custom hardware if the corresponding pins are exposed (via the 20-pin Simplicity Connector on the WSTK or the Simplicity Mini connector on the debug adapter for example):

![Figure Simplicity Debug Adapter Exposing PTI Signals on the Mini and Simplicity Connectors](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image6.png)

![Figure 20-Pin Simplicity Connector and the Mini Connector](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image7.png)
![Figure 20-Pin Simplicity Connector and the Mini Connector](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image8.png)

For more detail, refer to _AN958: Debugging and Programming Interfaces_.

##### Network Analyzer Features

This section describes the main features of the Network Analyzer user interface.

###### Tool Access and Preference Page

Network Analyzer is provided with Simplicity Studio. For easy access, on the toolbar click **Tools**, and select **Network Analyzer**.

![Network Analyzer](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image9.png)

With Network Analyzer Preferences, accessed by **Windows > Preferences** or the **Preferences** control on the toolbar, you can tune the tool, add security keys, and modify displays and icons.

![Network Analyzer Preferences](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image10.png)

You can also modify the Bluetooth protocol decoder in great detail (under the Decoding menu), define the integration with other tools (Energy profiler, Wireshark), and add Security keys (see section [Keys](04-network-analyzer-for-bluetooth-le-and-mesh#keys) for more information).

###### Interface

###### Large File Editor (heading level 7)

Because radio traffic contained in a captured session can be very large, a pane allowing time interval selection is opened first, as shown in the following figure. The interface implementing that feature is called the Large File Editor. It gives a complete overview of the capture session and allows you to select a specific time interval of study.

![Large File Editor](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image11.png)

**Interval viewing pane**: Displays the traffic data present in the ISD live or recorded session. The data points corresponding to the green curve represent the number of packets per unit of time. Further display options are available through the right-click context menu.

**Open Interval button**: Once you have selected the area of interest in the interval view, click **Open Interval** to see traffic detail. This opens a subsequent window in which transaction and events are listed, as shown in section [Interval Editor](#interval-editor).

**List of nodes**: In the right pane, the list of nodes present in the selected time interval is shown.

**Filtering pane**: Some packet filtering can be done on the selected time interval. In practice, this is more useful in the transaction/event pane. Filters are explained in more detail in section [Filters](#filters).

**Bookmarks and Event Difference pane**: Those functions are explained in detail in sections [Bookmarks](#bookmarks) and [Network Analyzer for Bluetooth LE](04-network-analyzer-for-bluetooth-le-and-mesh#network-analyzer-for-bluetooth-le), respectively

The following figure illustrates a selected interval (using the mouse directly on the waveform). The interval of interest appears in clear, whereas the rest of the interval viewing pane is greyed out.

![Selected Interval Display](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image12.png)

###### Interval Editor (heading level 7)

The Editor is laid out as follows:

![The Editor Present](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image13.png)

The events displayed in the event pane are directly linked to the transactions displayed in the transaction pane. When a transaction is selected, Network Analyzer jumps to the corresponding events in the event pane.

Press CTRL+SHIFT+Up/Down to toggle between events in a transaction.

In the **Status** field, “Missing packets” indicates that a packet expected in the transaction has not been received within the current timeout window.

> **Note**: A transaction is a group of related packets that together form a higher layer protocol procedure or message exchange. In the case of Bluetooth Low Energy (and Bluetooth mesh), a “transaction” refers to an actual Bluetooth Low Energy transaction as defined in the core specification. This corresponds most of the time to a Bluetooth Low Energy procedure. Equally, the event pane displays the actual Bluetooth Low Energy events corresponding to the transaction or procedure. For more details, refer to the Bluetooth Core specification document.

The filtering capabilities of the tool are explained in detail in section [Filters](#filters).

**Event detail pane**: The event detail pane exhibits all the data present in the corresponding Bluetooth LE packet. The data are displayed in a decoded format allowing the user to unpack the information at all layer levels, from radio information up to the GATT protocol and Bluetooth mesh Access layer. Using the Option menu in the top right corner of the Event Detail pane, you can expand the bit fields and toggle between hexadecimal and decimal format.

![Event Detail pane](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image14.png)

Note that when a bit field is selected, the corresponding data is automatically highlighted in the hex dump view of the packet.

Various layers of decoding exist, which can be viewed in the Hex Dump Pane (for Bluetooth mesh, result of Network decryption, Application decryption, Defragmentation of various levels and so on).

###### ISD File

Network Analyzer can capture data from nodes of any connected adapters, either from one node at a time or from multiple nodes. It can display data from Live sessions as well as Recorded sessions.

Network Analyzer saves session data to an ISD (.isd) file, which is a compressed file that stores session data and the network state. Network state includes display settings such as map modifications, which Network Analyzer restores when you reload the session file.

The following procedure describes how to start a network data capture on a single device:

1. In **Preferences > Simplicity Studio > SDKs** select the desired SDK.
2. In **Preferences** > **Network Analyzer** > **Decoding** >**Stack Version,** Make sure “Bluetooth Low Energy” is added in the decoding preferences.
3. If using encryption with known keys, make sure the security keys are added (see section [Keys](04-network-analyzer-for-bluetooth-le-and-mesh#keys) for more detail).
4. Connect to the adapter.  
   ![Adapter Connect](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image15.png)
5. Start capture.  
   ![Start Capture](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image16.png)

To start capturing on several adapters, press and hold the CTRL key and, in the Debug Adapters view:

1. Select more than one adapter.
2. Right-click and select **Connect**.
3. Right-click and select **Start Capture.**
4. Release the CTRL key.

a) ![Connect to a Group of Adapters.](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image17.png)

b) ![Start Capture on a Group of Adapters](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image18.png)

**a)** Connect to a Group of Adapters

**b)** Start Capture on a Group of Adapters

With Bluetooth mesh, when working in a busy environment, capturing from multiple nodes makes more sense than capturing from only one, because Bluetooth mesh nodes are constantly scanning for incoming packets.

For example, some nodes might be emitting Bluetooth mesh messages or beacons at the same time the node being used for capturing is answering a configure request. As a result, the data that were sent will not be received, simply because the link layer of the underlying Bluetooth LE stack was in the advertising state and not scanning. Additionally, there are three primary advertising channels and the radio transceiver can only listen to one channel at a time.

This should not be mistaken for an error or a malfunction in the stack. Rather, this is simply a by-product of the technology reliance on primary advertising channels and advertising PDUs. Apart from the GATT bearer scenario (relying on Bluetooth LE connections), there is no communication collision control.

> **Note**: It is possible to use “Duplicate Detection”, i.e. when the same packet is detected on multiple adapters it will only be displayed once. See **Preferences->Network Analyzer->Capture Configuration** for more details.

###### Bookmarks

Bookmarks can be used for marking events. As the name indicates, those are actual bookmarks that point to a certain Bluetooth LE or mesh event. Those are useful for pinpointing a certain event in a transaction that can be problematic and then sharing it with somebody else.

The following procedure shows how to set and navigate through bookmarks:

1. Select the event and right-click it.  
   ![Select the event](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image19.png)
2. Enter the bookmark name.  
   ![Enter the bookmark name](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image20.png)
3. See the bookmark recorded (highlighted in yellow).  
   ![See the bookmark recorded](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image21.png)

###### Set Zero-Time Anchor

When studying a particular event or transaction, it is sometime useful to set it as the time reference. Practically, this means setting the timestamp corresponding to that event or transaction to zero, and then seeing all subsequent timestamps updated according to the new time reference. Using this Network Analyzer feature is also an excellent way to verify the Bluetooth Low Energy advertising or connection timings (advertising interval, connection interval, and so on).

The following describes how this can be done, using a Bluetooth LE Initiating connection (CONNECT_IND) state as an example. Select the particular transaction or event, right-click to open the context menu, and then click **Set zero-time event anchor to this event.**

![Set zero time event anchor](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image22.png)

The timestamps of all events and transactions are then updated, taking into account the new anchor as time reference, as shown in the following figure.

![The timestamps of all events](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image23.png)

To remove the anchor, right-click the selected event or transaction and click **Unset zero-time**.

![Unset zero time](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image24.png)

###### Filters

Network Analyzer supports use of a set of built-in and manual filters.

###### Built-In Filters (heading level 7)

The following built-in filters can be enable/disabled when visualizing PTI data:

![Built in filters](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image25.png)

For example, you can filter Bluetooth LE data out in order to focus on Bluetooth mesh traffic. Radio errors and diagnostics can also be filtered out. Note that radio errors can be useful for debugging.

###### Manual Filters (heading level 7)

The filter bar is used to filter transactions and events. Each capture session has its own filters settings. When a session’s filter is changed and the filter is applied by clicking **Apply** in the Filter pane toolbar, Network Analyzer will refresh the display showing only the corresponding transactions or events. When you exit Network Analyzer, all sessions filters are cleared and must be reapplied when Network Analyzer is restarted.

Network Analyzer provides two ways to edit filters:

- Filter Manager: Maintains internally a set of saved filters that you can review and edit. You can also add new filters. You specify any of the saved filters for display on the Filters menu, where they are accessible for use in one or more sessions.
- Filter Bar: An editor that attaches to a given session, where you can enter one or more filter expressions on the fly. Network Analyzer discards filter bar expressions for all sessions when it exits. It does, however, store the expression for easier future access.

Multiple filters can be combined using logical expressions:

- && - And operator
- || – Or operator

Alternatively, conditions for individual filters can also be used:

- == - Equals
- != - Not equal
- |= - Contains

The following table shows examples of filtering in Bluetooth mesh traffic:

<table>
    <thead>
        <tr>
            <th>Filter example</th>
            <th>Meaning</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>transaction.summary |= "BT Mesh"<br>transaction.summary |= "Generic" &amp;&amp; transaction.dest == "C001"</p>
            </td>
            <td>
                <p>Show transactions where the summary field contains the text 'BT Mesh'<br>Summary contains string Generic and the destination address is 0xC001</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>transaction.summary != "EFR Rx packet"</p>
            </td>
            <td>
                <p>Do not show transactions with summary 'EFR Rx packet' → Hide those transactions that Network Analyzer cannot decode.</p>
            </td>
        </tr>
    </tbody>
</table>

The following figure shows an example of saved combined filters.

![Example of saved combined filters](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image26.png)

Alternatively, you can right-click and select preset filters.

![Select preset filters](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image27.png)

##### Network Analyzer for Bluetooth LE and Mesh

This section describes how the Network Analyzer can be used for Bluetooth Low Energy and Bluetooth mesh traffic monitoring. The current version of the Bluetooth core specification supported is 5.2. The current version of Bluetooth mesh profile and model specification is 1.0.1.

Bluetooth Low Energy profile support is limited. Additionally, there is no support for Bluetooth LE random addresses resolving.

###### Network Analyzer for Bluetooth LE

This section reviews the capabilities of Network Analyzer for the Bluetooth LE protocol.

When Bluetooth Low Energy data is captured, Network Analyzer displays Bluetooth LE transactions and the corresponding events, as shown in the following figure.

![Network Analyzer displays](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image28.png)

It shows that related packets like requests and responses together make a transaction. These transactions are listed separately in the Transactions pane. To find the first packet of the transaction, simply click on the transaction. To see the details of the packet, simply click on the packet. You can see both the raw and the parsed format of the packet in the Hex Dump / Event Detail pane (see section [Interval Editor](03-network-analyzer-features#interval-editor) for more detail).

To disable the display of some transactions that are not of interest, use **Preference > Network Analyzer > Decoding > Transaction Grouper**.

The following figure shows an example of “BLE Advertisement Grouper”.

![Example of BLE Advertisement Grouper](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image29.png)

###### Bluetooth Low Energy Transaction Example (heading level 7)

![Bluetooth Low Energy Transaction Example](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image30.png)

The Event Detail pane allows you to inspect packets at various levels, down to radio data. The example above shows a description of a Bluetooth Low Energy connection being established between a central and peripheral.

When the feature exchange transaction is selected, the Event panes display the corresponding Bluetooth LE events. Scroll up in the Event pane to find the Connection Indication packet.

![The Event panes display](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image31.png)

The packets corresponding only to a particular Bluetooth LE connection can be filtered using the radio synchronization word. To do so, in the Radio info in the Event detail pane, right-click on “Sync word” and add to the filter.

Once the Bluetooth LE connection is established, ATT transactions can take place. The following example illustrates a “Read by Group Type” ATT request and the corresponding response. Use the Event Detail pane on the right side to inspect the content of the request..

![Inspect the content of the request](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image32.png)

After a Bluetooth Low Energy connection is established, the next step is typically the GATT discovery of the GATT Client. A dedicated view is available for that under **Preferences > Network Analyzer > Decoding > Bluetooth,** which lists all GATT services/characteristics/descriptors and handles, can be used. There, the ability to save the view is also provided.

For more information on how Bluetooth Low Energy operates and how it can be monitored with Network Analyzer, refer to the [Bluetooth LE connection](https://docs.silabs.com/bluetooth/2.13/general/connections/bluetooth-connection-flowcharts) and [GATT connection](https://docs.silabs.com/bluetooth/2.13/general/gatt-protocol/gatt-operation-flowcharts) flowcharts.

Additionally, the Event Difference pane can be used as a diffing tool between two different events. The following figure illustrates the event diff between a scan request and response.

![The event diff between a scan request and response](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image33.png)

###### Bluetooth Low Energy Data Decryption (heading level 7)

Network Analyzer decrypts Legacy encryption automatically. In effect, the keys are harvested from the Bluetooth LE traffic data. When packets are encrypted using Secure Connection on the other hand, they can only be decrypted when using the security manager of the Bluetooth Low Energy stack in debug mode. In the Silicon Labs Bluetooth Low Energy stack, this can be turned on using the following routine:

`sl_status_t sl_bt_sm_set_debug_mode(void)`

When using Secure Connections, this has the effect of having the Security Manager using debug keys. Those keys are also known by the Network Analyzer, which allows it to decrypt the Bluetooth LE data traffic.

To disable debug mode, restart the device. For more information, refer to the [Bluetooth API reference](https://docs.silabs.com/bluetooth/latest/sl-bt-sm).

###### Network Analyzer for Bluetooth Mesh

This section presents the capabilities of Network Analyzer for the Bluetooth mesh protocol. Network Analyzer offers the following features:

- Decryption of the Bluetooth mesh packets at all levels (network, application...)
- Handles Network-level segmentation / reassembly.
- Tracing packets from nodes out of RF reach from the PC (over Ethernet)
- Tracing packets from multiple nodes at once (several WSTKs connected over Ethernet)

As a reminder, Network Analyzer currently supports the Bluetooth mesh 1.0.1 profile and model specification. Support of Bluetooth mesh devices properties is limited. Provisioning Data PDUs cannot be decrypted and the map pane is not reliable.

###### Default IV Index Value (heading level 7)

A Bluetooth mesh live or recorded session that has a non-zero IV index will not be decrypted properly. This can be adjusted in the Bluetooth decoder (**Preferences > Network Analyzer > Decoding** > **Bluetooth**) by setting the default IV index value. The following figure illustrates this.

![Default IV Index Value](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image34.png)

Make sure to import the ISD capture file again to see the change being applied.

Note: More information on the IV index can be found in [IV Update in a Bluetooth Mesh Network](https://docs.silabs.com/btmesh/latest/btmesh-iv-update).

###### Keys (heading level 7)

The Bluetooth mesh stack is composed of several layers, starting from the network layer up to the access layer. Data traffic can be encrypted in various context (that is, stack layer levels):

- Network: Each Bluetooth mesh network has its associated network key. A node can have several network keys.
- Device: Each device in a particular network has its own device key.
- Application: Each application, depending on how it is configured, has its own application key.

For more detail on how Bluetooth mesh security and encryption work, refer to the Bluetooth mesh profile specification.

When building a Bluetooth mesh network using a smart phone application or a gateway, it should be possible to export the corresponding security keys. The security keys can correspond to any of the three types: network, device, or application. The provisioner should allow you to export the keys in a text format that can then be shared with other applications.

This is useful typically in the case of analyzing network traffic or rebuilding a network from scratch. Network Analyzer can import and export Bluetooth mesh keys. With the Silicon Labs Bluetooth mesh mobile application, a JSON text format is used for keys import/export.

The following steps indicates how to export keys using the Silicon Labs Bluetooth mesh phone application. Note that the steps are independent from the phone operating system, but the graphic layout of the smart phone application might differ.

1. Browse to the export menu.  
   ![Browse to the export menu](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image35.jpg)
2. Use the Export cryptographic keys button to create the corresponding JSON file. The JSON file called **MeshDictionary.json** can now be sent via email.  
   ![Create the corresponding JSON file](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image36.jpg)

This should make a menu open allowing the user to select by which mean it wished to send the **MeshDictionary.json** file.

The content of the (generated) **MeshDictionary.json** JSON file is human readable text and contains a collection of keywords and hexadecimal coded Bluetooth mesh keys.

The following steps indicates how to import the corresponding keys in Network Analyzer.

1. Go to **Preferences > Network Analyzer > Decoding > Security Keys**.  
   ![Import the corresponding keys](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image37.png)
2. Deselect all default and saved keys that are already present and click **Import…**
3. Browse to the MeshDictionary.json file.  
   ![Browse to the MeshDictionary.json file](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image38.png)
4. Click **Open** and see the keys imported in the “Security Keys“ window. For debugging purposes, the decryption keys can be saved in the ISD file (by checking the corresponding checkbox). This is not best practice from a security point of view but is acceptable for debugging. These instructions assume you have checked this.
5. Click **Apply and Close**.  
   ![Apply and Close](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image39.png)
6. After importing the keyfile, select **File > Other Network Analyzer Actions … > Reload** to refresh the data.
7. Finally, save the ISD file (checkbox in the bottom left of the security key dialog box).

The access layer Bluetooth mesh data should now be decrypted. The following sections show the expected result, in green on the top right corner of the figures.

###### Bluetooth Mesh Advertising Packets (heading level 7)

The Bluetooth mesh technology is based on Bluetooth LE advertising packets. Bluetooth mesh traffic is differentiated from the regular Bluetooth LE traffic through the AD types used by the Bluetooth mesh advertising packets. Network Analyzer can filter advertising packets in a number of ways.

The following AD types are used for advertising bearer-based Bluetooth mesh traffic:

<table>
    <thead>
        <tr>
            <th>AD Type value</th>
            <th>Data type name</th>
            <th>Reference for definition</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0x29</p>
            </td>
            <td>
                <p>PD-ADV</p>
            </td>
            <td>
                <p>Bluetooth Mesh Profile specification section 5.2.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x2A</p>
            </td>
            <td>
                <p>Mesh Message</p>
            </td>
            <td>
                <p>Bluetooth Mesh Profile specification section 3.3.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x2B</p>
            </td>
            <td>
                <p>Mesh Beacon</p>
            </td>
            <td>
                <p>Bluetooth Mesh Profile specification section 3.9</p>
            </td>
        </tr>
    </tbody>
</table>

Based on this information, Bluetooth mesh advertising packets can be filtered. The following filters can be entered in the filter bar:

- `bleAdv.adv_type_0 == 0x2b`. This shows only Bluetooth mesh beacons that are used essentially for provisioning and secure data information propagation (secure beacons). The following shows an example.  
  ![Shows only Bluetooth mesh beacons](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image40.png)
- `bleAdv.adv_type_0 == 0x2a`. Shows Bluetooth mesh messages. Bluetooth mesh messages are used for common Bluetooth mesh data traffic. The payload of those mesh advertising packets is called “Network PDUs” (specified by the Bluetooth mesh profile specification). “Network PDUs” are the containers of the Network layer data. This is very useful because it allows you to display only the data traffic using the advertising bearer on provisioned nodes in a network. The following figure shows an example:  
  ![Shows Bluetooth mesh messages](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image41.png)
- `bleAdv.adv_type_0 == 0x29`. This shows Bluetooth mesh provisioning advertising packets. Those packets use the PB-ADV provisioning bearer and are used to provision a device using “Provisioning PDUs”.

###### Proxy Protocol (heading level 7)

The Bluetooth mesh technology is mainly based on Bluetooth LE advertisement packets used along with Bluetooth mesh AD types. Nevertheless, in some cases, some devices are not able to advertise using the Bluetooth mesh AD types. As a consequence, the Bluetooth mesh specification allows communication over a GATT connection and uses what is called the Proxy protocol to exchange Network PDUs.

The proxy protocol is designed to enable nodes to send and receive Bluetooth mesh network packets over a connection-oriented bearer. As mentioned earlier, a node could support GATT but not be able to advertise the Bluetooth mesh Message AD Type. This node will establish a GATT connection with another node that supports the Bluetooth LE ATT bearer, called GATT bearer, and the advertising bearer, using the Proxy protocol to forward messages between these bearers.

> **Note**: The term "GATT bearer", in effect, corresponds exactly to the ATT bearer as specified in the Bluetooth Host specification (Bluetooth Core specification, Host Vol. 3, 3.2.11).

Once the Bluetooth LE connection is established, the node can send and receive what are called "Proxy PDUs". A Proxy PDU is essentially a data container for the following PDUs:

<table>
    <thead>
        <tr>
            <th>Type</th>
            <th>Name</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0x00</p>
            </td>
            <td>
                <p>Network PDU</p>
            </td>
            <td>
                <p>The message is a Network PDU as defined in Section 3.4.4 of the profile spec.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x01</p>
            </td>
            <td>
                <p>Mesh Beacon</p>
            </td>
            <td>
                <p>The message is a Bluetooth mesh beacon as defined in Section 3.9 of the profile spec.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x02</p>
            </td>
            <td>
                <p>Proxy Configuration</p>
            </td>
            <td>
                <p>The message is a proxy configuration message as defined in Section 6.5 of the profile spec.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x03</p>
            </td>
            <td>
                <p>Provisioning PDU</p>
            </td>
            <td>
                <p>The message is a Provisioning PDU as defined in Section 5.4.1 of the profile spec.</p>
            </td>
        </tr>
    </tbody>
</table>

The Network PDU corresponds to all messages handled at the "Network Layer".

Network Analyzer allows you to filter Bluetooth mesh GATT bearer data in a live (or recorded) network session. Based on this information, Bluetooth mesh packets can be filtered. The following filters can be entered in the filter bar:

- `btMeshProxy.type == 0x0`. This shows all Network layer traffic. This is the GATT bearer equivalent to filter Bluetooth mesh Messages on advertising bearer traffic. The following figure shows an example (note the application and network key data in green in the top right corner).  
  ![Shows all Network layer traffic](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image42.png)
- `btMeshProxy.type == 0x1`. This shows Bluetooth mesh beacons on GATT bearer. The following figure shows an example, and shows an example of the secure beacon:  
  ![Shows Bluetooth mesh beacons on GATT bearer](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image43.png)
- `btMeshProxy.type == 0x2`. This shows Proxy client and server configuration messages. Proxy configuration messages are used to configure the proxy filters. The proxy server uses a filter to decide whether to forward the message to the proxy client or not. In practice that filter is only useful in certain specific cases.
- `btMeshProxy.type == 0x3`. This shows Provisioning PDUs over the GATT bearer. This is the GATT bearer equivalent of filtering PB-ADV adverting packet on advertising bearer Bluetooth mesh traffic. The following figure shows an example:  
  ![Show Provisioning PDUs over the GATT bearer](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image44.png)

> **Note**: When using Bluetooth mesh, the node map may not be totally reliable. This is a known issue in Network Analyzer.

Alternatively, filtering can be done on both bearers using frame patterns. When selecting a packet containing Bluetooth mesh Network layer data, in the Event detail pane, right-click the Bluetooth mesh Network data of that packet and click **Filter by Frame Pattern**. This filters all Network messages regardless of the bearer. The same procedure can be done with Bluetooth mesh beacons and provisioning PDUs.

##### Bluetooth Mesh Networking and the Network Analyzer

In a Bluetooth mesh network, especially on the field, node access can be challenging. Even when accessible, all nodes might not have the PTI pins exposed allowing network monitoring.

This section describes briefly what techniques can be used to monitor the Bluetooth mesh traffic in such environments.

The Silicon Labs recommendation for this use case is to set up a WSTK-based proxy node. That would be, in effect, a dedicated sniffer node. The sniffer node does not need to run any particular model beyond the basics. It would only need to have the network key associated with the Bluetooth mesh network to decipher the traffic.

Using a mobile phone application, connect to the proxy sniffer node that would be used with the Network Analyzer to see the Bluetooth mesh traffic. That way, not only traffic on the advertising channels can be monitored but also data using the GATT bearer. This can be quite helpful when debugging issues that occur between the mobile phone application and the nodes.

![Set up a WSTK based proxy node](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image45.png)

Alternatively, a sniffer node can be created in a Bluetooth mesh network by simply loading a demo or sample application that is constantly scanning onto a WSTK-based Bluetooth LE device (i.e. an EFR32BG radio board mounted on a WSTK).

As an example, the soc-thermometer-host, constantly scanning for health thermometer server devices, would receive all Bluetooth mesh advertising-based PDUs. The fact that it is not a Bluetooth mesh node is not a problem as this can be recorded and decoded later on in Network Analyzer (see section [Network Analyzer for Bluetooth Mesh](04-network-analyzer-for-bluetooth-le-and-mesh#network-analyzer-for-bluetooth-mesh))

![Receive all Bluetooth mesh advertising based PDUs](/network-analyzer-with-ble-btmesh/0.1/images/sld716-image46.png)

Although this type of sniffer is very useful in the field, it has a couple of limitations: GATT bearer Bluetooth mesh data would not be sniffed and only packets within radio range will be caught. In practice, the latter can be mitigated if the sniffer node is close to a relay node.

Finally, a standalone Java-based packet trace tool exist that is worth mentioning. The data stream recorded can be decoded in Network Analyzer (and Wireshark) or can simply be stored in text or binary format. For more detail, refer to [Github](https://github.com/SiliconLabs/java_packet_trace_library).

### Bluetooth Mesh Models

#### Bluetooth Mesh Models

These links provide details on Bluetooth Mesh Lighting and Sensor models.

- [Understanding the Silicon Labs Bluetooth Mesh Sensor Model Demonstration in SDK v2.x](/btmesh/11.0.0/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher): describes the basics of sensor models and the related sample applications in the SDK.
- [Understanding the Silicon Labs Bluetooth Mesh SDK v2.x Lighting Demonstration](/btmesh/11.0.0/btmesh-sdk6-or-higher-lighting-demo): Describes the basics of Bluetooth Mesh required to understand the example, and walks through key aspects of the application source code.
- [Networked Lighting Control](/btmesh/11.0.0/btmesh-networked-lighting-control): Describes the following Networked Lighting Control (NLC) profiles: ambient light sensor, basic scene selector, dimming control, basic lightness controller, and occupancy sensor.

#### Understanding the Silicon Labs Bluetooth Mesh Sensor Model Demonstration in SDK v6.x

##### Understanding the Silicon Labs Bluetooth® Mesh Sensor Model Demonstration in SDK v6.x or Higher

> **NOTE**: **This section replaces _AN1300: Understanding the Silicon Labs Bluetooth® Mesh Sensor Model Demonstration in SDK v6.x or Higher_. Further updates to this application note will be provided here**.

The Bluetooth mesh SDK comes with two sample projects that create a wireless network of sensors and sensor clients using Bluetooth mesh technology. The examples assume use of Silicon Labs devices for sensors and sensor clients, and the Silicon Labs Bluetooth Mesh mobile app as provisioner. In this document we discuss the basics of sensor models and describe the related sample applications in the SDK.

###### Key Points

- Short introduction to Bluetooth mesh sensor model
- Using the sensor example application
- Sensor example application code walkthrough

##### Introduction

This document focuses on explaining the Bluetooth mesh sensor demo, installed as part of the Bluetooth mesh SDK. For the most part, the document centers on the example application and its usage flow, along with an explanation of a key part of the source code. It also includes a brief discussion of some concepts of the sensor model specification that are important for understanding the example.

###### Sensor Model

The sensor model is Bluetooth mesh’s method of interfacing with sensors. For a list of supported sensor types, refer to the Bluetooth Mesh Device Properties [specifications](https://www.bluetooth.com/specifications/specs/). This model is made up of sensor states including descriptors, settings, cadence, data, and series columns. This model also defines the messages used for setting and reporting these states between client and server.

**Sensor Descriptors**: The sensor descriptors define the sensor property ID, to indicate the device’s sensor type, the positive and negative tolerance of the sensor, the sampling function, the measurement period, and the update interval.

**Sensor Settings**: The sensor settings state controls the parameters of a sensor, such as sensitivity. The sensor setting property ID determines whether the sensor settings can be read and written as well as a raw setting’s size and content.

**Sensor Cadence**: The sensor cadence state controls how often the sensor data is published. Data can be published either through a trigger or a fast cadence. The trigger can be defined either by the sensor property ID or as a percentage change in the measured value. A fast cadence can be used if the measured valued falls within a specified range.

**Sensor Data**: The sensor data state is constructed of a sensor property ID and a raw value. Multiple instances are permitted.

**Sensor Series Column**: Sensor measurements may be organized as arrays, conceptually as columns of data. The sensor series column state is made up of a raw Y value, raw X value, and column width. The sizes and contents of each of these is determined by the sensor property ID.

###### Sensor Messages

Each state in the sensor model has an acknowledged get message and an unacknowledged status message associated with it. A client requests the status message by sending the get message. In addition, writable sensor states such as the cadence and setting states also have both acknowledged and unacknowledged set messages.

###### Sensor Server and Client

The defined models are the Sensor Client, Sensor Server, and Sensor Setup Server. In any element where the Sensor Server is present, the Sensor Setup Server must also be present to allow configuration.

##### Getting Started with the Sensor Model Applications

Two applications are required in order to use the Sensor Model demonstration: **Bluetooth Mesh - SoC Sensor Client** and **Bluetooth Mesh - SoC Sensor Thermometer**. The applications are provided both as prebuilt demo binary images, ready to download and use, and corresponding example projects that you can modify and then build for the target part.

![Modify and then build for the target part](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-demos-and-examples.png)

The precompiled demos are only available for a limited set of parts, including selected EFR32xG13, xG21, xG24 and xG27 parts, and BGM13 and BGM220 modules. The examples can be built for any part supported by the Bluetooth Mesh SDK.

> **Note**: EFR32xG22 parts have limited support for Bluetooth Mesh (only LPN is supported).

This chapter describes how to start the mesh sensor model demonstration from either the precompiled demos, or from binaries that you build from the example projects.

###### Requirements

The following is required to run the demo.

- To see the complete demo in action, two mainboards with a supported board installed, one used for the Client and one for the Server
- [Simplicity Studio 5](https://www.silabs.com/developers/simplicity-studio)
- Bluetooth Mesh SDK 6.0.0 or later, distributed through Simplicity Studio 5. The prebuilt demos and examples are included in the SDK.
- [Silicon Labs Bluetooth Mesh Mobile Application](https://www.silabs.com/software-and-tools/bluetooth-mesh-mobile-app)  
  - Used for discovering and provisioning devices.  
  - Includes network, group, and publish-subscribe setup.  
  - Allows device configuration for the sensor models.

Example projects and additional code development can be done with GCC (supplied with Simplicity Studio 5), IAR EWARM, or command line tools.

Simplicity Studio has a network analyzer capable of capturing and decoding Bluetooth mesh packets. See [Using Network Analyzer with Bluetooth® Low Energy and Mesh](/btmesh/11.0.0/network-analyzer-with-ble-btmesh).

###### Starting with the Precompiled Demos

Open Simplicity Studio 5 with a compatible SoC wireless kit connected to the computer. Select the part in Debug Adapters view to open the Launcher perspective. Click the **Example Projects & Demos** tab. To see only the Bluetooth Mesh demos, turn off the Example Projects and Solution Examples, and set the Bluetooth Mesh checkbox. Next to either **Bluetooth Mesh - SoC Sensor Client** or to **Bluetooth Mesh - SoC Sensor Thermometer**, click **RUN**.

![Set the Bluetooth Mesh checkbox](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-demos-and-examples.png)

Connect your other device and repeat with the other application.

###### Starting with Example Projects

This section summarizes how to start the demonstration from example projects. See _QSG176: Bluetooth® Mesh Quick-Start Guide for SDK v2.x and v3.x_ for an introduction to configuring and building your own projects, and for a guide to additional resources.

Open Simplicity Studio 5 with a compatible SoC wireless kit connected to the computer. Select the part in Debug Adapters view to open the Launcher perspective. Click the **Example Projects & Demos** tab. Under Technology Type, filter on **Bluetooth Mesh**. Next to the **Bluetooth Mesh - SoC Sensor Client** project, click **Create**.

![Open the Launcher perspective](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-sample-selection2.png)

Modify project settings, and click **Finish** to create the project. Select the project .slcp file if it is not already selected, click the **Software Components** tab, and expand the Bluetooth Mesh components group to see the installed features.

![See the installed features](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-mesh-components2.png)

Project files autogenerate, with progress reflected in the lower right of the Simplicity IDE. Build and flash the project. Connect your other device and repeat for the **Bluetooth Mesh - SoC Sensor Thermometer** example.

For more information on how to configure a node in the Bluetooth Mesh SDK v6.x., refer to _UG472: Bluetooth® Mesh Stack and Bluetooth® Mesh Configurator User's Guide for SDK v2.x and Higher_.

##### Bluetooth Mesh Sensor Demonstration

###### Mesh Network Implementation

The demonstration implementation process can be divided into four main phases:

1. Unprovisioned mode: After the demo firmware is installed, the device starts in unprovisioned mode.
2. Provisioning: The devices are provisioned to a Bluetooth mesh network and network security is set up.
3. Configuration: The group, publish, and subscribe, and application security are configured.
4. Normal operation: The sensor server(s) can be controlled by the client(s).

In the first phase, all the devices are unprovisioned and transmitting unprovisioned beacons. They do not have any network keys or application keys configured, and publish and subscribe settings are not set. In this state, the devices are simply waiting for the provisioner to assign them into a Bluetooth mesh network, and configure publish and subscribe settings and mesh models. In this state, the devices can be detected by the smartphone application.

In the provisioning phase, the provisioner adds sensor servers and clients to the Bluetooth mesh network. A network key is generated and distributed to the nodes and each node is assigned a unicast address.

In the configuration phase, the provisioner configures groups, publish, and subscribe settings; generates application keys; and binds mesh models to application keys.

After provisioning and configuration, the Bluetooth mesh network is operational, and clients can be used to configure and request data from the sensors.

###### Running the Example

This section assumes you have installed the **BT Mesh – Sensor Client Example** demo binary to one of the devices and the **BT Mesh – Sensor Thermometer Example** to the other.

- Provision and configure the sample apps using the Silicon Labs Bluetooth Mesh mobile application as described in _QSG176: Bluetooth® Mesh Quick-Start Guide for SDK v2.x and v3.x_.
- Open a serial console in Simplicity Studio for each. If you reset the devices, this is what you will observe on the console for the client and server before provisioning:

![Observe on the console](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-image1.png)

![Observe on the console](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-image2.png)

- And this is what you will see in the device display for the client and server, respectively:

|![Device display for the client and server](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-l1.png)|![Device display for the client and server](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-r1.png)|
|---|---|

- After provisioning, the displays should be as below:

|![Displays after provisioning](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-l2.png)|![Displays after provisioning](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-r2.png)|
|---|---|

- Press PB0 on the client device to select the temperature sensor. Now the LCD on the client device will display the temperature reported by the server. Pressing it again will show the people count and lightness (these are not added to the server side, but can be installed as a component and configured):

|![Show the people count and lightness](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-l3.png)|![Show the people count and lightness](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-c3.png)|![Show the people count and lightness](/understanding-bluetooth-mesh-sensor-model-demo-sdk-6x-and-higher/10.0.0/images/sld813-r3.png)|
|---|---|---|

##### Code Walkthrough

As of BT Mesh SDK v6.x, the code structure of both the stack API and the code examples have been reworked. The Bluetooth Mesh API now abstracts away much of the event handling in generated files and allows the user to focus on application development. Much functionality is now hidden in the components, making the user application simpler.

The sections below describe the code in the application source of the examples (app.c and components).

###### Unprovisioned Mode, Provisioning, and Configuration

In unprovisioned mode, both examples behave the same way. The unprovisioned device simply starts sending unprovisioned beacons and waits for a provisioner to provision and configure it.

When the `app_init` is being called, the application checks if a button is pressed in the `handle_reset_conditions` function. If yes, depending on the pressed button(s), it calls either the function `sl_btmesh_initiate_full_reset()`, which halts the system and performs a factory reset by erasing the NVM3 storage, or the function `sl_btmesh_initiate_node_reset()`, which does the same, except performs full NVM storage erasure. The factory reset is also done after receiving a node_reset event (`sl_btmesh_evt_node_reset_id`). This is handled within the Factory Reset component. If no button is pressed, then the name of the device is set based on the Bluetooth address, within the function `sl_btmesh_provisionee_on_init()`, when it is called to signal the initialization of the Bluetooth mesh node stack.

The callback `sl_btmesh_provisionee_on_init()` indicates that the Bluetooth mesh node stack initialization is complete. In the background, the `sl_btmesh_evt_node_initialized_id` is being handled within the Provisionee component. The application first checks the provisioning status. If the node is not provisioned (the default state when the device is first powered up after programming), then the application starts unprovisioned beaconing by calling `sl_btmesh_node_start_unprov_beaconing()`.

The API call `sl_btmesh_node_start_unprov_beaconing()` takes one parameter (bearer) that selects which bearers are used (PB-ADV, PB-GATT, or both). In this example, both bearers are used. Because the PB-GATT bearer is enabled, the device will begin advertising its provisioning GATT service. This allows the smartphone application to detect unprovisioned nodes.

When unprovisioned beaconing has been started the application waits for the provisioner (in this case, the smartphone app) to start provisioning. Start of provisioning is indicated with the event `sl_btmesh_evt_node_provisioning_started_id` (see `sl_btmesh_provisioning_decorator.c`). This is handled in the application code through the `sl_btmesh_on_node_provisioning_started()`callback.

During provisioning, no actions are required from the user application. The configuration of network keys and other operations are handled automatically by the Bluetooth mesh stack. Both the sensor server and client applications simply start blinking the two LEDs on the WSTK to indicate that provisioning is in progress. Then they wait for the event `sl_btmesh_evt_node_provisioned_id` (see `sl_btmesh_provisioning_decorator.c` for more details) that indicates provisioning is complete. This is handled in the application code through the `sl_btmesh_on_node_provisioned()`callback.

###### Sensor Thermometer Example

This section describes basic operation of the **Bluetooth Mesh – SoC Sensor Thermometer**. It is assumed that the node is already provisioned and publish-subscribe settings have been configured by the smartphone app.

The sensor server may support multiple types of sensors present on the development board, such as a People Count sensor, or the Present Ambient Temperature sensor. The People Count sensor can be simulated by the buttons on the starter kit: PB0 decreases the count and PB1 increases the count, or via cli implementation. The count is maintained in a 16-bit unsigned integer. The Present Ambient Temperature sensor is a Silicon Labs Si7021. Temperature is reported in units of 0.5 degrees Celsius as a signed 8-bit integer.

Upon receiving the `sl_btmesh_evt_node_initialized_id` event and call to the corresponding callback `sl_btmesh_handle_sensor_server_events()`, the sensor server node initializes the sensors by calling `sl_btmesh_sensor_server_node_init()`. This occurs in the `btmesh_sensor_server` component (see `sl_btmesh_sensor_server.c`). This function sets the people count to 0 and initializes the temperature sensor hardware. Otherwise, the node starts unprovisioned beaconing and waits for a provisioner. Once provisioned and initialized, the sensor server node simply waits for messages from the client. Events generated by messages from the client are handled in the `sl_btmesh_sensor_server.c`.

Please note that sensor settings and cadence are not supported at this time so the message handlers are stubs.

- Get requests are handled by `handle_sensor_server_get_request()`. The property_id is queried. If the value is non-zero and is a supported value then the sensor data for that property is returned. If the property_id is zero, then all supported sensor data is returned. If the value is non-zero and is an unsupported value, the data length is set to zero to indicate an unsupported property. In all cases, `sl_btmesh_sensor_server_send_status()` is called to send the status to the client.
- Get Series requests are handled by `handle_sensor_server_get_series_request()`. Neither sensor properties supported in this example include either Series State so only the property_id is sent back to the client .
- Get Column requests are handled by `handle_sensor_server_get_column_request()`. Neither of the sensor properties include Column State so the same data is sent back to the client, per the specification.
- Publishing sensor data is handled by `handle_sensor_server_publish_event()` when the publish period expires. Data from both sensors is published.
- The Cadence and Settings States for the properties in this example are not included so their handlers simple return the property ID, per the specification.

###### Sensor Client Example

This section describes basic operation of the **Bluetooth Mesh – SoC Sensor Client**. It is assumed that the node is already provisioned and publish-subscribe settings have been configured by the smartphone app. The main purpose of the sensor client is to request sensor data from the sensor server. The sensor client supports two types of sensors: a people counting sensor and a temperature sensor.

Upon receiving the`sl_btmesh_evt_mesh_node_initialized_id` event, the sensor client node performs the following actions:

- Initializes the sensor client model by calling `sl_btmesh_sensor_client_init().`
- Handles the buttons on the device through calling `app_button_press_cb()`.
- Requests a sensor descriptor by calling `sl_btmesh_sensor_client_get_descriptor()` with address 0x0000 to publish the message using the publish parameters set by the configuration client.
- Starts a timer to periodically request sensor data.

The device buttons are used as follows:

- PB0 to select the sensor property_id to interact with.
- PB1 to reset the list of registered devices.

When PB0 is pressed, `sensor_client_change_current_property()` is called to handle the change. This function increments the variable current_property, which is used to index the properties array containing a list of the supported properties.

When PB1 is pressed `update_registered_devices()` is called to find and register the devices that support the currently selected property. This is done by calling `sl_btmesh_sensor_client_get_descriptor()` with the selected property as a parameter. A recurring timer is started with a 2000 ms interval. This timer is used to request the sensor data by calling `sl_btmesh_sensor_client_get_sensor_data()`.

When a message is received from a sensor server, one of the sensor events are triggered. These events are as follows:

|Event|Description|Behavior|
|---|---|---|
|sl_btmesh_evt_sensor_client_descriptor_status_id|Indicates that a descriptor status message has been received.|Adds the server to the list of registered devices if it was not previously registered.|
|sl_btmesh_evt_sensor_client_status_id|Indicates that a sensor status message has been received.|Verifies that the data came from a registered device, determines which type of sensor the data comes from, then saves and displays it.|

#### Lighting Demonstration for SDK v6.x and Higher

##### Understanding the Silicon Labs Bluetooth® Mesh SDK v6.x or Higher Lighting Demonstration

**NOTE: This section replaces _AN1299: Understanding the Silicon Labs Bluetooth® Mesh SDK v6.x or Higher Lighting Demonstration_ for Simplicity SDK 2024.12.2 and up. Further updates to this application note will be provided here.**

The Bluetooth Mesh SDK comes with example projects that creates a wireless network of lights and switches using Bluetooth Mesh technology. These pages assume the usage of Silicon Labs WSTKs for switches and lights and an Android or iOS mobile phone for provisioning and controlling the network. We discuss the basics of Bluetooth Mesh required to understand the example, and walk through key aspects of the application source code.

This demonstration assumes you have read the [QuickStart Guide for SDK v4.x and Higher](/btmesh/11.0.0/btmesh-getting-started-overview), installed the Bluetooth Mesh SDK, and successfully run the examples.

![Bluetooth LE and Mesh Stacks and Supported Topologies](/btmesh-sdk6-or-higher-lighting-demo/10.0.0/images/an1299-image1.png)

This demonstration explains the Bluetooth Mesh lighting demo, installed as part of the Bluetooth Mesh SDK. It focuses on the example application and its usage flow, explaining key parts of the source code and the Silicon Labs Bluetooth Mesh mobile application. It also introduces some concepts of the specification that are important for understanding the example.

There are different light sources with different capabilities. If a light source is a tuneable white, the CTL Model can control its light intensity, color temperature and Delta UV. The SoC Light CTL example, which demonstrates these types of light sources, is described in this document. There are also color-changing lights, where the HSL Model can control the Hue, Saturation, and Lightness to describe the quality of the light. Although the SoC Light HSL example demonstrates these types of light sources, this example is out of scope for this document. There is also a BT Mesh Lighting standard, called Networked Lighting Control (NLC), which defines profiles for the various roles in the lighting network. Each of these profiles are also demonstrated by NLC examples. These examples are not in scope for this document but are described in [Networked Lighting Control](/btmesh/11.0.0/btmesh-networked-lighting-control). In this document, BT Mesh SoC Light CTL nodes will be referred to as light nodes, and BT Mesh SoC Switch CTL Nodes will be referred to as switch nodes.

The following subsections briefly go through the relevant aspects of the Bluetooth Mesh technology. Section [Bluetooth Mesh Lighting Demonstration](02-bluetooth-mesh-lighting-demonstration) describes the features and functions of the Lighting Demonstration, section [Network Analyzer](03-network-analyzer) describes using Network Analyzer for packet capture, and section [Bluetooth Mesh Stack and Application for Smartphones](04-bluetooth-mesh-stack-and-application-for-smartphones) focuses on the mobile application.

###### Bluetooth Mesh

Bluetooth Mesh is a networking technology available for Bluetooth LE devices and applications. Previously Bluetooth devices have been using point-to-point connectivity or broadcasting topologies to communicate with other devices. Bluetooth Mesh extends that and allows both many-to-many device communications and using Bluetooth devices in a mesh topology. This enables multi-hop communications between Bluetooth devices and much larger-scale Bluetooth device networks than has previously been possible.

Bluetooth Mesh uses Bluetooth LE advertising channels to send and receive messages between the Bluetooth Mesh nodes, but it can also use Bluetooth connections and GATT services to communicate with devices that do not natively support Bluetooth Mesh.

Bluetooth Mesh also uses its own security architecture, which is separate from the normal Bluetooth LE security architecture, although the same AES-CCM 128-bit and Elliptic Curve Diffie Hellman (ECDH) security algorithms are used.

Bluetooth Mesh also defines its own application layer called mesh model which is different than the GATT-based profiles and services that non-mesh Bluetooth LE devices use. The new application layer was defined to address the requirements and needs of mesh-based topologies and also to make Bluetooth Mesh a full stack solution and enable interoperable mesh devices to be built.

###### Bluetooth Mesh Network Roles and Node Features (heading level 7)

The Bluetooth Mesh network typically consists of multiple nodes. All nodes can transmit and receive mesh messages, but they can optionally also support one or more additional features. If a node does not implement any of the additional features, it is considered just a node. Various node types are illustrated in the following figure.

![Node Types](/btmesh-sdk6-or-higher-lighting-demo/10.0.0/images/an1299-image2.png)

The four types of specified node features are as follows:

- **Proxy feature**: Enables message proxy between Bluetooth Mesh and GATT, and enables devices such as smartphones to connect to Bluetooth Mesh.
- **Relay feature**: Relays messages to extend the range and scale of a Bluetooth Mesh network.
- **Friend feature**: Implements an additional message cache to support nodes with the low power feature.
- **Low power feature**: Allows sleeping and polling of messages from friend nodes at known time intervals.

For further information on these features and Bluetooth Mesh technology, please go to the Silicon Labs [Bluetooth Mesh learning center](https://www.silabs.com/wireless/bluetooth/bluetooth-mesh).

###### Provisioning (heading level 7)

Provisioning refers to the operation where devices that are not part of any Bluetooth Mesh network are transformed into nodes that are part of one or more Bluetooth Mesh networks. For example, provisioning happens when a new light bulb is installed and taken into use, so it can be controlled by switches or dimmers.

Provisioning is mainly a security process where the first level security keys are generated by the provisioner and transferred to the device that is being provisioned to make it part of a Bluetooth Mesh network.

The provisioning process begins when a device starts to send unprovisioned Bluetooth beacon packets and the provisioner receives them. The provisioner then initiates the provisioning process, the devices exchange public keys, and both generate session keys. The session keys are used to secure the session, in the transfer of the actual network key, and the rest of the provisioning process. After provisioning, each device, now a node in the network, has the network key, a security parameter called the IV index, and its unicast address.

###### Publish and Subscribe (heading level 7)

In Bluetooth Mesh, communication to a group of devices is typically implemented through a publish and subscribe mechanism. This is an easy-to-understand concept which also simplifies the setup of Bluetooth Mesh networks and adding and reconfiguring nodes.

Usually the Bluetooth Mesh nodes are configured into groups, which may represent their physical location (kitchen or living room) or specific function (lights or window coverings). Usually the devices are also controlled as groups, so the same message is sent to all devices in a group. To accomplish this functionality, Bluetooth Mesh uses a concept called publish – subscribe, where nodes, such as lights, subscribe to messages groups and nodes, like switches, publish messages to those groups. At the network layer, each group is assigned a group address, and multicast messaging is used to send the messages to all devices in a specific group.

![Publish and Subscribe](/btmesh-sdk6-or-higher-lighting-demo/10.0.0/images/an1299-image3.png)

The benefit of publish and subscribe is that, when a new node is added or an existing node is removed or replaced, only that node needs to be provisioned and configured.

##### Bluetooth Mesh Lighting Demonstration

###### Requirements

- [Simplicity Studio](https://www.silabs.com/developers/simplicity-studio)  
  - Bluetooth Mesh SDK 6.0.0 or later, distributed through Simplicity Studio 5.  
  - The pre-built demo binaries and source code are included in the SDK.  
  - Simplicity Studio has a Network Analyzer capable of capturing and decoding Bluetooth Mesh packets.  
  - The actual code development can be done with Simplicity Studio, IAR EWARM, or command line tools.
- [Silicon Labs Bluetooth Mesh mobile application](https://www.silabs.com/developers/bluetooth-mesh-mobile-app)  
  - Available for both iOS and Android.  
  - Used for discovering and provisioning devices over GATT.  
  - Includes network, group, and publish-subscribe setup.  
  - Allows device configuration and control.  
  - Requires iOS 14 or later ([https://apps.apple.com/us/app/bluetooth-mesh-by-silicon-labs/id1411352948](https://apps.apple.com/us/app/bluetooth-mesh-by-silicon-labs/id1411352948)).  
  - Requires Android 11 (API30) or later ([https://play.google.com/store/apps/details?id=com.siliconlabs.bluetoothmesh&hl=en](https://play.google.com/store/apps/details?id=com.siliconlabs.bluetoothmesh&hl=en)).
- For the full experience, at least three [Silicon Labs Blue Gecko SoC Wireless Starter Kits](https://www.silabs.com/development-tools/wireless/efr32xg21-wireless-starter-kit?tab=overview) are needed.  
  - 2 kits are used as lights with proxy feature.  
  - 1 kit is used as a switch.  
  - EFR32xG27, EFR32xG24, EFR32xG21, and EFR32xG22 SoCs as well as the BGM220P and BGM220S modules support Bluetooth Mesh software. Note that EFR32xG22, BGM220P, and BGM220S only support limited Bluetooth Mesh features.

See the [QuickStart Guide for SDK v4.x and Higher](/btmesh/11.0.0/btmesh-getting-started-overview) for more information on obtaining required hardware and software, and running the demonstration.

The demonstration setup can, in principle, consist of any number of switch nodes and light nodes. A single switch node can control an arbitrary number of light nodes by sending commands to a group address. Similarly, a light node can receive on/off commands from multiple switches.

###### Mesh Network Implementation

The demonstration implementation process can be divided into four main phases as follows:

1. Unprovisioned mode: After the demo firmware is installed, the device starts in unprovisioned mode.
2. Provisioning: The devices are provisioned to a Bluetooth Mesh network and network security is set up.
3. Configuration: The group, publish and subscribe, and application security are configured.
4. Normal operation: The light node(s) can be controlled by the switch node(s) and the smartphone application.

In the first phase, all the devices are unprovisioned and transmitting unprovisioned beacons. They do not have any network keys or application keys configured, and publish and subscribe settings are not set. In this state, the devices are simply waiting for the provisioner to assign them into a Bluetooth Mesh network and to configure publish and subscribe and mesh models. In this state, the devices can be detected by the smartphone application.

In the provisioning phase, the provisioner adds lights and switches to the Bluetooth Mesh network. A network key is generated and distributed to the nodes, and each node is assigned a unicast address.

In the configuration phase, the provisioner configures groups, publish and subscribe settings, application-level security, and mesh models.

After provisioning and configuration, the Bluetooth Mesh network is operational, and switches can be used to control the lights. The WSTK switch’s buttons can be used to control all the lights in a group. The same functionality can be done with the smartphone application, and it can also control individual lights using unicast addressing.

###### Code Walkthrough

The Bluetooth Mesh SDK includes light and switch example projects, named **Bluetooth Mesh – SoC Light CTL** and **Bluetooth Mesh – SoC Switch CTL**. Both examples are implemented using the same event-driven architecture that is used in plain Bluetooth (non-mesh) applications.

For information about Bluetooth C application development, see [Silicon Labs Bluetooth C Application Developer's Guide for SDK v7.x and Higher](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x/).

###### Unprovisioned Mode, Provisioning, and Configuration (heading level 7)

In unprovisioned mode, both light and switch examples behave the same way. The unprovisioned device simply starts sending unprovisioned beacons and waits for a provisioner to provision and configure it.

When the `app_init` is called, the application checks if a button is pressed in the `handle_reset_conditions` function. If yes, -depending on the pressed button(s)- it calls either the function `sl_btmesh_initiate_full_reset()`, which halts the system and performs a factory reset by erasing the NVM3 storage, or the function `sl_btmesh_initiate_node_reset()`, which does the same, except full NVM storage erasure. The factory reset is also done after receiving a `node_reset` event (`sl_btmesh_evt_node_reset_id`). This is handled within the Factory Reset component. If no button is pressed, then the name of the device is set based on the Bluetooth address, within the function `sl_btmesh_provisionee_on_init()`, when it is called to signal the initialization of the Bluetooth Mesh node stack.

The callback `sl_btmesh_provisionee_on_init()` indicates that the Bluetooth Mesh node stack initialization is complete. In the background, the `sl_btmesh_evt_node_initialized_id` is handled within the Provisionee component. The application first checks the provisioning status. If the node is not provisioned (the default state when the device is first powered up after programming), then the application starts unprovisioned beaconing by calling `sl_btmesh_node_start_unprov_beaconing()`.

The API `sl_btmesh_node_start_unprov_beaconing` takes one parameter (`bearer`) that selects which bearers are used (PB-ADV, PB-GATT, or both). In this example, both bearers are used. Because the PB-GATT bearer is enabled, the device will begin advertising its provisioning GATT service. This allows the smartphone application to detect unprovisioned nodes.

When unprovisioned beaconing has been started, the application waits for the provisioner (in this case, the smartphone app) to start provisioning. The start of provisioning is indicated with the event `sl_btmesh_evt_node_provisioning_started_id`. When this event is raised, the callback function `sl_btmesh_on_node_provisioning_started()` is called.

During provisioning, no actions are required from the user application. The Bluetooth Mesh stack automatically handles network key configuration and other operations. Both the light and the switch application simply start blinking the two LEDs on the WSTK to indicate that provisioning is in progress. Then they wait for the event `sl_btmesh_evt_node_provisioned_id` that indicates provisioning is complete. When this event is raised, the callback function `sl_btmesh_on_node_provisioned()` is called.

Initialization of the Application:

![Initialization of the Application](/btmesh-sdk6-or-higher-lighting-demo/10.0.0/images/an1299-image4.png)

The next step after provisioning is configuration of the node. As explained in the [QuickStart Guide for SDK v4.x and Higher](/btmesh/11.0.0/btmesh-getting-started-overview), the smartphone app is used to configure a node either as a switch or a light and assign it to a group. The configuration procedure consists of following steps:

- Provisioner distributes an application key to the node.
- The application key is bound to the selected Bluetooth Mesh model.
- Publish address and settings are configured.
- Subscribe address and settings are configured.

The configuration phase is mostly handled between the Bluetooth Mesh stack and the provisioner and it does not require any involvement from the user application in the node. The following events are generated by the stack to give status information about the ongoing configuration:

- sl_btmesh_evt_node_key_added_id: generated when the provisioner has sent a new key (network or application)
- sl_btmesh_evt_node_model_config_changed_id: indicates that the provisioner has modified configuration of the local model (either publish or subscribe settings changed)

Up to this point, the code in the examples **Bluetooth Mesh – SoC Light CTL** and **Bluetooth Mesh – SoC Switch CTL** is almost identical.

###### Switch Node Example (heading level 7)

This section describes basic operation of the **Bluetooth Mesh – SoC Switch CTL** example. It is assumed that the node is already provisioned and publish - subscribe settings have been configured by the smartphone app. The switch node has one simple task: listen for push-button presses and -based on the button press length- control the brightness, color temperature, or on/off state of the lights in the group. Short button presses (less than 250 ms) are used to adjust light brightness up (PB1) and down (PB0). Medium button presses (more than 250 ms and less than 1 s) are used to adjust light color temperature up (PB1) and down (PB0). A long press (more than 1 s and less than 5 s) or a very long press (more than 5 s) recalls the previous light lightness (PB1) or turns the light off (PB0).

The on/off control, the brightness control and the color temperature control uses the **Light CTL Client** model. The switch example also demonstrates the **Low Power Node** (LPN) feature. When the switch is provisioned into the network, it will start looking for a friend so that it can enter low-power mode. When a friendship is established, the switch can go to deep sleep, and it will wake up periodically to poll the friend node for any incoming messages.

Upon receiving the `sl_btmesh_evt_node_initialized_id` event, the Generic Client Models, the Lightness Client, the CTL Client components, and the mesh library are initialized. The **Low Power Node** (LPN) feature is then initialized and configured. After the LPN feature is initialized, the callback function `sl_btmesh_lpn_on_init()` is called and the application displays “LPN on” on the WSTK LCD. The LPN configuration has five parameters: `lpn_queue_length`, `lpn_poll_timeout`, `lpn_receive_delay`, `lpn_request_retries`, and `lpn_retry_interval`. The settings of these parameters are defined in `sl_btmesh_lpn_config.h` as

- `SL_BTMESH_LPN_MIN_QUEUE_LENGTH_CFG_VAL`
- `SL_BTMESH_LPN_POLL_TIMEOUT_CFG_VAL`
- `SL_BTMESH_LPN_RECEIVE_DELAY_CFG_VAL`
- `SL_BTMESH_LPN_REQUEST_RETRIES_CFG_VAL`
- `SL_BTMESH_LPN_RETRY_INTERVAL_CFG_VAL`

respectively. After that, the node starts finding a friend node. The LPN feature status is displayed on the WSTK LCD display.

The LPN feature is mostly implemented in the mesh stack, so only a few informative events can be raised to the application through corresponding callback functions:

- `sl_btmesh_lpn_on_friendship_established`: A friendship was successfully established. The application displays “LPN with friend” on the WSTK LCD.
- `sl_btmesh_lpn_on_friendship_failed`: The Friendship establishment failed. The application displays “No friend” on the WSTK LCD, and the node tries to establish a friendship again in 2 seconds.
- `sl_btmesh_lpn_on_friendship_terminated`: The friendship was terminated for some reason. The application displays “Friend lost” on the WSTK LCD, and the node tries to establish a friendship again in 2 seconds.

If a GATT connection is opened, the friendship is terminated and the LPN is de-initialized. In this case, the callback function `sl_btmesh_lpn_on_deinit()` is called, and the application displays “LPN off” on the WSTK LCD. After all GATT connections are closed, the LPN feature is re-initialized.

The `sl_btmesh_ctl_client_set_lightness()` function (used in the example) changes the lightness level and sends its value to the server for short button presses. Short presses are used to adjust light brightness up and down. The application sends a request using the **Light CTL Client** model. The last level that has been set is stored in a variable (type `uint16`), and the level is adjusted up or down each time a short button press is detected. Sending a single request is implemented in `send_ctl_request()`, detailed below.

A similar function (but just for lightness) is `sl_btmesh_set_lightness()`. Here, sending a single light lightness request is implemented in function `send_lightness_request()`, which is very similar to the `send_onoff_request()` that can be used for on/off requests. All of these use the same API `mesh_lib_generic_client_publish()` to publish the request. The differences are in the model ID that is passed as argument and the parameter data type.

The `sl_btmesh_ctl_client_set_temperature()` function changes the color temperature and sends its value to the server for medium button presses. Medium presses are used to adjust light color temperature up and down. The application sends a request using the **Light CTL Client** model. The last temperature that has been set is stored in a variable (type `uint16`), and the temperature is adjusted up or down each time a medium button press is detected.

Sending a single light CTL request is implemented in function `send_ctl_request()`, which is very similar to `send_lightness_request()` that can be used for light brightness requests. Both of these use the same API `mesh_lib_generic_client_publish()` to publish the request. The differences are in the model ID that is passed as argument and the parameter data type.

Sending a single on/off request is implemented in the function `send_onoff_request()`. A soft timer is used to trigger three calls to `send_onoff_request()` with a 50 ms delay between each call. In the example, the on-off functionality is implemented with the help of the `sl_btmesh_ctl_client_set_lightness()` function.

The mesh stack API used to send one on/off transaction is `mesh_lib_generic_client_publish()`. This is a common API used to publish data for several client models. It is not limited to the generic on/off client only. For example, publishing data as a generic transition time client would be done using the same API. The first parameter `model_id` selects which model is being used.

In addition to the desired on/off status, the publish API has some additional parameters such as **transaction identifier**, **transition time**, and **delay**.

The transaction identifier is a running number that is incremented for each transaction. In this example, each on/off state change triggers three consecutive on/off requests. The transaction identifier is the same for each of these requests so that, at the receiving end, duplicate requests can be filtered out. In other words, all three published messages are part of the same transaction, and they will trigger only one event at the receiving light node.

The delay parameter can be used to indicate that the on/off transition should not be executed immediately but after a given delay. In this example, the delay parameter is set to values of 100 ms/50 ms/0 in the first, second, and third request, respectively. The purpose is to ensure that all lights in the target group change their state simultaneously, regardless of which of the three on/off requests was captured on the receiving side.

The application code that implements the light switch functionality is relatively simple because many aspects are automatically handled by the mesh stack. For example, the switch node does not need to know anything about the light nodes that it is controlling. Any number of light nodes can be subscribed to the ctl requests that are published by the switch node.

The switch node does not need to know the group address that has been configured by the provisioning application. It simply publishes the ctl requests using the API `mesh_lib_generic_client_publish()`, and the stack automatically sends the requests using the group address that has been configured by the provisioner.

###### Light Node Example (heading level 7)

This section describes basic operation of the **Bluetooth Mesh – SoC Light CTL** example. It is assumed that the node is already provisioned and that the publish and subscribe settings have been configured by the smartphone app.

The main feature of the light node is that the development kit LEDs are turned on or off based on the requests that are received from switch nodes or from the smartphone application. The brightness of the LEDs can also be controlled. The On/off control is based on the Bluetooth Mesh Generic OnOff model, and the brightness control is based on the Light Lightness model. The Light CTL model supports color temperature requests, as well as lightness. Color temperature changes are shown on the WSTK LCD display. The light node also supports the friend feature. It can establish a friendship with a low-power switch node in the network so that the switch node can enter low-power mode.

The light node supports the following states:

- Generic OnOff
- Generic Level
- Generic OnPowerUp
- Generic Default Transition Time
- Light Lightness
- Light CTL

Upon receiving the `sl_btmesh_evt_node_initialized_id` event, the Generic Server, the Lightness Server, the CTL Server, and the mesh library are initialized. The mesh library is an adaptation layer between the mesh stack and the application code that enables using multiple models with a small set of generic API calls.

To support all the states listed above, the light node must store its internal state permanently so that it is preserved over reboots and power cycles. The Lighting Server holds Generic and Light Lightness states in the `lightbulb_state` struct. The Light CTL Server holds Light CTL states in the `lightbulb_state` struct as well. The state information is also held in the stack.

The light state initialization is implemented in `sl_btmesh_lighting_server_init()` and `sl_btmesh_ctl_server_init()`. The `onpowerup` state enables configuration of the default state after power is applied to the light node. The possible settings are listed below.

|onpowerup state|Description (light node)|
|---|---|
|MESH_GENERIC_ON_POWER_UP_STATE_OFF|Light is off after power up|
|MESH_GENERIC_ON_POWER_UP_STATE_ON|Light is on after power up|
|MESH_GENERIC_ON_POWER_UP_STATE_RESTORE|The state before light was powered down is restored at next power up|

The transition time model makes it possible to configure how long it takes for the light to transition from one state to another.

The `lightbulb_state` struct in the Lighting Server contains the following fields.

|Struct Member Name|Description|Type|
|---|---|---|
|onoff_current|Current generic on/off value|uint8_t|
|onoff_target|Target generic on/off value|uint8_t|
|transtime|Transition time|uint8_t|
|onpowerup|On Power Up value|uint8_t|
|lightness_current|Current lightness value|uint16_t|
|lightness_target|Target lightness value|uint16_t|
|lightness_last|Last lightness value|uint16_t|
|lightness_default|Default lightness value|uint16_t|
|lightness_min|Minimum lightness value|uint16_t|
|lightness_max|Maximum lightness value|uint16_t|
|pri_level_current|Current primary generic level value|int16_t|
|pri_level_target|Target primary generic level value|int16_t|

The `lightbulb_state` struct in the Light CTL Server contains the following fields.

|Struct Member Name|Description|Type|
|---|---|---|
|temperature_current|Current temperature value|uint16_t|
|temperature_target|Target temperature value|uint16_t|
|temperature_default|Default temperature value|uint16_t|
|temperature_min|Minimum temperature value|uint16_t|
|temperature_max|Maximum temperature value|uint16_t|
|deltauv_current|Current delta UV value|int16_t|
|deltauv_target|Target delta UV value|int16_t|
|deltauv_default|Default delta UV value|int16_t|
|sec_level_current|Current secondary generic level value|int16_t|
|sec_level_target|Target secondary generic level value|int16_t|

The friend functionality is then initialized to enable the friend feature implemented in the stack. After successful initialization, friend requests from Low Power Nodes can be accepted. The friend feature is mostly implemented in the stack, so after initialization only a few informative events can be raised to the application through corresponding callback functions:

- `sl_btmesh_friend_on_friendship_established`: a friendship was established. The application displays “FRIEND” on the WSTK LCD and/or in UART logs.
- `sl_btmesh_friend_on_friendship_terminated`: the friendship was terminated. The application displays “NO LPN” on the WSTK LCD and/or in UART logs.

The light node registers callback functions for each of the supported models. This is done by calling the `mesh_lib_generic_server_register_handler()` function. The function has five parameters: the model ID, the element index, the client request handler function, the server state change handler function, and the server state recall handler function.

The light node registers handlers for the following models in the Lighting Server:

- Generic OnOff Server
- Generic PowerOnOff Server
- Generic Default Transition Time Server
- Light Lightness Server
- Light Lightness Setup Server
- Generic Level Server (on primary element)

The light node registers handlers for the following models in the Light CTL Server:

- Light CTL Server
- Light CTL Setup Server
- Light CTL Temperature Server (on secondary element)
- Generic Level Server (on secondary element)

On the server side, the mesh library works as follows. When any generic request from a client is received, the event `sl_btmesh_evt_generic_server_client_request_id` is raised. The application then calls the function `mesh_lib_generic_server_event_handler` from the mesh library and passes the event as the parameter. The mesh library decodes the model ID from the event and invokes the callback function that has been registered for that model.

For example, in the light node, a Generic OnOff request will invoke the callback function `onoff_request()`.

The `onoff_request()` function is called whenever an on/off request is received either from one of the switch nodes or from the smartphone app. This is the piece of code in the light node that turns lights on and off.

If the request does not specify any transition time or delay, then the light state is changed immediately. Alternatively, the client may have requested a delay and/or a transition time, meaning that the transition does not happen instantly. In that case, the light node application starts a soft timer with the given delay. The light state is not changed until the soft timer expires.

Light Lightness requests are handled in function `lightness_request()`. The lightness request includes a parameter of type `uint16` that indicates the light brightness on a scale of 0 – 65535. The example code uses pulse-width modulation (PWM) to drive the LEDs. The PWM is implemented using a 16-bit timer and the requested brightness value is directly mapped to the value of the Compare/Capture register of the timer. For example, the value 32768 will result in 32768/65536 ~ 50% brightness / PWM duty cycle. The duty cycle of the PWM signal is displayed on the LCD so that it is easy to compare the brightness that has been requested and the brightness that is currently set in the light node.

The Generic OnOff state is bound with the Light Lightness state. This means that, if the light is turned off with an on/off request, the last brightness value is saved by the application and is recovered after the application receives an on/off request that turns the light on. If brightness is set to 0 using lightness request, the generic on/off state is set to OFF. If brightness is set to a positive value, the generic on/off state is set to ON.

Brightness can be also changed using Generic Level requests handled in function `pri_level_request()`. The generic level request includes a parameter of type `int16` that indicates brightness level. The conversion from level to lightness is made by adding 32768 to the level value.

Light CTL requests are handled in function `ctl_request()`. The CTL request includes three parameters that indicate the light brightness, color temperature, and delta UV. The first two parameters are of type `uint16`, and the third is of type `int16`. Actual color temperature and delta UV are displayed on the WSTK LCD below the lightness. Color temperature is limited by spec to scale 800 – 20000 K. Limits can be changed by `ctl_setup_request()` with type of request set to _ctl_temperature_range_. Also the default values for CTL state could be changed using `ctl_setup_request()` with type of request set to _ctl_default_ .

##### Network Analyzer

Network Analyzer is a packet capture, decoder software, and visualization application and is part of Silicon Labs Simplicity Studio. Network Analyzer has support for Bluetooth LE and Bluetooth Mesh packet capture, and the latest version of Simplicity Studio also has decoders to decode the Bluetooth LE and mesh traffic. For more information, refer to [Using Network Analyzer with Bluetooth Low Energy and Mesh](/btmesh/11.0.0/network-analyzer-with-ble-btmesh).

The EFR32 SoCs have a dedicated Packet Trace Interface (PTI), which outputs all the radio traffic sent and received by a specific EFR32 device, and Network Analyzer can capture this traffic. On the EFR32, the PTI functionality can be enabled or disabled at the source-code level so it can be enabled during development and can then be disabled for production software.

Silicon Labs Wireless Starter Kits (WSTKs) support PTI packet capture either over USB, which is useful for capturing packets from a few WSTKs at a time, or over an Ethernet connection. The Ethernet connection also provides access to PTI, and this functionality enables building and debugging a network of WSTKs and large-scale testing environments for Bluetooth Mesh.

The easiest way to start a Network Analyzer session for a specific device is to switch to the **Network Analyzer** tab, right-click on the device, select **Connect,** and select **Start capture**.

![Starting Silicon Labs Network Analyzer](/btmesh-sdk6-or-higher-lighting-demo/10.0.0/images/an1299-image5.png)

##### Bluetooth Mesh Stack and Application for Smartphones

Silicon Labs also provides a Bluetooth Mesh stack and a reference application for smartphones. The application can be used to provision mesh-capable Bluetooth devices as nodes that are part of a Bluetooth Mesh network, as well as configure the nodes, set up groups, and the publish subscribe settings for nodes. At the time of writing this document, the application supports one physical network, multiple groups, and Lighting mesh models, but the application will be constantly updated for new features and functionality.

As the smartphones at the time of writing this document do not natively support Bluetooth Mesh, Silicon Labs also provides the Bluetooth Mesh stack for the phones. The mesh stack is needed for the phone to be able to provision, configure, and control the Bluetooth Mesh nodes over the GATT bearer. The figure below illustrates the architecture and the relationship between the Bluetooth stack on the phone operating system and the Silicon Labs Bluetooth Mesh stack, as well as how the application relates to this.

The Bluetooth Mesh stack will be available as a binary library for phone application developers. A reference application implementing the Bluetooth Mesh stack, provisioning, configuration, and device control is available on the Google Play and Apple App Stores.

Contact your local Silicon Labs sales office for more information.

![Bluetooth Stacks and Application Architecture on Smartphones](/btmesh-sdk6-or-higher-lighting-demo/10.0.0/images/an1299-image6.png)

#### Networked Lighting Control

##### Networked Lighting Control

> **NOTE: This section replaces _AN1438: Networked Lighting Control_. Further updates to this application note will be provided here**.

Networked lighting control (NLC) systems feature an intelligent network of individually addressable and sensor-rich luminaires and control devices that allows each component of the system to send and receive data. Specifically designed to meet the scale, reliability, and security demands required in commercial settings, Bluetooth® NLC is the only full-stack standard for wireless lighting control. By offering standardization from the radio through the device layer, Bluetooth® NLC enables true multi-vendor interoperability and mass adoption of wireless lighting control.

The Basic Lightness Controller NLC Profile specifies the requirements for a networked lighting control (NLC) product acting as a luminaire controller in a Bluetooth mesh system. The Basic Lightness Controller NLC Profile standardizes the use cases and implementation patterns of luminaire controllers to help improve interoperability and performance of systems based on Bluetooth mesh, such as NLC systems.

A common use case for the Basic Lightness Controller NLC Profile is a luminaire reacting to information published by occupancy and/or ambient light sensors as well as reacting to override events (e.g., manually dimming/brightening the lights or turning them on/off) in NLC systems.

###### Key Points

- Basic Lightness Controller NLC Profile
- Occupancy Sensor NLC Profile
- Ambient Light Sensor NLC Profile
- Dimming Control NLC Profile
- Basic Scene Selector NLC Profile

##### Introduction

Part of the reason that Bluetooth technology has become such a prevalent technology in people's lives is its reliance on standards. Through standards, the Bluetooth connections made between phones, PCs, headphones, game controllers, vehicle entertainment systems, and countless others all work because they all have built and established trust in the device profiles that initiate these connections, and they are universally used and available.

The Bluetooth SIG is taking that to the next step with the release of their new Network Lighting Control (NLC) bundle of device profiles. These standardized profiles will improve interoperability and scalability, simplify integration in the field, and grow the Bluetooth ecosystem. The same Silicon Labs Bluetooth SoCs and modules that support the new feature enhancements can also support the following NLC profiles: ambient light sensor, basic scene selector, dimming control, basic lightness controller, and occupancy sensor.

###### Lighting Control Device Profiles

Device profiles define which options and features of the Bluetooth Mesh specifications are mandatory for a certain kind of end product. The first suite of mesh device profiles, collectively referred to as NLC profiles, build on Bluetooth Mesh to enable the world’s first full-stack, multi-vendor interoperable wireless standard for wireless lighting control, Bluetooth® NLC.

###### NLC Profile Relationships

A device implementing the _Basic Lightness Controller NLC Profile_ interacts with devices implementing the following NLC profiles: _Occupancy Sensor NLC Profile_, _Ambient Light Sensor NLC Profile_, _Dimming Control NLC Profile_, _Basic Scene Selector NLC Profile_ (see Interaction of a Basic Lightness Controller with other NLC Profiles).

![first word, Interaction](/btmesh-networked-lighting-control/10.0.0/images/sld824-image1.png)

##### Implementation

Silicon Labs provides five examples to demonstrate this feature, one for every NLC Profile (except the Energy Monitor NLC Profile). All the examples and their main functionality logics are detailed below.

###### Bluetooth Mesh - NLC Basic Lightness Controller

_btmesh_soc_nlc_basic_lightness_controller_ - This is an example of a Bluetooth Mesh application providing the functionality of the Basic Lightness Controller NLC Profile. It demonstrates how to control a light source, an LED mounted on a mainboard, and a radio board or similar hardware, connected to a Bluetooth Mesh network. The light source lightness can be controlled with a Generic Level Client, e.g. another radio board running the Bluetooth Mesh - NLC Dimming Control application, or with Bluetooth Mesh smartphone application.

The device listens to messages from other NLC devices, namely Occupancy Sensor, Ambient Light Sensor, Dimming Control, and Basic Scene Selector nodes. Only a very simple implementation is needed on the application level.

```C
/*******************************************************************************

 * Callback for setting Light Lightness by PWM level (0x0001 - FFFE)

 ******************************************************************************/

void sl_btmesh_lighting_level_pwm_cb(uint16_t level)

{

  app_led_set_level(level);

}

/*******************************************************************************

 * Callback for setting Light Color by PWM level (0x0001 - FFFE)

 ******************************************************************************/

void sl_btmesh_lighting_color_pwm_cb(uint16_t color)

{

  app_led_set_color(color);

}
```

###### Bluetooth Mesh - NLC Basic Scene Selector

_btmesh_soc_nlc_basic_scene_selector_ - This is an example of a Low Power Node-enabled Bluetooth Mesh application providing the functionality of the Basic Scene Selector NLC Profile. Once the node is provisioned and a Basic Lightness Controller subscribes to the client, the two buttons of the mainboard are used to publish the messages that will recall stored scenes on the server. The example provides this recall functionality for scenes #1 and #2. The scene store functionality is provided by the mobile application.

Push Button presses control Basic Lightness Controllers in the network by scene recall requests. This requires the scene selection logic to be implemented in the button handler function.

```C
/*******************************************************************************

 * Button press Callbacks

 ******************************************************************************/

void app_button_press_cb(uint8_t button, uint8_t duration)

{

  (void)duration;

  char scene[SCENE_BUF_LEN];

#if SL_SIMPLE_BUTTON_COUNT == 1

  if (button == BUTTON_PRESS_BUTTON_0) {

    // Switch between scene 1 and 2

    current_scene = current_scene == 1 ? 2 : 1;

    sl_btmesh_select_scene(current_scene);

  }

#endif

#if SL_SIMPLE_BUTTON_COUNT >= 2

  // Select scene by pushed button

  current_scene = button == BUTTON_PRESS_BUTTON_0 ? 1 : 2;

  sl_btmesh_select_scene(current_scene);

#endif

  // Create unique device name using the last two bytes of the device UUID

  snprintf(scene, SCENE_BUF_LEN, "Selected scene: %d", current_scene);

  lcd_print(scene, SL_BTMESH_WSTK_LCD_ROW_CURRENT_SCENE_CFG_VAL);

}
```

###### Bluetooth Mesh - NLC Dimming Control

_btmesh_soc_nlc_dimming_control_ - This is an example of a Low Power Node-enabled Bluetooth Mesh application providing the functionality of the Dimming Control NLC Profile. Once the node is provisioned and a Basic Lightness Controller subscribes to the client, the two buttons of the mainboard are used to publish the messages that will change the state of the Basic Lightness Controller node.

Buttons can control the following models:

- Generic On/Off Client model can turn the light on and off or toggle
- Generic Level Client model can control the light brightness

Push Button presses control Basic Lightness Controllers in the network by Generic Level Delta or Generic On/Off messages. A slightly more complex logic is needed for the dimming in the button handler function.

```C
/*******************************************************************************

 * Button press Callbacks

 ******************************************************************************/

void app_button_press_cb(uint8_t button, uint8_t duration)

{

#if SL_SIMPLE_BUTTON_COUNT == 1

  if (button == BUTTON_PRESS_BUTTON_0) {

    switch (duration) {

      // Handling of button press less than 0.25s

      case APP_BUTTON_PRESS_DURATION_SHORT: {

        sl_btmesh_generic_level_client_ext_delta_set_unack(delta);

      } break;

      // Handling of button press greater than 0.25s and less than 1s

      case APP_BUTTON_PRESS_DURATION_MEDIUM: {

        sl_btmesh_generic_level_client_ext_delta_set_unack(-delta);

      } break;

      // Handling of button press greater than 1s

      case APP_BUTTON_PRESS_DURATION_LONG:

      case APP_BUTTON_PRESS_DURATION_VERYLONG: {

        sl_btmesh_change_switch_position(SL_BTMESH_LIGHTING_CLIENT_TOGGLE);

      } break;

      default:

        break;

    }

  }

#endif

#if SL_SIMPLE_BUTTON_COUNT >= 2

  // Selecting action by duration

  switch (duration) {

    // Handling of button press less than 0.25s

    case APP_BUTTON_PRESS_DURATION_SHORT: {

      int32_t delta_set;

      delta_set = button == BUTTON_PRESS_BUTTON_0 ? -delta : delta;

      sl_btmesh_generic_level_client_ext_delta_set_unack(delta_set);

      break;

    }

    // Anything more than 0.25s

    case APP_BUTTON_PRESS_DURATION_MEDIUM:

    case APP_BUTTON_PRESS_DURATION_LONG:

    case APP_BUTTON_PRESS_DURATION_VERYLONG: {

      uint8_t on_off = button == BUTTON_PRESS_BUTTON_0 ? SL_BTMESH_LIGHTING_CLIENT_OFF : SL_BTMESH_LIGHTING_CLIENT_ON;

      sl_btmesh_change_switch_position(on_off);

      break;

    }

    default:

      break;

  }

#endif

}
```

###### Bluetooth Mesh - NLC Ambient Light Sensor

_btmesh_soc_nlc_sensor_ambient_light_ - This example makes ambient light sensor measurements and forwards them to another node implementing the Basic Lightness Controller NLC Profile.

The device measures ambient light and sends these measurements to the network. Properly configured NLC Basic Lightness Controllers then can act on the received data. This example contains a Mock sensor logic in the button handler, in case there is no actual light sensor present on the board, thus revealing a possible logic to implement.

```C
/*******************************************************************************

 * Callback for button press

 ******************************************************************************/

void app_button_press_cb(uint8_t button, uint8_t duration)

{

  #if defined(SL_CATALOG_SENSOR_LIGHT_LUX_MOCK_PRESENT)

  float uvi;

  float lux;

  sl_status_t sc;

  sc = sl_sensor_light_get(&lux, &uvi);

  app_assert_status_f(sc, "Failed to get lux and uvi");

  #if (SL_SIMPLE_BUTTON_COUNT >= 2)

  // button pressed

  if (duration == APP_BUTTON_PRESS_DURATION_SHORT) {

    if (button == BUTTON_PRESS_BUTTON_0) {

      app_log("PB0 pressed" APP_LOG_NL);

      sl_sensor_light_set(lux - LUX_SMALL_CHANGE, uvi);

    } else if (button == BUTTON_PRESS_BUTTON_1) {

      app_log("PB1 pressed" APP_LOG_NL);

      sl_sensor_light_set(lux + LUX_SMALL_CHANGE, uvi);

    }

  } else if (duration == APP_BUTTON_PRESS_DURATION_MEDIUM) {

    if (button == BUTTON_PRESS_BUTTON_0) {

      app_log("PB0 medium pressed" APP_LOG_NL);

      sl_sensor_light_set(lux - LUX_LARGE_CHANGE, uvi);

    } else if (button == BUTTON_PRESS_BUTTON_1) {

      app_log("PB1 medium pressed" APP_LOG_NL);

      sl_sensor_light_set(lux + LUX_LARGE_CHANGE, uvi);

    }

  }

  #elif (SL_SIMPLE_BUTTON_COUNT == 1)

  (void)duration;

  if (button == BUTTON_PRESS_BUTTON_0) {

    app_log("PB0 pressed" APP_LOG_NL);

    sl_sensor_light_set(lux + LUX_LARGE_CHANGE, uvi);

  }

  #endif // SL_SIMPLE_BUTTON_COUNT

  #else

  (void)duration;

  (void)button;

  #endif // SL_CATALOG_SENSOR_LIGHT_MOCK_PRESENT

}
```

###### Bluetooth Mesh - NLC Occupancy Sensor

_btmesh_soc_nlc_sensor_occupancy_ – This example makes Occupancy Sensor measurements and forwards them to another node implementing the Basic Lightness Controller NLC Profile. This measurement can be faked by pressing the buttons on the mainboard:

- BTN1 increases people count
- BTN0 decreases people count

In case of only one button, a shorter press increases, while a longer one decreases the people count.

Push Button presses imitate people count changes which can control a properly configured NLC Basic Lightness Controller. Here as well, buttons simulate the increase/decrease of people, implemented in the button press handler function.

```C
/*******************************************************************************

 * Callback for button press

 ******************************************************************************/

void app_button_press_cb(uint8_t button, uint8_t duration)

{

  (void)duration;

  // button pressed

  if (duration == APP_BUTTON_PRESS_DURATION_SHORT) {

    if (button == BUTTON_PRESS_BUTTON_0) {

      app_log("PB0 pressed" APP_LOG_NL);

      sl_btmesh_people_count_decrease();

    } else if (button == BUTTON_PRESS_BUTTON_1) {

      app_log("PB1 pressed" APP_LOG_NL);

      sl_btmesh_people_count_increase();

    }

  } else if (duration == APP_BUTTON_PRESS_DURATION_MEDIUM) {

    if ( (button == BUTTON_PRESS_BUTTON_0)) {

      app_log("PB0 medium pressed" APP_LOG_NL);

      sl_btmesh_people_count_increase();

    }

  }

}
```

##### Network Setup

To create a demonstration network, at least five WSTK + radio boards or Thunderboards are needed, preferably ones equipped with display, and at least one of them with light sensor for the _btmesh_soc_nlc_sensor_ambient_light_ example and another one with RGB LED for the _btmesh_soc_nlc_basic_lightness_controller_ example.

###### Flashing

You may use the provided demo binaries or create your own project and flash it to the board with the bootloader of your choice. Doing these should lead to the terminal outputs below:

###### Bluetooth Mesh - NLC Basic Lightness Controller (heading level 7)

![Bluetooth Mesh - NLC Basic Lightness Controller](/btmesh-networked-lighting-control/10.0.0/images/sld824-image2.png)

###### Bluetooth Mesh - NLC Basic Scene Selector (heading level 7)

![Bluetooth Mesh - NLC Basic Scene Selector](/btmesh-networked-lighting-control/10.0.0/images/sld824-image3.png)

###### Bluetooth Mesh - NLC Dimming Control (heading level 7)

![Bluetooth Mesh - NLC Dimming Control](/btmesh-networked-lighting-control/10.0.0/images/sld824-image4.png)

###### Bluetooth Mesh - NLC Ambient Light Sensor (heading level 7)

![Bluetooth Mesh - NLC Ambient Light Sensor](/btmesh-networked-lighting-control/10.0.0/images/sld824-image5.png)

###### Bluetooth Mesh - NLC Occupancy Sensor (heading level 7)

![Bluetooth Mesh - NLC Occupancy Sensor](/btmesh-networked-lighting-control/10.0.0/images/sld824-image6.png)

###### Bluetooth Mesh App

With the help of Silicon Labs’ own Bluetooth Mesh App, scan for the Nodes and start to provision them one by one into your own NLC Mesh network.

![Provisioning and Configuration of the NLC Basic Scene Selector Node](/btmesh-networked-lighting-control/10.0.0/images/sld824-image7.png)  ![Provisioning and Configuration of the NLC Basic Scene Selector Node](/btmesh-networked-lighting-control/10.0.0/images/sld824-image8.png)  ![Before and After the Provisioning Process](/btmesh-networked-lighting-control/10.0.0/images/sld824-image9.png)

###### Bluetooth Mesh - NLC Basic Lightness Controller (heading level 7)

These figures show provisioning and configuration of the NLC Basic Lightness Controller Node.

![Bluetooth Mesh - NLC Basic Lightness Controller](/btmesh-networked-lighting-control/10.0.0/images/sld824-image10.png)  ![Bluetooth Mesh - NLC Basic Lightness Controller](/btmesh-networked-lighting-control/10.0.0/images/sld824-image11.png)

###### Bluetooth Mesh - NLC Basic Scene Selector (heading level 7)

These figures show provisioning and configuration of the NLC Basic Scene Selector Node.

![Provisioning and Configuration of the NLC Basic Scene Selector Node](/btmesh-networked-lighting-control/10.0.0/images/sld824-image12.png)  ![Provisioning and Configuration of the NLC Basic Scene Selector Node](/btmesh-networked-lighting-control/10.0.0/images/sld824-image13.png)

###### Bluetooth Mesh - NLC Dimming Control (heading level 7)

These figures show provisioning and configuration of the NLC Dimming Control Node.

![Bluetooth Mesh - NLC Dimming Control](/btmesh-networked-lighting-control/10.0.0/images/sld824-image14.png)  ![ Provisioning and Configuration of the NLC Dimming Control Node](/btmesh-networked-lighting-control/10.0.0/images/sld824-image15.png)

###### Bluetooth Mesh - NLC Ambient Light Sensor (heading level 7)

These figures show provisioning and configuration of the NLC Ambient Light Sensor Node.

![Bluetooth Mesh - NLC Ambient Light Sensor](/btmesh-networked-lighting-control/10.0.0/images/sld824-image16.png)  ![Bluetooth Mesh - NLC Ambient Light Sensor](/btmesh-networked-lighting-control/10.0.0/images/sld824-image17.png)

###### Bluetooth Mesh - NLC Occupancy Sensor (heading level 7)

These figures show provisioning and configuration of the NLC Occupancy Sensor Node.

![Provisioning and Configuration of the NLC Occupancy Sensor Node](/btmesh-networked-lighting-control/10.0.0/images/sld824-image18.png)  ![Bluetooth Mesh - NLC Occupancy Sensor](/btmesh-networked-lighting-control/10.0.0/images/sld824-image19.png)

###### Altering the Network

After the full setup, the network parameters are adjustable by changing the LC Property States, and the network can be tested by triggering changes with the push buttons. Switching LC Mode OFF, the NLC Dimming Control Node can be used, and by switching it ON, the NLC Ambient Light Sensor going to be active. By switching Occupancy Mode ON, the NLC Occupancy Sensor Node will take over.

|![Configuration of the Network and Node Logs](/btmesh-networked-lighting-control/10.0.0/images/sld824-image23.png)|![Configuration of the Network and Node Logs](/btmesh-networked-lighting-control/10.0.0/images/sld824-image22.png) ![Configuration of the Network and Node Logs](/btmesh-networked-lighting-control/10.0.0/images/sld824-image21.png) ![Configuration of the Network and Node Logs](/btmesh-networked-lighting-control/10.0.0/images/sld824-image20.png)|
|---|---|

##### Custom Project

To create a custom NLC Profile project, you have to add the appropriate NLC component to your project, which in turn will install the corresponding NLC Profile component. This is only valid for SoC projects. In the case of NCP, only the NLC Profile component is required.

![Simplicity Studio 5 Component Manager](/btmesh-networked-lighting-control/10.0.0/images/sld824-image24.png)

### Co-Processors (NCP/RCP)

#### Co-Processors (NCP and RCP)

The Silicon Labs Bluetooth stack provides multiple APIs for the developer to access the Bluetooth functionality. Three modes are supported:

- Standalone mode, where both the Bluetooth stack and the application run in an EFR32SoC or module. The application can be developed with C programming language.
- Network Co-Processor (NCP) mode, where the Bluetooth stack runs in an EFR32 and the application runs on a separate host MCU. For this use case, the Bluetooth stack can be configured into NCP mode where the API is exposed over a serial interface such as UART.
- Radio Co-Processor (RCP) mode, where only the Link Layer of the Bluetooth stack runs on the EFR32, and the Host Layer of the stack, as well as the application, runs on a separate host MCU or PC. In this use case, the Host Layer is developed by a third party, since Silicon Labs’ Bluetooth stack is only built for EFR32 SoCs / modules. The Link Layer and the host layer communicate via HCI (Host-Controller Interface), which is a standard interface between the two layers. The HCI can be accessed via UART following the Bluetooth SIG's UART (H4) transport protocol.

This section provides additional detail on the last two.

- [**Using the Bluetooth Stack in Network Co-Processor Mode**](/bluetooth/11.0.1/bluetooth-network-coprocessor-mode): Describes how to configure the NCP target and how to program the NCP host when using the Bluetooth Stack in Network Co-Processor mode
- [**Enabling a Radio Co-Processor using the Bluetooth Controller and HCI Functions**](/bluetooth/11.0.1/enabling-rcp-using-bt-hci): Gives a short overview of the standard Host Controller Interface (HCI) and how to use it with a Silicon Labs Bluetooth LE controller.

#### Local Event Handling on Bluetooth NCP

##### Introduction

A network co-processor (NCP) firmware can handle stack events locally instead of sending every event to the host processor, which allows event pre-processing, useful for some use cases, to prevent overflowing the host with events.

##### Background

Ordinarily, an NCP device sends and receives Bluetooth packets on behalf of a host processor but does not have any application layer intelligence. It receives commands from and sends events to the host and the host must tell the NCP what to do.

However, in some cases, it may be useful for the NCP to pre-process some of the events itself rather than to send every event to the host. For example, when the NCP acts as a scanner in a high-traffic environment, it reports every single advertisement to the host, which can easily be overwhelming for the host to process.

##### Implementation

This section explains how to modify the standard NCP firmware and assumes that the user is already familiar with the NCP by reading NCP-related documentation, for example [Using the Bluetooth Stack in Network Co-Processor Mode](/bluetooth/11.0.1/bluetooth-network-coprocessor-mode).

By default, the NCP firmware passes all events to the host processor. However, this can be controlled by an implementation of `sl_ncp_local_evt_process()`. This function can be implemented in any source file of the firmware, e.g., app.c. This function implementation will override the default implementation that performs no handling of events and returns _true_ to indicate that the event passed to it has not been handled and should be sent to the host. If the function returns _false_, the event will **not be sent** to the host device.

To handle a particular event locally, this function can be customized. In this case, let’s assume that the desired behavior is to filter out any advertisements or scan responses that do not come from a device with OUI 00:0B:57 (which is an OUI of Silicon Labs) and **not** to send them to the host. This can be accomplished by implementing a switch case statement in the `sl_ncp_local_evt_process()` function that captures the _scanner_scan_report_ event and checks the OUI.

```c
/**************************************************************************//**
 * Local event processor.
 *
 * Use this function to process Bluetooth stack events locally on NCP.
 *
 * @param[in] evt Event coming from the Bluetooth stack.
 *
 * @return true, if the event should be forwarded to the NCP-host.
 *         false, if the event has been handled locally.
 *
 * @note This overrides the default weak implementation.
 *****************************************************************************/
bool sl_ncp_local_evt_process(sl_bt_msg_t *evt)
{
  bool evt_to_host = true;
  bd_addr address;
  switch (SL_BT_MSG_ID(evt->header)) {

    case sl_bt_evt_scanner_scan_report_id:
      address = evt->data.evt_scanner_scan_report.address;
      if(address.addr[5] == 0x00 && address.addr[4] == 0x0B && address.addr[3] == 0x57) {
        // Scanned device has OUI 00:0B:57 so the event shall be sent to the host
        evt_to_host = true;
      }
      else {
        // Scanned device does *not* have OUI 00:0B:57 so the event shall *not* be sent to the host
        evt_to_host = false;
      }
      break;

    default:
      break;
  }
  return evt_to_host;
}
```

This section of code checks whether the first three bytes of the Bluetooth address, which come in reverse order, match the desired OUI. If that's the case, _evt_to_host_ is set **true** and the event **will be sent** to the host. Otherwise, _evt_to_host_ is set to **false** indicating that the event will **not be sent** to the host. This is a small change but it could dramatically reduce the amount of traffic between NCP and host as well as reducing the burden on the host itself.

In this way the `sl_ncp_local_evt_process()` function can be implemented to perform any local event handling.

#### Using the Bluetooth Stack in Network Co-Processor Mode

##### Introduction

> **Note: This section replaces _AN1259: Using the Silicon Labs _Bluetooth_® Stack v3.x and Higher in Network Co-Processor Mode_ for Simplicity SDK 2024.12.2 and up. Further updates to this application note will be provided here**.

These pages are an essential reference for anyone developing a system for the Silicon Labs Wireless Gecko products using the Silicon Labs v3.x Bluetooth Stack in Network Co-Processor (NCP) mode. They cover the C language application development flow,  walks through the examples included in the stack, and shows how to customize them.

The Silicon Labs Bluetooth SDK allows you to develop System-On-Chip (SoC) firmware in C on a single microcontroller. The SDK also supports the Network Co-Processor (NCP) system model.

These pages provide a guide on how to get started with software development of an NCP system. They describe the development tools and example projects, then highlight the most important steps you need to follow when writing your own application.

###### SoC vs NCP System Models

On an SoC system, the Application code, the Bluetooth Host, and Controller code run on the same Wireless MCU.

On an NCP system, the Application runs on a Host MCU, and the Host and Controller code run on a Target MCU. The Host and Target MCUs communicate on a serial interface. The communication between the Host and Target is defined in the Silicon Labs Proprietary Protocol called BGAPI. The physical interface is UART. BGLib v3.x is an ANSI C reference implementation of the BGAPI protocol, which can be used in the NCP Host Application.

![SoC vs NCP System Models](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-soc-vs-ncp-system-models.png)

##### NCP Target Development

This page describes the available tools for compiling and flashing the NCP target firmware.

Before proceeding with compiling and flashing C-based firmware, install Simplicity Studio 5 (SSv5). You can download it from the Silicon Labs website: [http://www.silabs.com/simplicity](http://www.silabs.com/simplicity). Once Simplicity Studio is installed, follow the prompts to install the Gecko SDK Suite (GSDK) containing the Bluetooth SDK. See the online [Simplicity Studio 5 User's Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/) for details on installation and using Simplicity Studio. See the [Bluetooth Getting Started Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-getting-started-overview/) for additional details about the Bluetooth SDK.

> **Note**: [Using the Silicon Labs Bluetooth Stack v3.x and Higher in Network Co-Processor Mode](https://docs.silabs.com/bluetooth/latest/bluetooth-network-coprocessor-mode/) describes in detail how the NCP is implemented in the Gecko SDK v2. This application note explains the code and tools on both the target and host side.

To develop in C, you not only need Simplicity Studio 5 but also a supported compiler. The Bluetooth SDK release notes and [Silicon Labs Bluetooth C Application Developers Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x/) list the supported compilers.

The NCP target firmware comes with the Bluetooth SDK. It is available in a precompiled binary format and as a project file you can build. The following procedures describe how to install the precompiled binary image and how to build and install the example project. Note that Simplicity Studio only shows the relevant examples for the preferred SDK, so you have to select **Gecko SDK Suite vn.n.n** first, as shown in the following figure. (Note: Your SDK version may be different from the one shown in the figure.)

![Preferred SDK](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-preferred-sdk.png)

The following procedure describes how to build and load the example code. This procedure assumes you have already loaded a Gecko Bootloader in one of the following ways:

- Loaded the Gecko Bootloader precompiled binary from the list of Demos. For an NCP application, load the NCP BGAPI UART DFU bootloader.
- Built and loaded your own Gecko Bootloader as described in _UG266: Silicon Labs Gecko Bootloader User’s Guide in GSDK 3.2 and Lower_, [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/), or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

1. Click **Example Projects & Demos**, select **Bluetooth - NCP** and click **Create**.  
   > **Note**: The **Bluetooth - NCP** example does not contain a GATT database. The dynamic GATT API can be used for building it. Host software examples in the Bluetooth SDK build their GATT database dynamically, by default.  
   ![Bluetooth - NCP example](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-examples.png)
2. Name the project and click **Finish**.  
   ![Name the project](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-create-project.png)
3. Now the project is ready to build and flash. Click **Debug** (bug icon) in the top left menu to do it in one step. You may also use the precompiled NCP demos in Simplicity Studio, which are shipped with bootloader included.  
   > **Note**: If you get an error when you click **Debug**, click the project _.isc_ file in the Project Explorer view. It may not be fully selected.

##### NCP Host Development

This section introduces the Bluetooth NCP Commander tool, which can be used to send BGAPI commands from a graphical user interface. It then walks through the process of building the PC Host examples provided in the Bluetooth SDK. And finally, it describes using Python for host side development.

###### Bluetooth NCP Commander

Bluetooth NCP Commander is an easy-to-use tool that can be used for testing different stack features, by sending BGAPI commands to the target device. The tool has two versions: a version built into Simplicity Studio, which makes it easy to connect to your development kit and start testing, and a standalone version to test a board in an environment where Simplicity Studio cannot be installed, or if you want to test a custom board that can be accessed on UART interface, but not through a Simplicity Studio supported debug adapter using VCOM.

###### Built-in Version (heading level 7)

1. To open the built-in Bluetooth NCP Commander, select the target board in the **Debug Adapters** view, and check that the preferred SDK is set to **Gecko SDK Suite vn.n.n**. Select the **Compatible Tools** tab, and click **Launch** next to Bluetooth NCP Commander.  
   ![Compatible Tools](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-tools-tab.png)  
   Alternatively, you can open the built-in Bluetooth NCP Commander from the **Tools** menu.  
   ![Tools dialog](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-tools-menu.png)
2. Select the target device, and click **Connect**.  
   ![Connection Manager](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-connection-manager.png)

###### Standalone Version (heading level 7)

1. To open the standalone tool, navigate to _C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\ncp_commander_, and start NcpCommander.exe.
2. In the standalone tool, provide the UART interface settings, and then select the COM port on which the device can be accessed.  
   ![Serial Connection Manager](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-serial-connection-manager.png)

###### Bluetooth NCP Commander Functions (heading level 7)

The following procedure covers most NCP Commander functions.

1. After the device is connected, you should see the result of the `sl_bt_system_get_identity_address` command displayed in green:  
   ![NCP Commander](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-open.png)
2. Unlike SoC examples, the NCP demo does not have a built-in GATT database. It expects the host to build the GATT database using the dynamic GATT database BGAPI commands. To create a basic GATT database, select the Local GATT menu, and click **Create Basic GATT**. This triggers a series of BGAPI commands that will build a basic database. You can modify this GATT database as you want. You can also change the device name here by changing the value of the Device Name characteristic.  
   ![Create Local GATT](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-create-local-gatt.png)
3. To extend the database with new services, characteristics, and descriptors, click **Add Service**. You can then add new characteristics for the service.  
   ![Commander add service](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-add-service.png)
4. To read out the GATT database from the device, click **Local GATT Database**. The smart console also supports API calls for creating entries.  
   ![Commander API method](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-api-method.png)
5. To start advertising your device so that other devices can discover it and connect to it, in the Advertise menu click '**+**' (Create Set) to create an advertiser set.  
   ![Commander start advertising](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-start-advertising.png)
6. To populate the advertisement payload with the device name, set the Advertising Data Type to **Generated data** and click **Start** to start advertising.  
   ![Advertising Data Type](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-start-advertising-2.png)
7. When advertising, the NCP target example accepts Bluetooth connections. If you connect to the mainboard or with another central device (for example with your phone), you can see the events and commands on the log.  
   ![Commander log view](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-log-view.png)
8. You can also issue commands manually. For example, you can issue the 'system hello' command at any time to verify that communication between the host and the device is working. The Smart Console provides auto-completion and documentation for the possible commands. To open/close the documentation, click the arrows at the right side of the input field.  
   ![Commander issue commands](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-issue-commands.png)
9. To create periodic advertisement sets, select **Advertisement mode: Periodic**. To set the content of the packet, use the **Edit** option next to "Periodic Advertising Packets".  
   ![Commander periodic advertising](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-periodic-advertising.png)  
   This opens a new dialog where you can edit the contents of the package. Click **Set Data** after the data is edited.  
   ![Commander edit packet](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-edit-packet.png)
10. It is also possible to synchronize to periodic advertisement trains. To do this, click **Synchronization** on the left menu, input the Advertiser Address and advertising Set identifier, and click **Open Synchronization**.  
    ![Commander synchronize streams](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-synchronize-streams.png)
11. NCP Commander also provides a simple scripting feature. You can create or import an existing script with the controls on the top right corner. You can use any BGAPI commands in the script, but there are no additional features, such as branching or error handling.  
    ![Commander scripting](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-scripting.png)  
    You can export the commands sent in the Smart console with the **Export** control. This saves the sent commands to a file that can be imported back as a script. You can also export the raw script using the **Export** button under the editor.  
    ![Commander export messages](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-export-messages.png)

###### Host Provisioner with Bluetooth NCP Commander (heading level 7)

Bluetooth NCP Commander also supports Bluetooth mesh features. You can issue Bluetooth mesh commands manually in the command box of Smart Console or use the host provisioner feature from the left menu. You can use the feature to provision and configure mesh nodes and to manage mesh networks rather than using a Bluetooth Mesh mobile application.

To use the Bluetooth Mesh features, create, build, and flash the device with an NCP example supporting Mesh features. Otherwise, the provisioner initialization attempt returns SL_STATUS_NOT_SUPPORTED (0x000f).

![NCP example supporting Mesh features](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-mesh-example.png)

In **Settings**, if the **Reset Mesh Node before Initializing as Provisioner** option is enabled, the host provisioner does a factory reset (the **node_reset** command) on the NCP target device before initializing the node. Clicking **Clear Data** next to **Remove all locally saved mesh data** removes the network and application keys that were configured during initialization.

![mesh initialization](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-initialization.png)

1. To start using the host provisioner, select either **Provision** or **Networks & Nodes** on the left menu, and click **Initialize as Provisioner**.  
   ![Initialize as Provisioner](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-start-provisioning.png)
2. To provision devices, select **Provision** on the left menu and click **Start Scan** in the right panel. The devices that are transmitting unprovisioned beacons are shown in the **Discovered Devices** section. If you do not have a network from a previous configuration or have reset the provisioner node, you must create a new network with **Create New Network**.  
   ![mesh provision](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-provision.png)
3. Enter the name of the new network and click **Confirm**.  
   ![create new network](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-create-network.png)
4. Click **Provision** next to the device you want to provision.  
   ![provision](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-provision-device.png)
5. Before configuring devices, you may need to create application keys and groups. Application keys, groups, and other network settings can be managed in the **Settings** tab of the **Networks & Nodes** menu item. To create an application key, click **Create App Key**, name the key, and click **Confirm**. You can create as many application keys as you need. If you have created any application keys before, you can click **Get App Keys** to retrieve them. To create a group, click **Add Group**, name the group, and click **Confirm**. You can create as many groups as you need.  
   ![create keys groups](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-create-keys-groups.png)
6. In the same tab, you can induce a full network-wide key refresh or exclude nodes.  
   ![other settings](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-other-settings.png)
7. To configure a provisioned device, select **Networks & Nodes** on the left menu. The devices you provisioned are shown in the **Nodes (Provisioned Devices)** section of the **Settings** tab. Click **Configure** and a **Mesh Node** tab opens in which you can configure the device.  
   ![configure provisioned device](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-configure-provisioned-device.png)
8. In the **Application Keys** section of the **Mesh Node** tab, select an application key from the drop-down list and then click **Add**.  
   ![mesh device keys](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-device-keys.png)
9. Click **Get DCD** to configure all the Models available on your node(s), bind to app keys, set publishing or subscription to groups, fine tune parameters, and so on.  
   ![node configuration](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-node-configuration.png)
10. To configure the Provisioner, the Models must first be initialized using **Initialize Client Models**.  
    ![initialize models](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-initialize-models.png)
11. The Application Key must be bound to the Models in order for them to decrypt received messages. Press **Bind**.  
    ![initialize models 2](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-initialize-models-2.png)
12. To subscribe the Models to the messages of the recently created Group (optional), select the chosen Group from the dropdown and click **Subscribe**.  
    ![subscribe models](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-subscribe-models.png)
13. When configuration is complete, click **Done**. The **Show Nodes** tab is displayed, where you can **Get DCD** of the provisioned Node(s).  
    ![Get DCD](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-get-dc.png)
14. After listing, you can **Get** or **Set** the Server states of the Node(s).  
    ![get or set server states](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-get-set-server-states.png)
15. Click Set to set the current state of the selected Server of the selected Node.  
    ![set server state](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-set-server-state.png)
16. Click **Get** to get the current state of the selected Server of the selected Node.  
    ![get server state](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-get-server-state.png)
17. On the **Show Groups** tab, you can **Set** or **Get** the Server Model(s) states on a Group level.  
    ![group level](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v14-ncp-commander-mesh-get-set-model-state.png)

###### Building the NCP Host Examples on Windows

The Silicon Labs v3.x Bluetooth SDK contains a generic NCP Host example project for the PC. This example can be compiled on Windows or any POSIX OS. This section goes through the build process on Windows.

> **Note**: The host example projects in the SDK use the dynamic GATT database feature. They are to be used with the **Bluetooth – NCP** target application.

1. To build the examples properly, the MSYS2 development toolchain must be installed on your PC. Download MSYS2 at [MSYS2](https://www.msys2.org/).
2. After MSYS2 is installed, update the package database as described at [MSYS2](https://www.msys2.org/).
3. Start MSYS2 bash and install mingw-64 with the following command:  
   ```C  
   pacman -S make mingw-w64-x86_64-gcc  
   ```
4. Close MSYS2 and start MSYS2 MinGW 64-bit.  
   ![msys2 mingw 64-bit](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-msys2-mingw-64-bit.png)
5. Change to the NCP Host example folder, where <version> varies by SDK version:  
   ```C  
   cd c:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.x\app\bluetooth\example_host\bt_host_empty\  
   ```  
   or  
   ```C  
   cd c:\Users\<username>\SimplicityStudio\SDKs\gecko_sdk\app  
   ```
6. Create an export of the example with the command `make export`. After the project files are exported, the export directory will be a working directory that is completely detached from the SDK but has the same folder structure inside. The benefit of using an export is that changes in the (config) files during development will not affect the SDK content, and multiple instances can coexist, for example for testing different variants. You can also use `make export EXPORT_DIR=/my/custom/export/path` to export the example to a custom directory.
7. Within the export folder navigate to the _/app/bluetooth/example_host/bt_host_empty_ folder.
8. If you want to add any service/characteristic to the GATT database, edit the _/config/btconf/gatt_configuration.btconf_ file. Edit it either with a text editor or drag-and-drop the file onto Simplicity Studio to edit it with the GATT Configurator. Do not forget to save the file after editing.
9. Generate GATT database source files from the ._btconf_ file by running `make gattdb` (in the _/bt_host_empty_ folder). Note: The generator script requires installing Python 3 and the Jinja2 package by calling `pip install jinja2`.
10. Build the exported project with the command: `make`. (Run it in the _/bt_host_empty_ folder, where you can find the makefile).
11. The build output is created in a new _exe_ folder. Go to this folder with `cd exe`, and then run`bt_host_empty.exe`. The COM port and the IP address of the target are passed as command line parameters. The COM port should be the same as the one used by the JLink CDC UART Port, as shown in [NCP Host Development](./03-ncp-host-development). To see how to pass the different parameters, first run the exe with the `-h` (help) switch.  
    ```C  
    .\bt_host_empty.exe -h  
    ```
12. Once the UART connection with the device is established, you should see the following:  
    ![started advertising message](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-figure-3-6.png)
13. Now you can connect to the device over Bluetooth.

###### Using Python for Host Side Development

You can also implement a host application using Python. A Python package is available at [PyBGAPI](https://pypi.org/project/pybgapi/). This package parses the API description file of the Bluetooth SDK and makes it possible to issue BGAPI commands and get BGAPI events in the Python environment. See the referred website for further documentation.

##### Secure NCP

Secure NCP secures communication between the NCP Host and target by encrypting the commands, events, and any data transmitted between the target and the host.

###### Target Side

To enable this feature on the target side, install the NCP Security Interface component.

![NCP Security Interface](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-secure-ncp-target.png)

By default, the NCP target boots without using this encryption. It will be requested by the Host part, and after the security is increased, only encrypted messages are sent and accepted by the target.

###### Host Side

To build the NCP Host project with secure mode, use the following command:

```C
make SECURITY=1
```

This requires the openssl package to be installed. Install it to your MSYS2 environment with:

```C
pacman -S mingw-w64-x86_64-openssl
```

After the project is built, the encryption can be enabled by calling the .exe file with the command line parameter `-s`:

```C
.\empty.exe -s
```

```C
$ ./empty.exe -u COM21 -s
[I] NCP host initialised.
[I] Resetting NCP target...
[I] Press Ctrl+C to quit
[I] Start encryption
[I] Communication encrypted
[I] Bluetooth stack booted: v3.2.1-b216
[I] Bluetooth public device address: 00:0B:57:A7:84:15
[I] Started advertising.
```

Running the exe file without this option will start a normal NCP Host application without encryption.

##### Using NCP with CPC (Co-Processor Communication)

###### Co-Processor Communication Overview

The purpose of the Co-Processor Communication (CPC) Protocol is to act as a serial link multiplexer that allows data sent from multiple applications to be transported over a secure shared physical link. In CPC, data transfers between processors are segmented in sequential packets over endpoints. Transfers are guaranteed to be error-free and sent in order.

Find more information about the CPC at [https://docs.silabs.com/gecko-platform/4.1/service/cpc/overview](https://docs.silabs.com/gecko-platform/4.1/service/cpc/overview).

###### Usage

The CPC daemon acts as a bridge between the host and the target application. It was designed to make a reliable connection between two ends through UART or SPI. Reliability is achieved by an HDLC-like header and CPC. It offers multi-channel communication, and security is turned on by default. It is a connection-based protocol, so that if a message arrives incorrectly, it notifies the other end, which then can re-send that message.

![CPC daemon](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-cpc-daemon.png)

The NCP host by default does not contain usage of CPC. You need to build the application with the command line option `CPC=1`.

###### Use Cases

Adding the CPC functionality is recommended for the following use cases, as they cannot be used with the simple UART interface:

- Using SPI as the transport layer: SPI communication is only supported with CPC.
- DMP projects: the CPC protocol contains a multiplexer, which makes it possible to use the same interface for different applications.

###### Building the Target

To make the target use CPC communication, replace the USART component in the **bt_ncp** sample application with **CPC Secondary - UART (USART)** or **CPC Secondary – SPI (USART)**. This adds all the necessary components to enable CPC communication on the target. Set the pins of the selected communication interface according to the hardware design of the project.

The encryption of the communication is enabled by default. For developing and debugging, Silicon Labs recommends adding the **CPC SECURITY NONE** component so that the packet traces can be easier analyzed.

![Secondary UART](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-cpc-secondary-uart.png)

###### Host Side

Perform the following steps:

###### Step 1: Build the CPC daemon (heading level 7)

Download the code for the CPC daemon and follow the instructions to build it from [https://github.com/SiliconLabs/cpc-daemon](https://github.com/SiliconLabs/cpc-daemon).

After the build is finished, open the _cpcd.conf_ file and set the **bus_type**, and configure the pins and bitrate according to the settings on the Secondary side.

If the **CPC SECURITY NONE** component was added to the target, set **disable_encryption** to true.

###### Step 2: Build the host application (heading level 7)

Find the _ncp_host_bt.mk_ file in the <SDK folder>/app/Bluetooth/component_host/ folder, and set `CPC_DIR` to the path of the CPC daemon folder on your machine.

Next, go to the **bt_host_empty** sample application in <SDK folder>/app/Bluetooth/example_host/bt_host_empty, and build it with this command line option to enable CPC: `make CPC=1`.

###### Step 3: Run the application (heading level 7)

Start the CPC daemon `cpcd -c ./cpcd.conf`.

Start the host application by passing the **instance_name** set in the _cpcd.conf_ file: `./bt_host_empty -C cpcd_0`.

##### Example Project Walkthrough

This page describes the structure of the example NCP Host and Target projects, and highlights the parts that can be important if you create your own project.

###### NCP Target

This section focuses on the NCP-specific part of the **Bluetooth - NCP** SSv5 project. You can find a general project description in [Silicon Labs Bluetooth C Application Developers Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-c-soc-dev-guide-sdk-v9x/).

The **Bluetooth - NCP** example does not contain a GATT database. The dynamic GATT API can be used for building it. This is recommended because the target code does not need to be modified and synchronized with the Host code when the GATT database is updated.

###### Project File Structure (heading level 7)

A common directory and file structure are used across all examples in the Bluetooth SDK v3.x. The following figure shows this layout.

![project file structure](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v10-bt-ncp-project.png)

These files and directories are present in the root directory of the project:

- _main.c_ and _app.c/h_ – the C application code
- _bt_ncp.pintool_ – the hardware configuration file and user interface
- _bt_ncp.slcp_ – the component configuration and user interface
- _bt_ncp.slps_ – the project properties XML file
- _GNU ARM v<X.Y.Z>_ – the build directory
- _gecko.sdk_3.<X.Y>_ – the Bluetooth SDK source code
- _config_ – the C configuration files of the hardware and Bluetooth stack. This directory contains the output files of the Pin Tool and Component Manager.
- _autogen_ – the C configuration code of the application. This directory typically contains the stack definition and initialization C files, as well as the generated GATT database C declaration files (_gatt_db.c/h_).

###### Pin Tool (heading level 7)

1. Open the pin configuration tool (Pin Tool) on the project Configuration Tools tab.  
   ![pin tool](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v04-pin-tool.png)  
   You can also double-click the _<projectname>.pintool_ file in the Project Explorer view, shown highlighted in the figure above.
2. Use this tool to modify the pin configuration of the device, for example, you can reassign the pins used for USART communication to the appropriate layout for a custom board design. You do this by selecting the desired pin in the list and then selecting its functionality from the drop-down list.  
   ![pin tool example](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-figure-4-3.png)
3. After clicking the selected item, the layout is updated. After saving the file, the configuration source codes are automatically generated.  
   ![config source code generation](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-figure-4-4.png)

###### Project Configurator/Component Editor (heading level 7)

You can install or uninstall components using the Project Configurator's Software Components tab. You can also configure installed components using the Component Editor. The following figures show how to change the NCP interface buffer sizes.

1. Select the component from the list and click **Configure**.  
   ![Configure](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v04-ncp-communications-component.png)
2. The Component Editor opens in a new tab with the possible configuration options. You can view the corresponding source code by clicking **Open Source**.  
   ![Open Source](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v04-ncp-interface-options.png)
3. Apart from the application-specific NCP options, you can use the Project Configurator to configure the Bluetooth stack features that will be included in your project. Some advanced features are excluded from the stack by default, to save flash and memory. You can add the needed features, for example, the Adaptive Frequency Hopping (AFH) component, by clicking **Install**.  
   ![Install](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v04-component-install.png)
4. In many cases, you also need to change the default Bluetooth Core configuration, for example to enable more than four connections. To do so, browse for the Bluetooth Core component, and click **Configure**.  
   ![Configure](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-bluetooth-core-configure.png)

###### Enabling Hardware Flow Control (heading level 7)

In the sample applications, Hardware Flow Control is enabled by default. On the mainboard, hardware flow control can be enabled as described in this section.

Important: If the hardware flow control settings are not the same in the SoC and mainboard, the NCP will not work.

1. Open Simplicity Studio and, in the Debug Adapters view, right-click the target device.
2. Select **Connect**.
3. Right-click the device again and select **Launch Console**.
4. Select the admin tab.
5. Set flow control with the following command:  
   ```C  
   WSTK> serial vcom config handshake rtscts  
   RTS handshake enabled  
   CTS handshake enabled  
   Serial configuration saved  
   ```
6. Check the configuration with the following command:  
   ```C  
   WSTK> serial vcom  
   ----- Virtual COM port -----  
   Stored port speed : 115200  
   Active port speed : 115226  
   Stored handshake : rtscts  
   Actual handshake : rtscts  
   RTS Asserted - Ready to Receive.  
   ```

The flow can be disabled by setting the handshake parameter to `none` in step 5 above.

###### Main Walkthrough (heading level 7)

This is a code snippet that corresponds to the `main` function. Because the Bluetooth stack and subsequent hardware are considered to be components, they are separated from the application processing that is entirely managed in _app.c/h_.

![code snippet of main function](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-figure-4-8.png)

Once the USART and Bluetooth stack are initialized, the main loop continuously calls the component as well as the application state machine. The corresponding functions are `sl_system_process_action()` and `app_process_action()` respectively.

The `sl_system_process_action()` handles Silicon Labs tasks and routines. It must _not be removed_ from the loop.

The default USART settings are mentioned in the Host example section. Make sure that the target and the host use the same configuration. The configuration can be adapted with the help of the Pin Tool and the Project Configurator.

###### Application Callback and Actions (heading level 7)

Use the `app_init()` function to call application-related initializations.

Use the `app_process_action()` function to call application-specific tasks and routines.

![application callback](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v08-callbacks.png)

###### NCP Code Walkthrough (heading level 7)

The USART communication handling is implemented in _ncp_usart.c_. Receiving any command from the Host generates an interrupt, and it will queue the received data in the command queue. Similarly, when a stack generates an event, it will be put into an event queue, which will be forwarded to the Host. These two queues will be processed in _ncp.c_, as described on the following figure.

![NCP Code Walkthrough](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-figure-4-10.png)

###### Sleep Modes (heading level 7)

The NCP example project does not enable deep sleep mode (EM2) by default, because UART needs EM1 or EM0 to be able to receive commands at any time. Deep sleep mode can be enabled, but in this case, it is essential to configure a wakeup pin so that the NCP Host can wake up the target before sending any BGAPI commands to it. Any available GPIO pin can be configured as a wakeup pin and the polarity is configurable. The following example shows how to configure pin PF6 as the wakeup pin using active-high polarity.

To enable deep sleep mode, the UARTDRV Core component's **Enable reception when sleeping** parameter must be disabled. Otherwise the UART driver will prevent the device from going into EM2 (deep sleep) and it will stay in EM1 (sleep):

![UARTDRV Core](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v02-uartdrv.png)

To define a wakeup pin, the Bluetooth > Utility > Wake Lock component must be added to the project:

![Wake Lock](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v04-wake-lock.png)

Configure the Wake-Lock component as follows:

- Enable the wake-lock (direction in) functionality
- Set the polarity (active high in this case)
- Assign the GPIO pin (PF6 in this example)  
  ![Wake Lock Input](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v02-wake-lock-config.png)

When the Host sets the wakeup pin to the configured active value, the NCP device will wake up from deep sleep and send out the event `sl_bt_evt_system_awake` to indicate to the host that it has woken up. The host must wait for this event before sending any BGAPI commands, otherwise they might be partially or completely missed.

The remote wake-lock (direction: out) functionality can be used to wake up the host before the NCP target sends out an event. This way the host is also able to go into sleep mode, and it will be notified when it should wake up.

###### PC Host

The PC host application project that comes with the SDK is written in C. The host-side source files for this project are found in folders, for GSDK 3.x:

*c:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<version>\app\bluetooth\example_host\empty*

or, for GSDK 4.0 and higher:

_c:\Users\<username>\SimplicityStudio\gecko_sdk\app\bluetooth\example_host_

The projects comprise only a few source and header files. Note, however, that many other files are referenced from the SDK in the makefile. For example, many utility functions are implemented under:

*<SDK folder>\app\bluetooth\common_host*

but the Bluetooth protocol folder is also heavily used as described later. To copy all the files related to the project into a single folder, take advantage of the export feature described in [Host Side](04-secure-ncp#host-side).

###### BGAPI Support Files (heading level 7)

While the files in the previous section contain all of the application logic, the actual BGLib implementation code containing the BGAPI parser and packet generation functions is found elsewhere, in other subfolders.

Default location in GSDK 3.x, where <version> will vary by SDK version:

- `c:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\inc\sl_bt_ncp_host.h`
- `c:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\src\sl_bt_ncp_host.c`
- `c:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\src\sl_bt_ncp_host_api.c`

Default location in GSDK 4.0 and higher:

- `c:\Users\<NAME>\SimplicityStudio\SDKs\gecko_sdk\protocol\bluetooth\inc\sl_bt_ncp_host.h`
- `c:\Users\<NAME>\SimplicityStudio\SDKs\gecko_sdk\protocol\bluetooth\src\sl_bt_ncp_host.c`
- `c:\Users\<NAME>\SimplicityStudio\SDKs\gecko_sdk\protocol\bluetooth\src\sl_bt_ncp_host_api.c`

The SDK’s specific arrangement of files is one possible way the BGAPI protocol can be used, but it is also possible to create your own library code that implements the protocol correctly with a different code architecture. The only requirement here is that the chosen implementation must be able to create BGAPI command packets correctly and send them to the module over UART. Similarly, it must be able to receive BGAPI response and event packets over UART and process them into whatever function calls are needed to trigger the desired application behavior.

The header files contain primarily #define’d compiler macros and named constants that correspond to all of the various API methods and enumerations you may need to use. The _sl_bt_ncp_host.h_ file also contains function declarations for the basic packet reception, processing, and transmission functions.

The _sl_bt_ncp_host.c_ file contains the implementation of the packet management functions. All functions defined here use only ANSI C code, to help ensure maximum cross-compatibility on different platforms.

> **Note**: With structure packing, the SDK’s BGLib implementation makes heavy use of direct mapping of packet payload structures onto contiguous blocks of memory, to avoid additional parsing and RAM usage. This is accomplished with the PACKSTRUCT macro used extensively in the BGLib header files. It is important to ensure than any ported version of BGLib also correctly packs structures together (no padding on multi-byte struct member variables) in order to achieve the correct operation.

With byte order, the BGAPI protocol uses little-endian byte ordering for all multi-byte integer values, which means directly-mapped structures will only work if the host platform also uses little-endian byte ordering. This covers most common platforms today, but some big-endian platforms exist and are actively used today (Motorola 6800, 68k, and so on).

###### Host Application Logic (heading level 7)

1. Initialize BGLIB.  
   ```C  
   sl_bt_api_initialize_nonblock(ncp_host_tx, ncp_host_rx, ncp_host_lazy_peek);  
   ```
2. Initialize UART.  
   ```C  
   handle_ptr = &handle;  
   HOST_COMM_API_INITIALIZE_NONBLOCK(uartTx, uartRx, uartRxPeek);  
   status = uartOpen(handle_ptr, (int8_t *)uart_port, uart_baud_rate,  
                     uart_flow_control, DEFAULT_UART_TIMEOUT);  
   if (status < HANDLE_VALUE_MIN) {  
     app_log_error("Failed to open serial connection (%d)"  
                   APP_LOG_NL, status);  
     exit(EXIT_FAILURE);  
   }  
   uartFlush(handle_ptr);  
   ```
3. Reset NCP Target to ensure it gets into a defined state. Once the chip successfully boots, the `sl_bt_evt_system_boot_id` event should be received.  
   ```C  
   // This command is equivalent with sl_bt_system_reboot  
   uint8_t reboot_command[] = { 0x20, 0x00, 0x01, 0x1f };  
     
   if (boot_retry_count < NCP_REBOOT_RETRY_COUNT) {  
   app_log_info("Rebooting NCP target (%d)..." APP_LOG_NL, boot_retry_count);  
   boot_retry_count++;  
   (void)host_comm_tx(sizeof(reboot_command), reboot_command);  
   sl_status_t sc = app_timer_start(timer,  
                                   NCP_REBOOT_TIMEOUT_RETRY_MS,  
                                   on_boot_timer_expire,  
                                   NULL,  
                                   false);  
   app_assert_status(sc);  
   } else {  
   app_assert(false, "NCP target unreachable.");  
   }  
   ```
4. The `sl_bt_step` function will be called from the main loop.  It checks for any NCP Target events and forwards them to the handler function.  
   ```C  
   // Poll Bluetooth stack for an event and call event handler  
   static void sl_bt_step(void)  
   {  
     sl_bt_msg_t evt;  
     // Pop (non-blocking) a Bluetooth stack event from event queue.  
     sl_status_t status = sl_bt_pop_event(&evt);  
     if (status != SL_STATUS_OK) {  
       return;  
     }  
     sl_bt_on_event(&evt);  
   }   
   ```
5. Process the incoming NCP target events.  
   ```C  
   /**************************************************************************//**  
   * Bluetooth stack event handler.  
   * This overrides the default weak implementation.  
   *  
   * @param[in] evt Event coming from the Bluetooth stack.  
   *****************************************************************************/  
   void sl_bt_on_event(sl_bt_msg_t *evt)  
   {  
     sl_status_t sc;  
     bd_addr address;  
     uint8_t address_type;  
     uint8_t system_id[8];  
     
     switch (SL_BT_MSG_ID(evt->header)) {  
       // -------------------------------  
       // This event indicates the device has started and the radio is ready.  
       // Do not call any stack command before receiving this boot event!  
       case sl_bt_evt_system_boot_id:  
         // Extract unique ID from BT Address.  
         sc = sl_bt_gap_get_identity_address(&address, &address_type);  
         app_assert_status(sc);  
         app_log_info("Bluetooth %s address: %02X:%02X:%02X:%02X:%02X:%02X" APP_LOG_NL,  
                     address_type ? "static random" : "public device",  
                     address.addr[5],  
                     address.addr[4],  
                     address.addr[3],  
                     address.addr[2],  
                     address.addr[1],  
                     address.addr[0]);  
     
         // Pad and reverse unique ID to get System ID.  
         system_id[0] = address.addr[5];  
         system_id[1] = address.addr[4];  
         system_id[2] = address.addr[3];  
         system_id[3] = 0xFF;  
         system_id[4] = 0xFE;  
         system_id[5] = address.addr[2];  
         system_id[6] = address.addr[1];  
         system_id[7] = address.addr[0];  
     
         sc = sl_bt_gatt_server_write_attribute_value(gattdb_system_id,  
                                                     0,  
                                                     sizeof(system_id),  
                                                     system_id);  
         app_assert_status(sc);  
     
         // Create an advertising set.  
         sc = sl_bt_advertiser_create_set(&advertising_set_handle);  
         app_assert_status(sc);  
     
         // Generate data for advertising  
         sc = sl_bt_legacy_advertiser_generate_data(advertising_set_handle,  
                                                   sl_bt_advertiser_general_discoverable);  
         app_assert(sc == SL_STATUS_OK,  
                   "[E: 0x%04x] Failed to generate advertising data\n",  
                   (int)sc);  
     
         // Set advertising interval to 100ms.  
         sc = sl_bt_advertiser_set_timing(  
           advertising_set_handle,  
           160, // min. adv. interval (milliseconds * 1.6)  
           160, // max. adv. interval (milliseconds * 1.6)  
           0,   // adv. duration  
           0);  // max. num. adv. events  
         app_assert_status(sc);  
         // Start general advertising and enable connections.  
         sc = sl_bt_legacy_advertiser_start(advertising_set_handle,  
                                           sl_bt_legacy_advertiser_connectable);  
         app_assert_status(sc);  
         app_log_info("Started advertising." APP_LOG_NL);  
         break;  
     
       // -------------------------------  
       // This event indicates that a new connection was opened.  
       case sl_bt_evt_connection_opened_id:  
         app_log_info("Connection opened." APP_LOG_NL);  
         break;  
     
       // -------------------------------  
       // This event indicates that a connection was closed.  
       case sl_bt_evt_connection_closed_id:  
         app_log_info("Connection closed." APP_LOG_NL);  
     
         // Generate data for advertising  
         sc = sl_bt_legacy_advertiser_generate_data(advertising_set_handle,  
                                                   sl_bt_advertiser_general_discoverable);  
         app_assert(sc == SL_STATUS_OK,  
                   "[E: 0x%04x] Failed to generate advertising data\n",  
                   (int)sc);  
     
         // Restart advertising after client has disconnected.  
         sc = sl_bt_legacy_advertiser_start(advertising_set_handle,  
                                           sl_bt_legacy_advertiser_connectable);  
         app_assert_status(sc);  
         app_log_info("Started advertising." APP_LOG_NL);  
         break;  
     
       ///////////////////////////////////////////////////////////////////////////  
       // Add additional event handlers here as your application requires!      //  
       ///////////////////////////////////////////////////////////////////////////  
     
       // -------------------------------  
       // Default event handler.  
       default:  
         break;  
     }  
   }  
   ```

##### Custom API Support

This chapter introduces how to implement a custom binary protocol between an NCP target and host using specific features of  the BGAPI. The Silicon Labs Bluetooth SDK  provides the following commands and events for that purpose:

- `cmd_user_message_to_target`
- `evt_user_message_to_host`

The command and event details are documented in the API reference manual.

The `cmd_user_message_to_target` command can be used by an NCP host to send a message to the target application on a device. To send a custom message with this API command, the host must send the byte sequence specified below to the target. Byte 4..255 can be the custom message itself.

The custom message can be interpreted in any specific way, but the default implementation uses the first byte as the custom command type, and the rest handled as parameters for that command. This is the recommended way of using custom APIs.

Command Byte Sequence:

|Byte Number|Value/Type|Description|
|---|---|---|
|0|0x20|Message type: Command|
|1|payload length|The size of the uint8array struct including its length and payload members.|
|2|0xFF|Message class: User messaging|
|3|0x00|Message ID|
|4..255|uint8array|The user message. The first byte is the length of the message. The next bytes are the message bytes|

Once the target receives this byte sequence, it must response with the byte sequence specified below. Byte 6 to 255 can be used for the custom response.

Response Byte Sequence:

|Byte Number|Value/Type|Description|
|---|---|---|
|0|0x20|Message type: Command|
|1|payload length|The size of the uint8array struct including its length and payload members.|
|2|0xFF|Message class: User messaging|
|3|0x00|Message ID|
|4-5|uint16|Result code: 0: Success / Non-0: An error occurred|
|6..255|uint8array|The user message. The first byte is the length of the message. The next bytes are the response message bytes.|

Additionally, the `evt_user_message_to_host event` can be used by the target to send a message to NCP host. The target must send the byte sequence specified below. Byte 4..255 can be the custom message itself.

Event Byte Sequence:

|Byte Number|Value/Type|Description|
|---|---|---|
|0|0xA0|Message type: Event|
|1|payload length|The size of the uint8array struct including its length and payload members.|
|2|0xFF|Message class: User messaging|
|3|0x00|Message ID|
|4..255|uint8array|The user message. The first byte is the length of the message. The next bytes are the message bytes.|

###### ncp_user_command_cb

The NCP Target calls `sl_ncp_user_cmd_message_to_target_cb` if a command ID equals to `sl_bt_cmd_user_message_to_target_id`.

You can find the default implementation of `sl_ncp_user_cmd_message_to_target_cb` in the _app.c_ file and the declaration it in the _ncp.h_ file.

In the first case, the Target echoes back the command to the Host, as a reply for the `USER_CMD_1` command.

`USER_CMD_2` sends back the same command as an event, to demonstrate how events can be sent to the Host.

```C
sl_ncp_app_user_cmd_message_to_target_cb(void *data)
{
  uint8array *cmd = (uint8array *)data;

  switch (cmd->data[0]) {
    // -------------------------------
    // Example: user command 1.
    case USER_CMD_1_ID:
      //////////////////////////////////////////////
      // Add your user command handler code here! //
      //////////////////////////////////////////////

      // Send response to user command 1 to NCP host.
      // Example: sending back received command.
      sl_ncp_user_cmd_message_to_target_rsp(SL_STATUS_OK, cmd->len, cmd->data);
      break;

    // -------------------------------
    // Example: user command 2.
    case USER_CMD_2_ID:
      //////////////////////////////////////////////
      // Add your user command handler code here! //
      //////////////////////////////////////////////

      // Send response to user command 2 to NCP host.
      // Example: sending back received command.
      sl_ncp_user_cmd_message_to_target_rsp(SL_STATUS_OK, cmd->len, cmd->data);
      // Send user event too.
      // Example: sending back received command as an event.
      sl_ncp_user_evt_message_to_host(cmd->len, cmd->data);
      break;

    // -------------------------------
    // Unknown user command.
    default:
      // Send error response to NCP host.
      sl_ncp_user_cmd_message_to_target_rsp(SL_STATUS_FAIL, 0, NULL);
      break;
  }
}

```

###### Host Side

The example below shows how to send custom APIs from the Host side, and how to handle custom events. The custom command structure is defined as a struct for easier access:

```C
#define USER_CMD_2_ID     0x02
#define DATA_LENGTH       0x02
PACKSTRUCT(struct user_cmd {
  uint8_t hdr;
  uint8_t data[DATA_LENGTH];
});
typedef struct user_cmd user_cmd_t;
```

The command packet is filled with Command ID and custom data, and then sent with the sl_bt_user_message_to_target. The response is logged to the console.

```C
user_command.hdr = USER_CMD_2_ID;
user_command.data[0] = 0xAA;
user_command.data[1] = 0xBB;
sl_bt_user_message_to_target(sizeof(user_command), (uint8_t*)&user_command, sizeof(user_command),
                               &resp_length, (uint8_t*)&custom_response);
app_log_info("Custom response received. Response data: %x %x", custom_response->data[0],
 custom_response->data[1]);
```

If the target also sends an event, it can be handled from the main event handler loop as any other NCP events. The `evt->data.evt_user_message_to_host.message.data` field contains the user message:

```C
case sl_bt_evt_user_message_to_host_id:
custom_event = (user_cmd_t*)evt->data.evt_user_message_to_host.message.data;
app_log_info("Custom event received. Response data: %x %x", custom_event->data[0], custom_event->data[1]);
break;
```

##### Adding New Attributes to the GATT Database

This page describes how to add a custom Bluetooth service to the **NCP** example using the dynamic GATT API. The service added here has one characteristic to receive data. When the central device (tablet/phone) writes this characteristic, the peripheral (starter kit – NCP Target) forwards this data to the NCP Host. The NCP Host prints out the actual data to the PC console.

![new service to NCP](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-new-service-to-ncp-empty.png)

To implement this application, you need to make these changes:

- Modify the GATT database in the Host project
- Handle the GATT change event (sl_bt_evt_gatt_server_attribute_value) in the Host project

###### Adding New Attributes Using the Configuration File

Beginning with SDK version 3.3, the NCP host sample applications contains a .btconf file with a basic GATT configuration. This configuration can be edited with the GATT Configurator. Although PC host examples are not handled by Simplicity Studio, .btconf files can still be edited individually. Open the Simplicity IDE perspective in Simplicity Studio and drag-and-drop the .btconf file onto the editor area. GATT Configurator will automatically open. Edit the file as described in [GATT Configurator User’s Guide for Bluetooth SDK v3.x](https://docs.silabs.com/bluetooth/latest/gatt-configurator-users-guide-ble-btmesh/) and save it. To be compatible with the code snippets, create a custom service and then add a custom characteristic with the following properties:

- ID:  my_data
- Read, Write, Indicate
- Value length: 20 bytes

Once the .btconf file is saved it must be turned into source code by running `make gattdb`. Run this command in the root folder of your example, where you can find the makefile. Note that the generator script requires installing Python 3 and the Jinja2 package by calling `pip install jinja2`.

![make gattdb](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-v08-make-code-snippet.png)

The output (gatt_db.c / gatt_db.h) is located in the autogen folder. These values will be used as parameters for the dynamic GATT APIs. The database will be created (that is, built on the NCP target with the dynamic GATT API) automatically in the initialization phase before the boot event is sent to the application. The application is still able update the GATT database with the dynamic GATT commands, as described in the next section.

> **Note**: If your database contains included services, the included ones need to be defined before the ones including them.

###### Adding New Attributes Using the Dynamic GATT API

The GATT database can be extended with the APIs provided by the Dynamic GATT Configurator component. For more details, see the Bluetooth API reference manual on [docs.silabs.com](https://docs.silabs.com/), section "GATT Database."

In the code snippet below, the custom service and characteristic is added to the database. The service will be a primary service, defined with a 16-byte long UUID, and it will be advertised.

The characteristic has the following properties:

- Read, Write, Indicate
- Valuelength: 20 bytes
- Valuemax length: 20 bytes
- 16-bytelong UUID

The service and the characteristic can be added any time after the boot event was received, but adding them in the boot event handler is suggested.

```C
uint8_t uuid_service[16] = {…} //define your 128bit service UUID, you can use a random number
uint8_t uuid_characteristic[16] = {…} //define your 128bit characteristic UUID

//create a session for the database update
sl_bt_gattdb_new_session(&session);
//add our service to the database, as an advertised primary service
sl_bt_gattdb_add_service(session, sl_bt_gattdb_primary_service, SL_BT_GATTDB_ADVERTISED_SERVICE, 16,
                 uuid_service, &service);
//define the following properties: read, write, indicate
property = (SL_BT_GATTDB_CHARACTERISTIC_READ | SL_BT_GATTDB_CHARACTERISTIC_INDICATE |
                 SL_BT_GATTDB_CHARACTERISTIC_WRITE);
//add our characteristic to the service
sl_bt_gattdb_add_uuid128_characteristic(session, service, property, 0, 0, uuid_characteristic,
                 sl_bt_gattdb_fixed_length_value, 20, 20, &value, &characteristic);
//activate the new service
sl_bt_gattdb_start_service(session, service);
//activate the new characteristic
sl_bt_gattdb_start_characteristic(session, characteristic);
//store the handle of the characteristic for future reference
gattdb_my_data = characteristic;
//save changes and close the database editing session
sl_bt_gattdb_commit(session);
```

> **Note**: The handle returned while adding a service or characteristic is not always the final one. It is only valid until `sl_bt_gattdb_commit` is called. You can get the actual final handle with the API call `sl_bt_gatt_server_find_attribute()`.

###### Responding to the GATT Change Event

1. Add the callback function that reacts to the GATT change. In this case, it prints out the content of the characteristic.  
   ```C  
   void AttrValueChanged_my_data(uint8array *value)  
   {  
     uint8_t i;  
     for (i = 0; i < value->len; i++){  
         app_log("my_data[%d] = 0x%x \r\n",i,value->data[i]);  
     }  
     app_log("\r\n");  
   }  
   ```
2. Add the `sl_bt_evt_gatt_server_attribute_value_id` event to the switch case.  
   ```C  
   case sl_bt_evt_gatt_server_attribute_value_id:  
     // Check if the event is because of the my_data changed by the remote GATT client  
     if ( gattdb_my_data == evt->data.evt_gatt_server_attribute_value.attribute ){  
       // Call my handler  
      AttrValueChanged_my_data(&(evt->data.evt_gatt_server_attribute_value.value));  
      }  
   break;  
   ```

> **Note**: If you edited the .btconf file, `gattdb_my_data` is defined in _gatt_db.h_. If you used the dynamic GATT API, `gattdb_my_data` is defined in the application as in the provided code snippet.

Now you can rebuild the host application. See the build process with MinGW in [Building the NCP Host Examples on Windows](03-ncp-host-development#building-the-ncp-host-examples-on-windows).

###### Testing

1. Start the host application from the _\exe_ folder.
2. Once the PC is connected to WSTK (via UART), the WSTK starts advertising on Bluetooth.
3. If you connect via tablet/phone you can write the newly created `my_data` characteristic in the GATT. For this, you can use the Simplicity Connect app provided by Silicon Labs.
4. Browse to the `my_data` characteristic and write something to it. The data will be printed by the host application.  
   ![my data characteristic](/bluetooth-network-coprocessor-mode/11.0.1/images/an1259-my-data-characteristic.png)

#### Enabling a Radio Co-Processor using the Bluetooth HCI Function

##### Enabling a Radio Co-Processor using the Bluetooth® LE HCI Function

> **Note: This section replaces _AN1328: Enabling a Radio Co-Processor using the Bluetooth® LE HCI Function_. Further updates to this application note will be provided here**.

This document gives a short overview of the standard Host Controller Interface (HCI) and how to use it with Silicon Labs’ Bluetooth LE controller. First it briefly describes the HCI layer, the supported features, and explains the difference between a Network Co-Processor (NCP) and a Radio Co-Processor (RCP) project. It then lists the available vendor-specific commands and shows how to get started with the RCP Example project included in the Bluetooth LE SDK.

This document assumes that you have installed Simplicity Studio 5 and the Bluetooth LE SDK, and that you are familiar with creating, configuring, building, and flashing projects. If not, see the [Bluetooth SDK Getting Started Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-getting-started-overview/).

##### Introduction

The HCI is described in detail in Bluetooth Core Specification, Vol 4: Host Controller Interface. In the Silicon Labs software and documentation, the HCI is also referred to as RCP (Radio Co-Processor).

The HCI is a standardized way for Bluetooth host and controller to communicate with each other. Since the interface is standard, the host and controller can be from different vendors.

The following figure illustrates the layered communication mechanism between the Bluetooth Controller and Host protocol stacks, and the user application.

![Bluetooth High-Level Components](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image1.png)

The lowest layer between the host and controller communication is the HCI Transport. Currently, the RCP (Radio Co-Processor) sample applications support the HCI Three-Wire UART, or UART (Universal Asynchronous Receiver-Transmitter) as the HCI transport layer using either:

- Bluetooth SIG’s UART (H4) transport protocol or
- Silicon Labs’ proprietary CPC (Co-Processor Communication) protocol.

The next layer is the HCI, which provides set of commands and events, and ACL data packets. The Host side sends commands to the controller. The commands are used to start advertising or scanning, establish connection to another Bluetooth device, read status information from the controller, and so on.

The events are sent from the Controller side to the Host. The events are used as a response to commands or to indicate various events in the controller such as scanning reports, connection establishment or closing, and various failures.

The ACL (Asynchronous ConnectionLess) data packets are used to deliver user application data between the host and controller in both directions. The data packets are exchanged between Bluetooth devices.

The Silicon Labs Bluetooth LE Controller does not support SCO (Synchronous Connection Oriented) and ISOC (Isochronous Channels) modes, and the related HCI messages are not supported.

The Bluetooth specification defines three types of controllers: Low Energy (LE), BR/EDR (classic) and AMP (alternate MAC and PHY). Silicon Labs supports only the LE controller.

The Silicon Labs Bluetooth LE Controller runs on EFR32 Radio Co-Processors, and external Bluetooth Host stacks can communicate with the controller over the HCI. This is also called RCP mode, and is illustrated in the following figure.

![RCP Mode](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image2.png)

Silicon Labs’ previously provided solutions, NCP (Network Co-Processor) mode and SoC mode, are illustrated in figure NCP Mode and figure SoC Mode below, respectively. In the NCP mode the Silicon Labs Host and Controller protocol stacks run on the EFR32 Radio Co-Processor. The application runs on a separate processor and communicates with Silicon Labs Bluetooth stack over the proprietary NCP protocol (BGAPI), which is exposed to the application via UART.

![NCP Mode](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image3.png)

In SoC mode the application runs on the same processor as the Silicon Labs Bluetooth LE protocol stacks. The application communicates with the Bluetooth LE protocol stack via BGAPI.

![SoC Mode](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image4.png)

##### Enabling HCI Functionality

###### Using an Example Application

The Gecko SDK suite includes the **Bluetooth – RCP** and **Bluetooth – RCP CPC** example applications, which can be used to create an HCI-capable Bluetooth Controller application that can be run in RCP mode. An external Bluetooth Host protocol stack, such as Linux BlueZ, can use the Bluetooth Controller via HCI. BlueZ provides interactive control tools such as _bluetoothctl_ to send HCI commands to the controller. The basic usage of _bluetoothctl_ is documented in the [readme](https://github.com/SiliconLabsSoftware/sisdk-release/blob/sisdk-2025.12/bluetooth_le_app/example/bt_rcp/readme.md) of the **Bluetooth – RCP** example project.

To use the example applications, select the target device in the Debug Adapters view, find the **Bluetooth – RCP** or **Bluetooth – RCP CPC** example on the EXAMPLE PROJECTS & DEMOS tab, and create the project.

**Bluetooth – RCP** creates an RCP project that uses Bluetooth SIG’s UART (H4) transport protocol as the transport protocol.

**Bluetooth – RCP CPC** creates a project that uses Silicon Labs’ proprietary CPC (Co-Processor Communication) protocol as the transport protocol. The latter one is useful in DMP (Dynamic Multi-protocol) use cases, when the host device communicates with multiple protocol stacks running on the Radio Co-Processor, but it may also be useful if you need a robust and secure transport protocol. For more information on CPC, refer to [https://github.com/SiliconLabs/cpc-daemon/blob/main/readme.md](https://github.com/SiliconLabs/cpc-daemon/blob/main/readme.md). To learn more about the DMP use case, see [Running Zigbee, OpenThread, and Bluetooth Concurrently on a Linux Host with a Multiprotocol RCP](https://docs.silabs.com/multiprotocol/latest/multiprotocol-solution-linux/).

![Create Bluetooth RCP project](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image5.png)

After building the project, flash it to the target device as with any other project:

![Flash to the target device](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image6.png)

Finally, attach the Bluetooth controller to your Bluetooth host stack using hciattach, and reset the device before issuing commands.

The application configuration can be reviewed and changed in the Project Configurator under the SOFTWARE COMPONENTS tab. To find a specific component, begin typing its name in the Search field.

###### Transport layer configuration

###### UART (heading level 7)

By default, the application uses UART as the HCI Transport layer. The UART has been configured as follows.

- Hardware flow control: enabled
- Speed: 115200 kbps
- Data bits: 8
- Parity bit: N
- Stop bits: 1

The default configuration can be changed with the **vcom** component.

![vcom component](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image7.png)

This will generate the values to the header file _sl_uartdrv_usart_vcom_config.h_. Especially for high-speed communication over UART, enabling hardware flow control and increasing the baud rate to 921600 is strongly recommended.  Instructions for setting the hardware flow control in the WSTKs (Wireless Starter Kits) are given in Section [Configuring Hardware Flow Control In the WSTK](05-configuring-hardware-flow-control-in-the-wstk#configuring-hardware-flow-control-in-the-wstk). Similarly. the baud rate can be changed.

Note that by default nearly all HCI events sent from the controller have been filtered out. The events to be filtered or passed from the controller to host can be configured using the HCI commands _HCI_LE_Set_Event_Mask_ and _HCI_Set_Event_Mask_.

###### Three-Wire UART (heading level 7)

> **Note**: To use the Three-Wire UART transport layer (H5) for transmitting HCI messages instead of the default UART transport layer (H4), add the HCI Three-Wire UART software component to the project. This will add framing, software flow control, and data integrity check to the transport layer, making the communication via UART much more reliable.

To enable the Three-Wire UART transport layer instead of the UART, add the _HCI Three-Wire UART_ software component to the project:

![HCI Three-Wire UART component](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image8.png)

###### Required Components for HCI Capable RCP Mode Application

For the basic HCI-enabled application in the RCP mode the following components are required, and are installed in the example applications by default.

- Bluetooth Low Energy Controller Only
- Bluetooth Controller HCI
- HCI UART Handler (if H4 UART transport protocol is used)
- HCI CPC component (if CPC transport protocol is used)

Other components are required to make a reasonably functional application. For example, the **Connection** and **Advertiser** components are required (and installed by default) to make an application that can advertise and accept connections. If the application should be able to accept a large number of simultaneous connections, also including the **Even Connection Scheduling Algorithm** component is useful.

![Even Connection Scheduling Algorithm](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image9.png)

Another example is to add the ability to scan near-by devices and establish connections to them. This requires the **Connection** and **Scanning** components. For the application to use the power control functionality for connections, include the **Power Control** component.

###### Optional Components

Bluetooth LE event information can be reported to the host by installing the Bluetooth LE Event Information Reporting component. To enable event reporting, see the [vendor specific HCI commands.](04-vendor-specific-hci-commands-and-events#vendor-specific-hci-commands)

![Bluetooth LE Event Information Reporting component](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-ble-event-reporting-component.png)

##### Sleep Modes

In RCP mode two sleep modes can be activated, EM1 and EM2. To do so, install the **HCI Sleep Component**:

![HCI Sleep component](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image10.png)

The device enters EM1 when it is idle and wakes from EM1 when data is received via USART.

The device enters EM2 on receiving the `HCI_VS_Silabs_Sleep` vendor-specific command, with the sleep bit set to 1. It handles all outstanding events before entering EM2.

An interrupt triggered by received GPIO data wakes the device from EM2. The first byte wakes the device but is discarded. This means that a normal HCI command cannot be used to wake a device from sleep. The recommended way is to send a “0”. If the first byte (Packet Type) is “0”, it will be discarded in other energy modes as well.

All Bluetooth activities operate normally during sleep except HCI interface reception, which is disabled during EM2.

If a host processor must be put to sleep and events prevented from being sent over the HCI interface, then it is recommended to only have Bluetooth activities operating that do not generate any events. For example, using non-connectable advertising or periodic advertising would not generate any events over the HCI. Note that advertising must not have a timeout and must not report scan requests.

Events can also be disabled by using HCI event mask commands. Depending on the masked events, these are handled by the link layer itself. See the Bluetooth Core specification for details.

##### Vendor-Specific HCI Commands and Events

The Silicon Labs HCI and Controller support some vendor-specific commands and events as described in the following two sections. Additional vendor-specific commands can also be implemented, as described in [Custom Commands](#custom-commands).

###### Vendor-Specific HCI Commands

The Silicon Labs HCI and Controller support the following vendor-specific HCI commands.

- [HCI VS_SiliconLabs_Forcefully_Kill_Connection – Command](#hci-vs-siliconlabs-forcefully-kill-connection-command)
- [HCI VS_SiliconLabs_Forcefully_Kill_Connection – Command Parameters](#hci-vs-siliconlabs-forcefully-kill-connection-command-parameters)
- [HCI_VS_SiliconLabs_Set_Connection_Config_Bits – Command](#hci-vs-siliconlabs-set-connection-config-bits-command)
- [HCI_VS_SiliconLabs_Set_Connection_Config_Bits – Command Parameters](#hci-vs-siliconlabs-set-connection-config-bits-command-parameters)
- [HCI_VS_SiliconLabs_Clear_Connection_Config_Bits – Command](#hci-vs-siliconlabs-clear-connection-config-bits-command)
- [HCI_VS_SiliconLabs_Configure – Command](#hci-vs-siliconlabs-configure-command)
- [HCI_VS_SiliconLabs_Configure – Command Parameters](#hci-vs-siliconlabs-configure-command-parameters)
- [HCI_VS_SiliconLabs_Configure – Parameter Key](#hci-vs-siliconlabs-configure-parameter-key)
- [HCI_VS_SiliconLabs_Get_Timing – Command](#hci-vs-siliconlabs-get-timing-command)
- [HCI_VS_SiliconLabs_Get_Timing – Command Parameters](#hci-vs-siliconlabs-get-timing-command-parameters)
- [HCI_VS_SiliconLabs_Config_Flags – Command](#hci-vs-siliconlabs-config-flags-command)
- [HCI_VS_SiliconLabs_Config_Flags – Command Parameters](#hci-vs-siliconlabs-config-flags-command-parameters)
- [HCI_VS_SiliconLabs_Get_Counters – Command](#hci-vs-siliconlabs-get-counters-command)
- [HCI_VS_SiliconLabs_Get_Counters – Command Parameters](#hci-vs-siliconlabs-get-counters-command-parameters)
- [HCI_VS_Silabs_Sleep – Command](#hci-vs-silabs-sleep-command)
- [HCI_VS_Silabs_Sleep – Command Parameters](#hci-vs-silabs-sleep-command-parameters)
- [HCI_VS_Silabs_Set_Min_Max_TX_Power – Command](#hci-vs-silabs-set-min-max-tx-power-command)
- [HCI_VS_Silabs_Set_Min_Max_TX_Power – Command Parameters](#hci-vs-silabs-set-min-max-tx-power-command-parameters)
- [HCI_VS_Silabs_Set_Cte_Transmit_Enable – Command](#hci-vs-silabs-set-cte-transmit-enable-command)
- [HCI_VS_Silabs_Set_Cte_Transmit_Enable – Command Parameters](#hci-vs-silabs-set-cte-transmit-enable-command-parameters)
- [HCI_VS_Silabs_Set_Iq_Sampling_Enable – Command](#hci-vs-silabs-set-iq-sampling-enable-command)
- [HCI_VS_Silabs_Set_Iq_Sampling_Enable – Command Parameters](#hci-vs-silabs-set-iq-sampling-enable-command-parameters)
- [HCI_VS_Silabs_Read_Current_TX_Power_Configuration – Command](#hci-vs-silabs-read-current-tx-power-configuration-command)
- [HCI_VS_Silabs_Read_Current_TX_Power_Configuration – Command Parameters](#hci-vs-silabs-read-current-tx-power-configuration-command-parameters)
- [HCI_VS_Silabs_Enter_Bootloader_Mode – Command](#hci-vs-silabs-enter-bootloader-mode-command)
- [HCI_VS_SiliconLabs_Set_Advertising_Config_Bits – Command](#hci-vs-siliconlabs-set-advertising-config-bits-command)
- [HCI_VS_SiliconLabs_Set_Advertising_Config_Bits – Command Parameters](#hci-vs-siliconlabs-set-advertising-config-bits-command-parameters)
- [HCI_VS_SiliconLabs_Clear_Advertising_Config_Bits – Command](#hci-vs-siliconlabs-clear-advertising-config-bits-command)
- [HCI_VS_SiliconLabs_Clear_Advertising_Config_Bits – Command Parameters](#hci-vs-siliconlabs-clear-advertising-config-bits-command-parameters)
- [HCI_VS_SiliconLabs_Set_Max_Low_Tx_Power – Command](#hci-vs-siliconlabs-set-max-low-tx-power-command)
- [HCI_VS_SiliconLabs_Set_Max_Low_Tx_Power – Command Parameters](#hci-vs-siliconlabs-set-max-low-tx-power-command-parameters)
- [HCI_VS_SiliconLabs_Allocate_Connections – Command](#hci-vs-siliconlabs-allocate-connections-command)
- [HCI_VS_SiliconLabs_Allocate_Connections – Command Parameter](#hci-vs-siliconlabs-allocate-connections-command-parameter)
- [HCI_VS_SiliconLabs_Allocate_Advertisers – Command](#hci-vs-siliconlabs-allocate-advertisers-command)
- [HCI_VS_SiliconLabs_Allocate_Advertisers – Command Parameter](#hci-vs-siliconlabs-allocate-advertisers-command-parameter)
- [HCI_VS_SiliconLabs_Allocate_Addresses – Command](#hci-vs-siliconlabs-allocate-addresses-command)
- [HCI_VS_SiliconLabs_Allocate_Addresses – Command Parameter](#hci-vs-siliconlabs-allocate-addresses-command-parameter)
- [HCI_VS_SiliconLabs_Allocate_PeriodicAdv – Command](#hci-vs-siliconlabs-allocate-periodicadv-command)
- [HCI_VS_SiliconLabs_Allocate_PeriodicAdv – Command Parameter](#hci-vs-siliconlabs-allocate-periodicadv-command-parameter)
- [HCI_VS_SiliconLabs_Allocate_PeriodicScan – Command](#hci-vs-siliconlabs-allocate-periodicscan-command)
- [HCI_VS_SiliconLabs_Allocate_PeriodicScan – Command Parameter](#hci-vs-siliconlabs-allocate-periodicscan-command-parameter)
- [HCI_VS_SiliconLabs_Deinit – Command](#hci-vs-siliconlabs-deinit-command)
- [HCI_VS_SiliconLabs_MemBufResize – Command](#hci-vs-siliconlabs-membufresize-command)
- [HCI_VS_SiliconLabs_MemBufResize – Command Parameters](#hci-vs-siliconlabs-membufresize-command-parameters)
- [HCI_VS_SiliconLabs_ExtScanPHYsAllowed – Command](#hci-vs-siliconlabs-extscanphysallowed-command)
- [HCI_VS_SiliconLabs_ExtScanPHYsAllowed – Command Parameters](#hci-vs-siliconlabs-extscanphysallowed-command-parameters)
- [HCI_VS_SiliconLabs_Set_Public_Address – Command](#hci-vs-siliconlabs-set-public-address-command)
- [HCI_VS_SiliconLabs_Set_Public_Address – Command Parameters](#hci-vs-siliconlabs-set-public-address-command-parameters)
- [HCI_VS_SiliconLabs_Periodic_Advertising_Update_Sync_Parameters – Command](#hci-vs-siliconlabs-periodic-advertising-update-sync-parameters-command)
- [HCI_VS_SiliconLabs_Periodic_Advertising_Update_Sync_Parameters – Command Parameters](#hci-vs-siliconlabs-periodic-advertising-update-sync-parameters-command-parameters)
- [HCI_VS_SiliconLabs_Get_Conn_Params – Command](#hci-vs-siliconlabs-get-conn-params-command)
- [HCI_VS_SiliconLabs_Get_Conn_Params – Command Parameters](#hci-vs-siliconlabs-get-conn-params-command-parameters)
- [HCI_VS_SiliconLabs_Allocate_ResolvingList – Command](#hci-vs-siliconlabs-allocate-resolvinglist-command)
- [HCI_VS_SiliconLabs_Set_CS_Antenna_Config – Command](#hci-vs-siliconlabs-set-cs-antenna-config-command)
- [HCI_VS_SiliconLabs_Set_CS_Antenna_Config – Command Parameters](#hci-vs-siliconlabs-set-cs-antenna-config-command-parameters)
- [HCI_VS_SiliconLabs_Allocate_PawrAdv – Command](#hci-vs-siliconlabs-allocate-pawradv-command)
- [HCI_VS_SiliconLabs_Allocate_PawrAdv – Command Parameter](#hci-vs-siliconlabs-allocate-pawradv-command-parameter)
- [HCI_VS_SiliconLabs_Allocate_PawrSync – Command](#hci-vs-siliconlabs-allocate-pawrsync-command)
- [HCI_VS_SiliconLabs_Allocate_PawrSync – Command Parameter](#hci-vs-siliconlabs-allocate-pawrsync-command-parameter)
- [HCI_VS_Siliconlabs_Set_Connection_Tx_Power – Command](#hci-vs-siliconlabs-set-connection-tx-power-command)
- [HCI_VS_Siliconlabs_Set_Connection_Tx_Power – Command Parameters](#hci-vs-siliconlabs-set-connection-tx-power-command-parameters)
- [HCI_VS_SiliconLabs_Read_Connection_Statistics – Command](#hci-vs-siliconlabs-read-connection-statistics-command)
- [HCI_VS_SiliconLabs_Read_Connection_Statistics – Commands Parameters](#hci-vs-siliconlabs-read-connection-statistics-commands-parameters)
- [HCI_VS_SiliconLabs_Sniff_Connection_Packets – Command](#hci-vs-siliconlabs-sniff-connection-packets-command)
- [HCI_VS_SiliconLabs_Sniff_Connection_Packets – Command Parameters](#hci-vs-siliconlabs-sniff-connection-packets-command-parameters)
- [HCI_VS_SiliconLabs_Get_Stack_Space – Command](#hci-vs-siliconlabs-get-stack-space-command)
- [HCI_VS_SiliconLabs_Stop_Sniff_Connection_Packets – Command Parameters](#hci-vs-siliconlabs-stop-sniff-connection-packets-command-parameters)
- [HCI_VS_SiliconLabs_Stop_Sniff_Connection_Packets – Command](#hci-vs-siliconlabs-stop-sniff-connection-packets-command)
- [HCI_VS_SiliconLabs_Stop_Sniff_Connection_Packets – Command Parameters](#hci-vs-siliconlabs-stop-sniff-connection-packets-command-parameters)
- [HCI_VS_SiliconLabs_Read_AFH_Channel_Map_Quality – Command](#hci-vs-siliconlabs-read-afh-channel-map-quality-command)
- [HCI_VS_SiliconLabs_Read_AFH_Channel_Map_Quality – Command Parameters](#hci-vs-siliconlabs-read-afh-channel-map-quality-command-parameters)
- [HCI_VS_SiliconLabs_Event_Info_Reporting_Enable – Command](#hci-vs-siliconlabs-event-info-reporting-enable-command)
- [HCI_VS_SiliconLabs_Event_Info_Reporting_Enable – Command Parameters](#hci-vs-siliconlabs-event-info-reporting-enable-command-parameters)

###### HCI VS_SiliconLabs_Forcefully_Kill_Connection – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Forcefully_Kill_Connection</p>
            </td>
            <td>
                <p>0x3f/0x04</p>
            </td>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI VS_SiliconLabs_Forcefully_Kill_Connection – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Unknown Connection Identifier (0x02)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Connection_Config_Bits – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Set_Connection_Config_Bits<br><br>Configure various parameters of the Bluetooth connection.</p>
            </td>
            <td>
                <p>0x3f/0x05</p>
            </td>
            <td>
                <p>handleconfig_bits</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Connection_Config_Bits – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>config_bits</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Configure the connection. Supported values:<br>0x01 – Disable peripheral latency. Peripheral will ignore peripheral latency and treat it as being 0.<br>0x02 – Disable 1M PHY<br>0x04 – Disable 2M PHY<br>0x08 – Disable Coded PHY<br>These affect PHY-update procedure to allow selecting certain PHYs if remote end indicates support for multiple PHYs.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Unknown Connection Identifier (0x02)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Clear_Connection_Config_Bits – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Clear_Connection_Config_Bits</p>
            </td>
            <td>
                <p>0x3f/0x06</p>
            </td>
            <td>
                <p>handle<br>config_bits</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Clear_Connection_Config_Bits – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>config_bits</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Clears the connection configuration. The supported values are the same as the <code>config_bits</code> in <code>HCI_VS_SiliconLabs_Set_Connection_Config_Bits</code> command.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x00),<br>Unknown Connection Identifier (0x02)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Configure – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Configure<br><br>Configure various aspects in Silicon Labs Bluetooth Controller.</p>
            </td>
            <td>
                <p>0x3f/0x07</p>
            </td>
            <td>
                <p>key,<br>length,<br>data</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Configure – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>key</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Configuration parameter key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>configuration data length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Length of the configuration data field.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>data</p>
            </td>
            <td>
                <p>0-255</p>
            </td>
            <td>
                <p>Configuration data related to the configuration parameter (key).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br> Invalid HCI Command Parameters (0x12),<br> Unknown Advertising Identifier (0x42),<br> Invalid LL Parameters (0x1E),<br> Unsupported Feature or Parameter Value (0x11),<br> Unspecified Error (0x1F)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Configure – Parameter Key (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Configuration parameter key [key value]</p>
            </th>
            <th>
                <p>Parameters [size]</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>CONFIG_KEY_HALT [1]</p>
            </td>
            <td>
                <p>halt [1]</p>
            </td>
            <td>
                <p>Halt (1) or resume (0) the radio</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_PRIORITY_RANGE [2]</p>
            </td>
            <td>
                <p>rail_mapping_offset [2],<br>rail_mapping_range[2]</p>
            </td>
            <td>
                <p>Sets the RAIL priority_mapping offset field of the link layer priority configuration structure to the first byte of the value field. Used with multiprotocol.<br>See Dynamic Multiprotocol User’s Guide</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_SCAN_CHANNELS [3]</p>
            </td>
            <td>
                <p>channel_map [1]</p>
            </td>
            <td>
                <p>Set primary channels to be scanned. Only the three least significant bits are meaningful. 0x1 = Channel 37, 0x2 = Channel 38, 0x4 = Channel 39</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_SET_FLAGS [4]</p>
            </td>
            <td>
                <p>flags [4]</p>
            </td>
            <td>
                <p>Sets the link layer configuration flags. The value is a little endian 32-bit integer. Currently supported flag values: <br>0x00000001 – Disable Automatic Feature Exchange when peripheral, <br>0x00000002 – Disable Automatic Feature Exchange when central, <br>0x00000004 – Enable Completed Packets Event, <br>0x00000008 – Enable Advertisement Channel Info, <br>0x00000040 – Enable Raw IQ Sampling mode, <br>0x00000400 – Enable Host Session Key Generation, <br><br>0x00008000 – Disable Auto Data Length Update, <br>0x00020000 – Enable connection event extension in multitask situations to improve connection throughput, <br>0x00040000 – Enable the scanner to abort the reception of a packet if it will conflict with another scheduled higher priority task, <br>0x00080000 – Enable inaccurate sleep clock</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_CLR_FLAGS [5]</p>
            </td>
            <td>
                <p>flags [4]</p>
            </td>
            <td>
                <p>Clear the link layer configuration flags. The supported values are the same as with CONFIG_KEY_SET_FLAGS.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_SET_AFH_INTERVAL [7]</p>
            </td>
            <td>
                <p>scanning_interval [1]</p>
            </td>
            <td>
                <p>Set the AFH scanning interval. The unit is 0.1 secs.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_PERIODIC_ADV_STATUS_EVENT [8]</p>
            </td>
            <td>
                <p>handle [1],<br>enable [1]</p>
            </td>
            <td>
                <p><strong>handle</strong>: Advertising handle<br><strong>enable</strong>: Enable (1) or disable (0) status event on the sync advertiser</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_SET_PRIORITY_TABLE [9]</p>
            </td>
            <td>
                <p>scan_min [1],<br>scan_max [1],<br>adv_min [1],<br>adv_max [1],<br>conn_min [1],<br>conn_max [1],<br>init_min [1],<br>init_max [1],<br>rail_mapping_offset [1],<br>rail_mapping_range [1],<br>reserved [1],<br>adv_step [1],<br>scan_step [1],<br>pawr_tx_min [1],<br>pawr_tx_max [1],<br>pawr_rx_min [1],<br>pawr_rx_max [1]</p>
            </td>
            <td>
                <p>Configure link layer task priorities.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>(1) CONFIG_KEY_SET_RX_PACKET_FILTERING [10]</p>
            </td>
            <td>
                <p>filter_count [1],<br>filter_offset [1],<br>filter_length [1],<br>filter_bitmask [1],<br>filter_list [variable]</p>
            </td>
            <td>
                <p>Enable and configure, or disable, RX packet filtering.<br><strong>Filter_count:</strong> number of template filters in the list. At most four filters can be configured. Setting the value 0 disables the feature, and all other parameters are ignored.<br><strong>Filter_offset:</strong> offset of the field in the received link layer packet where the filters and bitmask are applied. The offset 0 is the first octet after the <em>access address</em> field.<br><strong>filterLength:</strong> The length of the filters and bitmask in octets. All filters and bitmask must be equal in length.<br><strong>Filter_bitmask:</strong> Bitmask of <em>Filter_length</em> octets used for filtering. The LSB must be the first byte. The bitmask must be given in the following format as a byte string: xx:xx:xx:xx:xx:xx<br>^- LSB MSB -^<br>The same bitmask is applied to all filter templates.<br><strong>Filter_list:</strong> Up to four filters, <em>Filter_length</em> octets each, used for filtering. The filters must be given the LSB first order. The filtering list must be given in the following format as a byte string: xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx …<br>^- LSB MSB -^ ^- LSB MSB -^ ^- field1 -^ ^- field2 -^ …</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>(1) CONFIG_KEY_SET_SIMULTANEOUS_SCANNING [11]</p>
            </td>
            <td>
                <p>enable [1]</p>
            </td>
            <td>
                <p>Enable (1) or disable (0) simultaneous 1M and Coded PHY scanning feature.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_SET_CHANNELMAP_FLAGS [12]</p>
            </td>
            <td>
                <p>flags [4]</p>
            </td>
            <td>
                <p>Configure channel map flags. Supported flag values: <br>0x01 – Enable active adaptivity, <br>0x02 – Enable passive adaptivity<br>Note: AFH must be enabled to enable adaptivity.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_POWER_CONTROL_GOLDEN_RANGE [16]</p>
            </td>
            <td>
                <p>golden_rssi_min_1m [1],<br>golden_rssi_max_1m [1],<br>golden_rssi_min_2m [1],<br>golden_rssi_max_2m [1],<br>golden_rssi_min_coded_s8 [1],<br>golden_rssi_max_coded_s8 [1],<br>golden_rssi_min_coded_s2 [1],<br>golden_rssi_max_coded_s2 [1]</p>
            </td>
            <td>
                <p>Configure the golden range values of the power control feature</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_ACTIVE_SCANNER_BACKOFF_UPPER_LIMIT [17]</p>
            </td>
            <td>
                <p>backoff_upper_limit [2]</p>
            </td>
            <td>
                <p>Sets a new maximum for the scanner backoff upper limit. This value is used to mitigate collisions between different scanners in a busy environment. Lower value implies a more aggressive scanner. <br>Set to 0 for default value (256). <br>Minimum value: 16 <br>Maximum value: 256</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_AFH_RSSI_THRESHOLD [18]</p>
            </td>
            <td>
                <p>threshold [1]</p>
            </td>
            <td>
                <p>Configure the cutoff RSSI used to block channels. <br>Default is -70 dBm.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_AFH_CHANNEL_COOLDOWN [19]</p>
            </td>
            <td>
                <p>cooldown [2]</p>
            </td>
            <td>
                <p>Configure the cooldown value when a channel is blocked. <br>Default is 8 seconds.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CONFIG_KEY_SET_REPORT_ALL_SCAN_RSPS [20]</p>
            </td>
            <td>
                <p>enable [1]</p>
            </td>
            <td>
                <p>Enable (1) or disable (0) all received SCAN_RSP reporting</p>
            </td>
        </tr>
    </tbody>
</table>

(1) Supported only by EFR32XG22/24 devices.

###### HCI_VS_SiliconLabs_Get_Timing – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Get_Timing</p>
            </td>
            <td>
                <p>0x3f/0x08</p>
            </td>
            <td>
                <p>timers<br>clear_timers</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Timing – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>timers</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Select timer.<br>0 – Start timestamp<br>1 – Maximum timer value<br>2 – Number of measurements performed<br>3 – Total accumulated time</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>clear_timers</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>0 – Do not clear timers<br>1 – Clear timers</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Unsupported Feature or Parameter Value (0x11)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Change_Periodic_Advertising_Parameters – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Change_Periodic_Advertising_Parameters</p>
            </td>
            <td>
                <p>0x3f/0x09</p>
            </td>
            <td>
                <p>advertising_handle<br>interval_min<br>interval_max<br>periodic_advertising_properties<br>num_subevents<br>subevent_interval<br>response_slot_delay<br>response_slot_spacing<br>num_response_slots<br>new_phy<br>repeat_count</p>
            </td>
            <td>
                <p>advertising_handle</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Change_Periodic_Advertising_Parameters – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>advertising_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Advertising handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>interval_min</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Minimum periodic advertising interval</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Interval_max</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Maximum periodic advertising interval</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>periodic_advertising_properties</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Bitmap describing properties.<br>- Bit 6: include TX power to advertising PDUs.<br>- All other bits reserved for future use.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>num_subevents</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Number of subevents in one event</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>subevent_interval</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Interval between subevents.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>response_slot_delay</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Delay to the first response slot.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>response_slot_spacing</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Duration of response slot to update</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>num_response_slots</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Response slots used.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>new_phy</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>New PHY for the PAwR train</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>repeat_count</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Number of times the new train parameters is sent on subevents before new set is taken into use</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Siliconlabs_Periodic_Advertising_Set_Info_Transfer – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Siliconlabs_Periodic_Advertising_Set_Info_Transfer</p>
            </td>
            <td>
                <p>0x3f/0x0a</p>
            </td>
            <td>
                <p>source_advertising_handle<br>service_data<br>target_advertising_handle<br>repeat_count<br>subevents_length<br>subevents[0]</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Siliconlabs_Periodic_Advertising_Set_Info_Transfer – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Source_advertising_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Advertising handle of the source train</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Service_data</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>A value provided by the application for use by the peer device</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Target_advertising_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Advertising handle of the target train</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Repeat_count</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Number of times the new train parameters are sent to synchroniser the new set is taken into use.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Subevents_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Number of subevents in one event to send new train info</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>subevents</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Subevents list to send new train info</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Memory Capacity Exceeded (0x7)<br>Unknown Advertising Identifier (0x42)<br>Invalid HCI Command Parameters (0x12)<br>Command Disallowed (0xC)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Config_Flags – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Config_Flags<br><br>Configure the link layer configuration flags.</p>
            </td>
            <td>
                <p>0x3f/0x11</p>
            </td>
            <td>
                <p>set<br>clr<br>read</p>
            </td>
            <td>
                <p>flags<br>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Config_Flags – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>set</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Enable the link layer flags. Supported values are listed in Table 4.9, CONFIG_KEY_SET_FLAGS.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>clr</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Clear the link layer flags.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>read</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Return link layer configuration flags with bitmask applied as determined by this field.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>flags</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Return the flags.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Unsupported Feature or Parameter Value (0x11)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Counters – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Get_Counters<br><br>Read radio counters.</p>
            </td>
            <td>
                <p>0x3f/0x12</p>
            </td>
            <td>
                <p>reset</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Counters – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>reset</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Reset counters after reading them<br>1 – yes, 0 – no.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>tx_packets</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Number of transmitted radio packets.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Rx_packets</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Number of received radio packets.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Crc_errors</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Number of received packets detected with a CRC error.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Failures</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Number of radio failures, indicating errors in radio resource scheduling.</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Sleep – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Silabs_Sleep<br>Enter EM2 sleep mode</p>
            </td>
            <td>
                <p>0x3f/0x13</p>
            </td>
            <td>
                <p>sleep</p>
            </td>
            <td>
                <p>status<br>sleep</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Sleep – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sleep</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Set to 1 to enter sleep mode. Returns 0 if sleep request unsuccessful.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Unsupported Feature or Parameter Value (0x11)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Set_Min_Max_TX_Power – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Silabs_Set_Min_Max_Tx_Power<br><br>Set minimum and maximum TX power levels.</p>
            </td>
            <td>
                <p>0x3f/0x14</p>
            </td>
            <td>
                <p>min_tx_power<br>max_tx_power</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Set_Min_Max_TX_Power – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>min_tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Minimum TX power to be used. The unit is in deci-dBm and the value must be within the range min_supported_tx_power—max_supported_tx_power. See <em>HCI_VS_SiliconLabs_Read_Current_TX_Power_Configuration</em></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>max_tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Maximum TX power to be used. The unit is in deci-dBm and the value must be within the range min_supported_tx_power—max_supported_tx_power. See <em>HCI_VS_SiliconLabs_Read_Current_TX_Power_Configuration</em></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Unspecified Error (0x1F)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Set_Cte_Transmit_Enable – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Silabs_Set_Cte_Transmit_Enable<br>Enable CTE transmission.</p>
            </td>
            <td>
                <p>0x3f/0x15</p>
            </td>
            <td>
                <p>advertising_handle<br>cte_enable<br>cte_length<br>cte_type<br>cte_count<br>switching_pattern_len<br>antenna_ids</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Set_Cte_Transmit_Enable – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>advertising_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Handle of the advertiser used for CTE transmission.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Cte_enable</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Enable (1) or disable (0) CTE transmission. If transmission is disabled, the remaining parameters can be omitted.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Cte_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Length of the CTE. Valid range 0x2 – 0x14.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Cte_type</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Type of the CTE (0x0 or 0x1).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Cte_count</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>CTE count. Valid range 0x1 – 0x10.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Switching_pattern_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Length of the switching pattern.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Antenna_ids</p>
            </td>
            <td>
                <p>variable</p>
            </td>
            <td>
                <p>Antenna identifiers for CTE transmission (number of IDs must equal switching_pattern_length).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Memory Capacity Exceeded (0x7)<br>Unknown Advertising Identifier (0x42)<br>Invalid HCI Command Parameters (0x12)<br>Unsupported Feature or Parameter Value (0x11)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Set_Iq_Sampling_Enable – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Silabs_Set_Iq_Sampling_Enable<br>Enable SiliconLabs proprietary IQ sampling.<br>For further information, refer to the following documents:<br>For further information, refer to the following documents:<br><a href="https://docs.silabs.com/rtl-lib/latest/bluetooth-direction-finding-fundamentals/">Bluetooth® Direction Finding Fundamentals</a><br><a href="https://docs.silabs.com/rtl-lib/latest/direction-finding-solution-guide/">Silicon Labs Direction-Finding Solution Quick-Start Guide</a><br><a href="https://docs.silabs.com/rtl-lib/latest/rtl-lib-app-development/">Application Development with Silicon Labs’ RTL Library</a></p>
            </td>
            <td>
                <p>0x3f/0x16</p>
            </td>
            <td>
                <p>sampling_enable<br>slot_durations<br>max_sampled_ctes<br>switching_pattern_len<br>antenna_ids</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Set_Iq_Sampling_Enable – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sampling_enable</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Enable (1) or disable (0) IQ sampling. If sampling is disabled, the remaining parameters can be omitted.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Slot_durations</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>CTE slot durations.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Max_sampled_ctes</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Currently always 0.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Switching_pattern_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Length of the switching pattern.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Antenna_ids</p>
            </td>
            <td>
                <p>variable</p>
            </td>
            <td>
                <p>Antenna identifiers for IQ sampling (number of IDs must equal switching_pattern_length).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Memory Capacity Exceeded (0x7)<br>Invalid HCI Command Parameters (0x12)<br>Unsupported Feature or Parameter Value (0x11)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Read_Current_TX_Power_Configuration – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Silabs_Read_Current_TX_Power_Configuration<br>Read the TX power range supported by the radio, and the current TX power configuration.</p>
            </td>
            <td>
                <p>0x3f/0x17</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Status<br>min_supported_tx_power<br>max_supported_tx_power<br>min_configured_tx_power<br>max_configured_tx_power<br>tx_rf_path_compensation</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Read_Current_TX_Power_Configuration – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>min_supported_tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Minimum TX power supported by the radio. The unit is deci-dBm.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Max_support_tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Maximum TX power supported by the radio. The unit is deci-dBm</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>min_configured_tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Minimum TX power configured to be used. The unit is in deci-dBm and value must be within the range min_supported_tx_power—max_supported_tx_power.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Max_configured_tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Maximum TX power configured to be used. The unit is in deci-dBm and value must be within the range min_supported_tx_power—max_supported_tx_power.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Tx_rf_path_compensation</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Currently configured TX RF path compensation in deci-dBms.</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Silabs_Enter_Bootloader_Mode – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Silabs_Enter_Bootloader_Mode<br>Set Controller to bootloader mode and reset it, for example for firmware update purposes.</p>
            </td>
            <td>
                <p>0x3f/0x18</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

Note: the controller does not reply with a Command Complete event.

###### HCI_VS_SiliconLabs_Set_Advertising_Config_Bits – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Set_Advertising_Config_Bits</p>
            </td>
            <td>
                <p>0x3f/0x19</p>
            </td>
            <td>
                <p>advertising_handle<br>config_bits</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Advertising_Config_Bits – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>advertising_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Advertising handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>config_bits</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>
                    0x00000001 – Force public address usage in advertising packets.<br>
                    0x00000002 – Include advertising address in advertising packets.<br>
                    0x00000004 – Include advertising TX power in advertising packets.
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Unknown Advertising Identifier (0x42)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Clear_Advertising_Config_Bits – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Clear_Advertising_Config_Bits</p>
            </td>
            <td>
                <p>0x3f/0x1a</p>
            </td>
            <td>
                <p>advertising_handle<br>config_bits</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Clear_Advertising_Config_Bits – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>advertising_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Advertising handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>config_bits</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>0x00000001 – Remove requirement of public address usage in advertising packets.<br>0x00000002 – Remove advertising address from advertising packets.<br>0x00000004 – Remove advertising TX power from advertising packets.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Unknown Advertising Identifier (0x42)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Max_Low_Tx_Power – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Set_Max_Low_Tx_Power<br>Set the maximum power in low-power mode for each PHY.</p>
            </td>
            <td>
                <p>0x3f/0x1b</p>
            </td>
            <td>
                <p>max_1m_low_power<br>max_2m_low_power<br>max_125k_low_power<br>max_500k_low_power</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Max_Low_Tx_Power – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>max_1m_low_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>The maximum power in low-power mode (DTS mode) for 1M PHY set to a level allowed by the region.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>max_2m_low_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>The maximum power in low-power mode (DTS mode) for 2M PHY set to a level allowed by the region.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>max_125k_low_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>The maximum power in low-power mode (DTS mode) for 125k PHY set to a level allowed by the region.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>max_500k_low_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>The maximum power in low-power mode (DTS mode) for 500k PHY set to a level allowed by the region.</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_Connections – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_Connections<br>Allocates memory for connection descriptors.</p>
            </td>
            <td>
                <p>0x3f/0x20</p>
            </td>
            <td>
                <p>num_connections</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_Connections – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>num_connections</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>The number of connections for which memory will be allocated.</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_Advertisers – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_Advertisers<br>Allocates memory for advertiser descriptors.</p>
            </td>
            <td>
                <p>0x3f/0x21</p>
            </td>
            <td>
                <p>num_advertisers</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_Advertisers – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>num_advertisers</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>The number of advertisers for which memory will be allocated.</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_Addresses – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_Addresses<br>Allocates memory for stored addresses.</p>
            </td>
            <td>
                <p>0x3f/0x22</p>
            </td>
            <td>
                <p>num_addresses</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_Addresses – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>num_addresses</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>The number of addresses for which memory will be allocated.</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PeriodicAdv – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_PeriodicAdv<br><br>Allocates memory for periodic advertiser descriptors.</p>
            </td>
            <td>
                <p>0x3f/0x23</p>
            </td>
            <td>
                <p>num_periodicadv</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PeriodicAdv – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>num_periodicadv</td>
            <td>1</td>
            <td>The number of periodic advertisers for which memory will be allocated.</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PeriodicScan – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_PeriodicScan<br><br>Allocates memory for periodic advertisement synchronization descriptors.</p>
            </td>
            <td>
                <p>0x3f/0x24</p>
            </td>
            <td>
                <p>num_periodicscan</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PeriodicScan – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>num_periodicscan</td>
            <td>1</td>
            <td>The number of periodic advertisement synchronizations for which memory will be allocated.</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Deinit – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Deinit<br><br>De-initializes the Bluetooth Controller and frees up allocated memory.</p>
            </td>
            <td>
                <p>0x3f/0x25</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_MemBufResize – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_MemBufResize<br><br>Allocates memory for periodic advertisement synchronization descriptors.</p>
            </td>
            <td>
                <p>0x3f/0x26</p>
            </td>
            <td>
                <p>buffer_memory</p>
            </td>
            <td>
                <p>status<br>buffers_allocated</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_MemBufResize – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>buffer_memory</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Size of memory to allocate</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Unspecified Error (0x1F)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>buffers_allocated</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Number of memory buffers allocated</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_ExtScanPHYsAllowed – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_ExtScanPHYsAllowed<br><br>Sets the used PHYs used for scanning for external advertisements, Aux Pointer will not be followed unless it has one of the allowed PHYs.<br>If a given PHY is not supported by the device, bt_err_invalid_command_parameters will be returned</p>
            </td>
            <td>
                <p>0x3f/0x27</p>
            </td>
            <td>
                <p>phys</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_ExtScanPHYsAllowed – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>phys</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Bitfield:<br>ll_phy_1M = 1<br>ll_phy_2M = 2,<br>ll_phy_Coded = 4</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Invalid HCI Command Parameters (0x12)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Public_Address – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>Command</th>
            <th>Command Value (OGF/OCF)</th>
            <th>Command Parameters</th>
            <th>Return Parameters</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>HCI_VS_SiliconLabs_Set_Public_Address</td>
            <td>0x3f/0x28</td>
            <td>bdaddr[6]</td>
            <td>status</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_Public_Address – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>bdaddr[6]</td>
            <td>1</td>
            <td>Address to set the public address.<br>If NULL, device unique address is used.</td>
        </tr>
        <tr>
            <td>status</td>
            <td>1</td>
            <td>Success (0x0)</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Periodic_Advertising_Update_Sync_Parameters – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Periodic_Advertising_Update_Sync_Parameters</p>
            </td>
            <td>
                <p>0x3f/0x29</p>
            </td>
            <td>
                <p>sync_handle<br>skip<br>sync_timeout</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Periodic_Advertising_Update_Sync_Parameters – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sync_handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Periodic advertising sync handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>skip</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>New value for the skip parameter</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sync_timeout</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>New timeout value</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Invalid HCI Command Parameters (0x12),<br>Command Disallowed (0xC),<br>Unknown Advertising Identifier (0x42)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Conn_Params – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Get_Conn_Params<br><br>Get the Bluetooth connection parameters.</p>
            </td>
            <td>
                <p>0x3f/0x2a</p>
            </td>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>status<br>interval<br>access_address,<br>crc_init.<br>start_time,<br>event_counter,<br>channel,<br>flags,<br>hop,<br>central_phy,<br>peripheral_phy,<br>channel_map[5],<br>central_sca<br>supervision_timeout</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Conn_Params – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Command Disallowed (0xC)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>interval</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection interval</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>access_address</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Access Address Field of packet</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>crc_init</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Value used to initialize the CRC algorithm</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>start_time</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Start time of the connection task</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>event_counter</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Number of connection events</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>channel</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Channel on which next event will occur</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>flags</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Bit 1 set if Channel Selection Algorithm #2 in use</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>hop</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Channel hop value</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>central_phy</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>PHY in use on Central device</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>peripheral_phy</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>PHY in use on Peripheral device</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>channel_map[5]</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Bitmap of valid channels</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Central_sca</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Sleep clock accuracy</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Supervision_timeout</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection supervision timeout configured for the connection</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_ResolvingList – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_ResolvingList<br><br>Allocates memory for the resolving list.</p>
            </td>
            <td>
                <p>0x3f/0x2c</p>
            </td>
            <td>
                <p>entries</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_CS_Antenna_Config – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Set_CS_Antenna_Config<br><br>Set the distance offset of antenna(s) for channel sounding.</p>
            </td>
            <td>
                <p>0x3f/0x2d</p>
            </td>
            <td>
                <p>num_antenna_elements<br>antenna_element_offset[]</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Set_CS_Antenna_Config – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>num_antenna_elements</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Number of antennas</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>antenna_element_offset[]</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Antenna offset in cm. Array size is length of antenna elements.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Unspecified Error (0x1F)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PawrAdv – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_PawrAdv<br><br>Allocates memory for PAwR advertisers.</p>
            </td>
            <td>
                <p>0x3f/0x2e</p>
            </td>
            <td>
                <p>num_pawradv</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PawrAdv – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>num_pawradv</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Allocate memory to the specified number of PAwR advertisers</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>No More Resource (0x1A)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PawrSync – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Allocate_PawrSync<br>Allocates memory for PAwR synchronizers.</p>
            </td>
            <td>
                <p>0x3f/0x2f</p>
            </td>
            <td>
                <p>num_pawrsync</p>
            </td>
            <td>
                <p>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Allocate_PawrSync – Command Parameter (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>num_pawrsync</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Allocate memory to the specified number of PAwR synchronizers.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Memory Capacity Exceeded (0x7)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Siliconlabs_Set_Connection_Tx_Power – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_Siliconlabs_Set_Connection_Tx_Power</p>
            </td>
            <td>
                <p>0x3f/0x30</p>
            </td>
            <td>
                <p>handle<br>tx_power</p>
            </td>
            <td>
                <p>tx_power</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_Siliconlabs_Set_Connection_Tx_Power – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Tx_power</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>TX power in deci-dBm</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0),<br>Unknown Connection Identifier (0x02)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Read_Connection_Statistics – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Read_Connection_Statistics</p>
            </td>
            <td>
                <p>0x3f/0x31</p>
            </td>
            <td>
                <p>handle<br>reset</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Read_Connection_Statistics – Commands Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>handle</td>
            <td>2</td>
            <td>Connection handle</td>
        </tr>
        <tr>
            <td>reset</td>
            <td>1</td>
            <td>Reset the connection parameters</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Sniff_Connection_Packets – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Sniff_Connection_Packets<br><br>Sniff Bluetooth LE connection packets based on the provided connection settings.</p>
            </td>
            <td>
                <p>0x3f/0x32</p>
            </td>
            <td>
                <p>interval<br>access_address<br>crc_init<br>start_time<br>event_counter<br>channel<br>options<br>hop<br>central_phy<br>peripheral_phy<br>channel_map[5]<br>central_sca<br>supervision_timeout</p>
            </td>
            <td>
                <p>sniffer_handle</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Sniff_Connection_Packets – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>interval</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection interval</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>access_address</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Access Address Field of packet</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>crc_init</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Value used to initialize the CRC algorithm</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>start_time</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Start time of the connection task</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>event_counter</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Number of connection events</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>channel</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Channel on which next event will occur</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>options</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Bit 1 – Channel Selection Algorithm #2 in use<br>Bit 2 – Ignore start_time parameter</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>hop</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Channel hop value</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>central_phy</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>PHY in use on Central device</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>peripheral_phy</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>PHY in use on Peripheral device</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>channel_map[5]</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Bitmap of valid channels</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>central_sca</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Sleep clock accuracy</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>supervision_timeout</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection supervision timeout</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sniffer_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Index of sniffer</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Stack_Space – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Get_Stack_Space</p>
            </td>
            <td>
                <p>0x3f/0x33</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>transport_thr_stack_space<br>linklayer_thr_stack_space<br>status</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Get_Stack_Space – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>transport_thr_stack_space</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Stack space of transport thread in a RTOS</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>linklayer_thr_stack_space</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Stack space of link layer thread in a RTOS</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Command Disallowed (0xC)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Stop_Sniff_Connection_Packets – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>Command</th>
            <th>Command Value (OGF/OCF)</th>
            <th>Command Parameters</th>
            <th>Return Parameters</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>HCI_VS_SiliconLabs_Stop_Sniff_Connection_Packets</td>
            <td>0x3f/0x34</td>
            <td>sniffer_handle</td>
            <td>status</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Stop_Sniff_Connection_Packets – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sniffer_handle</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Index of sniffer to stop</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Invalid HCI Command Parameters (0x12)</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Read_AFH_Channel_Map_Quality – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><strong>HCI_VS_SiliconLabs_Read_AFH_Channel_Map_Quality</strong><br><br>Read the channel map quality when AFH is enabled and the passive adaptivity channel map flag is enabled</p>
            </td>
            <td>
                <p>0x3f/0x35</p>
            </td>
            <td>
                <p>operation_mode</p>
            </td>
            <td>
                <p>status<br>quality_map</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Read_AFH_Channel_Map_Quality – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>mode</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Operation mode to select what the output will contain<br>0x00 – Get channel quality map; error otherwise</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Invalid HCI Command Parameters (0x12)<br>Command Disallowed (0xC)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>quality_map</p>
            </td>
            <td>
                <p>40</p>
            </td>
            <td>
                <p>Channel map quality score for each data channel (first 37 bytes) and the 3 advertisement channels (last 3 bytes)<br>Active channel quality range: [-112,80]<br>Blocked channel quality: -127</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Event_Info_Reporting_Enable – Command (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Command</p>
            </th>
            <th>
                <p>Command Value (OGF/OCF)</p>
            </th>
            <th>
                <p>Command Parameters</p>
            </th>
            <th>
                <p>Return Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><strong>HCI_VS_SiliconLabs_Event_Info_Reporting_Enable</strong><br><br>Enable event info reporting</p>
            </td>
            <td>
                <p>0x3f/0x36</p>
            </td>
            <td>
                <p>enable<br>configuration<br>procedure_type<br>procedure_identifier_length<br>procedure_identifier[]</p>
            </td>
            <td>
                <p>status<br>procedure_type<br>procedure_identifier_length<br>procedure_identifier[]</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Event_Info_Reporting_Enable – Command Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>enable</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Enable (1) or disable (0) event info reporting</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>configuration</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Bitfield for configuration options<br>0x000001 - PAwR event counter </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>procedure_type</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Type of procedure for reporting<br>0 - PAwR ADV</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>procedure_identifier_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Length of procedure identifier data array for the procedure type<br>0x02 - PAwR ADV</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>procedure_identifier[]</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Procedure identifier data<br>PAwR ADV:<br> Byte 1 - Advertising handle<br>Byte 2 - Subevent</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>status</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Success (0x0)<br>Invalid HCI Command Parameters (0x12)<br>Memory Capacity Exceeded (0x7)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>response: procedure_type</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Type of procedure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>response: procedure_identifier_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Length of procedure identifier array</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>response: procedure_identifier[]</p>
            </td>
            <td>
                <p>variable</p>
            </td>
            <td>
                <p>Procedure identifier data</p>
            </td>
        </tr>
    </tbody>
</table>

###### Vendor-Specific HCI Events

The Silicon Labs HCI and Controller support the following vendor-specific HCI events.

- [HCI_Event_Le_Silabs_IQ_Report – Event](#hci-event-le-silabs-iq-report-event)
- [HCI_Event_Le_Silabs_IQ_Report – Event Parameters](#hci-event-le-silabs-iq-report-event-parameters)
- [HCI_Event_Le_Silabs_Sk_Request – Event](#hci-event-le-silabs-sk-request-event)
- [HCI_Event_Le_Silabs_Sk_Request – Event Parameters](#hci-event-le-silabs-sk-request-event-parameters)
- [HCI_Event_VS_SiliconLabs_Connection_Statistics – Event](#hci_event_vs_siliconlabs_connection_statistics-event)
- [HCI_Event_VS_SiliconLabs_Connection_Statistics – Event Parameters](#hci-event-vs-siliconlabs-connection-statistics-event-parameters)
- [HCI_Event_Le_Silabs_Sniff_Connection – Event](#hci-event-le-silabs-sniff-connection-event)
- [HCI_Event_Le_Silabs_Sniff_Complete – Event Parameters](#hci-event-le-silabs-sniff-complete-event-parameters)
- [HCI_Event_ VS_Siliconlabs_Periodic_Advertising_Sync_Transfer_Received – Event](#hci-event-vs-siliconlabs-periodic-advertising-sync-transfer-received-event)
- [HCI_Event_ VS_Siliconlabs_Periodic_Advertising_Sync_Transfer_Received – Event Parameters](#hci-event-vs-siliconlabs-periodic-advertising-sync-transfer-received-event-parameters)
- [HCI_VS_SiliconLabs_Event_Info_Report – Event](#hci-vs-siliconlabs-event-info-report-event)
- [HCI_VS_SiliconLabs_Event_Info_Report – Event Parameters](#hci-vs-siliconlabs-event-info-report-event-parameters)

> **Note**: The vendor-specific events use the Vendor-Specific HCI Event code (0xFF). The first event parameter, `subevent_code`, contains the vendor-specific subevent identifier (subcode) that selects the concrete event.
> Legacy behaviour of using 0x3F as vendor specific event code can be configure by SL_BT_CONTROLLER_USE_LEGACY_VENDOR_SPECIFIC_EVENT_CODE option in HCI controller configuration.

###### HCI_Event_Le_Silabs_IQ_Report – Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_Event_Le_Silabs_IQ_Report<br>Receive SiliconLabs proprietary IQ sampling reports.<br>For further information, refer to the following documents:<br><a href="https://docs.silabs.com/rtl-lib/latest/bluetooth-direction-finding-fundamentals/">Bluetooth® Direction Finding Fundamentals</a><br><a href="https://docs.silabs.com/rtl-lib/latest/direction-finding-solution-guide/">Silicon Labs Direction-Finding Solution Quick-Start Guide</a><br><a href="https://docs.silabs.com/rtl-lib/latest/rtl-lib-app-development/">Application Development with Silicon Labs’ RTL Library</a></p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>address_type<br>address<br>rx_phy<br>channel_index<br>rssi<br>rssi_antenna_id<br>cte_type<br>slot_durations<br>packet_status<br>packet_counter<br>sample_count<br>sample</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_IQ_Report – Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>subevent_code</td>
            <td>1</td>
            <td>Vendor-specific subevent identifier (subcode) for this event. Value: 0xEE.</td>
        </tr>
        <tr>
            <td>address_type</td>
            <td>1</td>
            <td>Bluetooth address type</td>
        </tr>
        <tr>
            <td>address</td>
            <td>6</td>
            <td>Bluetooth address</td>
        </tr>
        <tr>
            <td>rx_phy</td>
            <td>1</td>
            <td>Used PHY</td>
        </tr>
        <tr>
            <td>channel_index</td>
            <td>1</td>
            <td>Channel index for the report.</td>
        </tr>
        <tr>
            <td>rssi</td>
            <td>1</td>
            <td>RSSI</td>
        </tr>
        <tr>
            <td>rssi_antenna_id</td>
            <td>1</td>
            <td>ID of the antenna where the samples are collected.</td>
        </tr>
        <tr>
            <td>cte_type</td>
            <td>1</td>
            <td>CTE type</td>
        </tr>
        <tr>
            <td>slot_durations</td>
            <td>1</td>
            <td>Slot duration</td>
        </tr>
        <tr>
            <td>packet_status</td>
            <td>1</td>
            <td>Status of received packets</td>
        </tr>
        <tr>
            <td>packet_counter</td>
            <td>2</td>
            <td>Number of received packets</td>
        </tr>
        <tr>
            <td>sample_count</td>
            <td>1</td>
            <td>Number of samples</td>
        </tr>
        <tr>
            <td>sample</td>
            <td>variable</td>
            <td>IQ samples</td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_Sk_Request – Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_Event_Le_Silabs_Sk_Request<br><br>Request for host to generate session key.</p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>Handle<br>RandomDiversifier<br>SKD</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_Sk_Request – Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>subevent_code</td>
            <td>1</td>
            <td>Vendor-specific subevent identifier (subcode) for this event. Value: 0xED.</td>
        </tr>
        <tr>
            <td>Handle</td>
            <td>2</td>
            <td>Connection handle</td>
        </tr>
        <tr>
            <td>Random</td>
            <td>1</td>
            <td>Random data</td>
        </tr>
        <tr>
            <td>Diversifier</td>
            <td>2</td>
            <td>Encryption diversifier</td>
        </tr>
        <tr>
            <td>SKD</td>
            <td>1</td>
            <td>Session key diversifier</td>
        </tr>
    </tbody>
</table>

###### HCI_Event_VS_SiliconLabs_Connection_Statistics Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_Event_VS_SiliconLabs_Connection_Statistics<br><br>Statistics report of a connection.</p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>handle<br>rssi_min<br>rssi_max<br>events_total<br>events_success<br>events_missed<br>crc_errors</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_VS_SiliconLabs_Connection_Statistics Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>subevent_code</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Vendor-specific subevent identifier (subcode) for this event. Value: 0xEF.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>handle</p>
            </td>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Connection handle</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>rssi_min</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Minimum RSSI received in connection packets.<br>0x7f if RSSI is unknown.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>rssi_max</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Maximum RSSI receiver in connection packets.<br>-0x7f if RSSI is unknown.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>events_total</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Total number of connection events</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>events_success</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Number of successful connection events</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>events_missed</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Number of missed connection events</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>crc_errors</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Increased when packet with bad crc is received</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_Sniff_Connection – Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_Event_Le_Silabs_Sniff_Connection<br><br>Report of the sniffed connection.</p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>central_rssi<br>peripheral_rssi<br>flags<br>sniffer_handle</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_Sniff_Connection – Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>subevent_code</td>
            <td>1</td>
            <td>Vendor-specific subevent identifier (subcode) for this event. Value: 0xF0.</td>
        </tr>
        <tr>
            <td>central_rssi</td>
            <td>1</td>
            <td>Central packet RSSI</td>
        </tr>
        <tr>
            <td>peripheral_rssi</td>
            <td>1</td>
            <td>Peripheral packet RSSI</td>
        </tr>
        <tr>
            <td>flags</td>
            <td>1</td>
            <td>Sniffer flags</td>
        </tr>
        <tr>
            <td>sniffer_handle</td>
            <td>1</td>
            <td>Sniffer instance handle</td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_Sniff_Complete – Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_Event_Le_Silabs_Sniff_Complete<br><br>Received when connection sniffing is complete.</p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>sniffer_handle<br>reason</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_Le_Silabs_Sniff_Complete – Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>subevent_code</td>
            <td>1</td>
            <td>Vendor-specific subevent identifier (subcode) for this event. Value: 0xF1.</td>
        </tr>
        <tr>
            <td>sniffer_handle</td>
            <td>1</td>
            <td>Index of sniffer</td>
        </tr>
        <tr>
            <td>reason</td>
            <td>1</td>
            <td>Reason to stop</td>
        </tr>
    </tbody>
</table>

###### HCI_Event_ VS_Siliconlabs_Periodic_Advertising_Sync_Transfer_Received – Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_Event_<br><em>VS_Siliconlabs_Periodic_Advertising_Sync_Transfer_Received</em><br><br>Received when the periodic advertising sync parameters are changed or the receiver drops the current synchronizer and establishes a new one</p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>status<br>receiving_sync_handle<br>service_data<br>sync_handle<br>advertising_sid<br>advertiser_address_type<br>advertiser_address<br>advertiser_phy<br>periodic_advertising_interval<br>advertiser_clock_accuracy<br>num_subevents<br>subevent_interval<br>response_slot_delay<br>response_slot_spacing</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_Event_ VS_Siliconlabs_Periodic_Advertising_Sync_Transfer_Received – Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>subevent_code</td>
            <td>1</td>
            <td>Vendor-specific subevent identifier (subcode) for this event. Value: 0xEC.</td>
        </tr>
        <tr>
            <td>status</td>
            <td>1</td>
            <td>Status when device tried to synchronize</td>
        </tr>
        <tr>
            <td>receiving_sync_handle</td>
            <td>2</td>
            <td>The sync handle after synchronization established</td>
        </tr>
        <tr>
            <td>service_data</td>
            <td>2</td>
            <td>Identification of PAwR train</td>
        </tr>
        <tr>
            <td>sync_handle</td>
            <td>2</td>
            <td>Sync handle for the sync</td>
        </tr>
        <tr>
            <td>avertising_sid</td>
            <td>1</td>
            <td>Advertising SID</td>
        </tr>
        <tr>
            <td>advertiser_address_type</td>
            <td>1</td>
            <td>Type of advertiser</td>
        </tr>
        <tr>
            <td>advertiser_address</td>
            <td>1</td>
            <td>Advertiser’s address</td>
        </tr>
        <tr>
            <td>advertiser_phy</td>
            <td>1</td>
            <td>Advertiser’s PHY</td>
        </tr>
        <tr>
            <td>periodic_advertising_interval</td>
            <td>2</td>
            <td>Periodic advertising interval</td>
        </tr>
        <tr>
            <td>advertiser_clock_accuracy</td>
            <td>1</td>
            <td>Advertiser’s sleep clock accuracy</td>
        </tr>
        <tr>
            <td>num_subevents</td>
            <td>1</td>
            <td>Number of subevents in PAwR train</td>
        </tr>
        <tr>
            <td>subevent_interval</td>
            <td>1</td>
            <td>Subevent interval</td>
        </tr>
        <tr>
            <td>response_slot_delay</td>
            <td>1</td>
            <td>Response slot delay</td>
        </tr>
        <tr>
            <td>response_slot_spacing</td>
            <td>1</td>
            <td>Response slot spacing</td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Event_Info_Report - Event (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Event</p>
            </th>
            <th>
                <p>Event Value</p>
            </th>
            <th>
                <p>Event Parameters</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HCI_VS_SiliconLabs_Event_Info_Report</p>
                <p><br>Report of the event information</p>
            </td>
            <td>
                <p>0xff</p>
            </td>
            <td>
                <p>subevent_code<br>configuration<br>procedure_type<br>procedure_identifier_length<br>procedure_identifier<br>event_info_length<br>event_info</p>
            </td>
        </tr>
    </tbody>
</table>

###### HCI_VS_SiliconLabs_Event_Info_Report - Event Parameters (heading level 7)

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>subevent_code</td>
            <td>1</td>
            <td>Vendor-specific subevent identifier (subcode) for this event. Value: 0xF2.</td>
        </tr>
        <tr>
            <td>configuration</td>
            <td>4</td>
            <td>Configuration value</td>
        </tr>
        <tr>
            <td>procedure_type</td>
            <td>1</td>
            <td>Type of procedure</td>
        </tr>
        <tr>
            <td>procedure_identifier_length</td>
            <td>1</td>
            <td>Length (in bytes) of <code>procedure_identifier</code>.</td>
        </tr>
        <tr>
            <td>procedure_identifier</td>
            <td>Variable</td>
            <td>Procedure identifier. Length is <code>procedure_identifier_length</code> bytes.</td>
        </tr>
        <tr>
            <td>event_info_length</td>
            <td>1</td>
            <td>Length (in bytes) of <code>event_info</code>.</td>
        </tr>
        <tr>
            <td>event_info</td>
            <td>Variable</td>
            <td>Event information. Length is <code>event_info_length</code> bytes.</td>
        </tr>
    </tbody>
</table>

###### Custom Commands

On RCP builds it is possible to hook custom message handlers to the message processing. The Application needs to allocate the `sl_btctrl_command_handler_t` structure in the heap and implement a callback function. The stack adds this to the list of message handlers, and calls it during message processing. When the handler receives a message, if it does not handle it must return false. If the message is processed, the handler must return true. If no handler handles the HCI command, then a Command Complete event with 0x01 (Unknown HCI Command) is returned to the host.

Silicon Labs uses opcodes starting from 0xfc00 forward. To prevent collisions with these opcodes, use opcodes starting from 0xff00 in your applications.

###### Example (heading level 7)

This example implements a simple vendor-specific HCI command with opcode 0xff00 that receives a 32-bit number, then returns the same number increased by one.

1. Include this header in the application file:  
   ```C  
   #include "sl_btctrl_hci_handler.h"  
   ```
2. Allocate the structure in heap:  
   ```C  
   struct sl_btctrl_command_handler custom_handler;  
   ```
3. Implement the callback function:  
   ```C  
   bool custom_message_handler(struct sl_btctrl_hci_message * msg)  
   {  
       uint16_t opcode;  
       if(sl_btctrl_hci_message_get_opcode(msg, &opcode) != SL_STATUS_OK){  
           return false;  
       }  
       size_t length;  
       if(sl_btctrl_hci_message_get_length(msg, &length) != SL_STATUS_OK){  
           return false;  
       }  
     
       switch(opcode)  
       {  
           case 0xff00:{  
               uint32_t params;  
                   if(sl_btctrl_hci_message_get_parameters(msg, (uint8_t*)&params, sizeof(params)) != SL_STATUS_OK){  
                       sl_btctrl_hci_message_set_response(msg, 0x12, NULL, 0);  
                       // 0x12 is "Invalid HCI Command Parameters"-error.  
                       // Set response only fails if NULL pointers or too long data is passed  
                   }else{  
                       params++;//Increase  
                       sl_btctrl_hci_message_set_response(msg, 0x0, (uint8_t*)&params, sizeof(params));  
                   }  
           }  
           return true;//Command is handled  
           }  
       return false;  
       ```  
     
   ```
4. Register handler in startup code:

```C
sl_btctrl_hci_register_handler(&custom_handler, &custom_message_handler);
```

###### Custom Commands Provided as Software Components (heading level 7)

Some Silicon Labs specific features are provided as software components. They implement custom command handling for different functionalities.

###### HCI Get Version (heading level 8)

Add the software component **HCI Get Version Vendor Specific Command** to the project. The Opcode for this vendor specific command can be defined in the component. By default, it is 0xFF10.

Return parameters:

<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Size</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>major</td>
            <td>2</td>
            <td>The major version number</td>
        </tr>
        <tr>
            <td>minor</td>
            <td>2</td>
            <td>The minor version number</td>
        </tr>
        <tr>
            <td>patch</td>
            <td>2</td>
            <td>The patch version number</td>
        </tr>
        <tr>
            <td>build</td>
            <td>2</td>
            <td>The build number of the version</td>
        </tr>
    </tbody>
</table>

The return parameter structure is defined in the file _sl_bt_hci_version_config.h_.

###### HCI Coex (heading level 8)

Add the component **HCI Coex Vendor Specific Commands** to the project. The Opcodes for this vendor specific command can be defined in the component.

The provided commands have the same inputs and return parameters as the Coex commands defined in SoC projects: [https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-coex](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-coex)

###### HCI Extended Advertisement Filtering (heading level 8)

Add the software components **HCI Event(s) Filtering** and **HCI Extended Advertisement Filtering** in the project to enable filtering of advertisements using RSSI and/or UUID (16-bit and 32-bit).

![HCI Extended Advertisment Filtering 1](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image11.png)

The default filter configuration can be set in the **HCI Extended Advertisement Filtering** component configuration, if needed.

> **Note**: The number of UUIDs to be included in the advertisement report **must** be configured in the component in order to allocate the memory for the maximum UUID array size.

![HCI Extended Advertisement Filtering 2](/enabling-rcp-using-bt-hci/11.0.1/images/sld865-image12.png)

The Opcode for this vendor specific command can be defined in the component. By default, it is 0xFF11.

Command parameters:

<table>
    <thead>
        <tr>
            <th>
                <p>Parameter</p>
            </th>
            <th>
                <p>Size</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>filter_config</p>
            </td>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Bitmap that holds configuration of the filter<br>0x00000001 – Enable RSSI filtering<br>0x00000002 – Enable filtering of 16-bit Service Data UUIDs<br>0x00000004 – Enable filtering of Incomplete Lists of 16-bit Service Class UUIDs<br>0x00000008 - Enable filtering of Complete Lists of 16-bit Service Class UUIDs<br>0x00000010 - Enable 32-bit Service Data UUID filtering<br>0x00000020 – Enable filtering of Incomplete Lists of 32-bit Service Class UUIDs<br>0x00000040 - Enable filtering of Complete Lists of 32-bit Service Class UUIDs</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>rssi_threshold</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Threshold value in dBm for RSSI when event filtering by RSSI is enabled</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>uuid_array_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Array length of 16-bit UUID array. Must be less than or equal to SL_BT_HCI_FILTER_16BIT_UUID_ARRAY_LEN</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>uuid_array [ ]</p>
            </td>
            <td>
                <p>variable</p>
            </td>
            <td>
                <p>16-bit UUID array. Array size is the length set for 16-bit UUID array</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>uuid_array_length</p>
            </td>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Array length of 32-bit UUID array. Must be less than or equal to SL_BT_HCI_FILTER_32BIT_UUID_ARRAY_LEN</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>uuid_array [ ]</p>
            </td>
            <td>
                <p>variable</p>
            </td>
            <td>
                <p>32-bit UUID array. Array size is the length set for 32-bit UUID array</p>
            </td>
        </tr>
    </tbody>
</table>

##### Configuring Hardware Flow Control In the WSTK

Hardware flow control can be enabled or disabled between the UART controller of the WSTK and Silicon Labs SoC. In the SoC, hardware flow control can be configured with the configuration parameter shown in Section [Using an Example Application](02-enabling-hci-functionality#using-an-example-application). In the WSTK the hardware flow control can be configured as described in this section. The example below shows how to enable hardware flow control.

> **Important**: If the hardware flow control settings are not the same in the SoC and WSTK, the HCI will not work.

1. Open Simplicity Studio and, in the Debug Adapters view, right-click the target device.
2. Select **Connect**.
3. Right-click the device again and select **Launch Console**.
4. Select the admin tab.
5. Set flow control with the following command:  
   ```sh  
       WSTK\> serial vcom config handshake rtscts  
       RTS handshake enabled  
       CTS handshake enabled  
       Serial configuration saved  
   ```
6. Check the configuration with the following command:  
   ```sh  
   WSTK\> serial vcom  
   ----- Virtual COM port -----  
   Stored port speed  : 115200  
   Active port speed  : 115226  
   Stored handshake   : rtscts  
   Actual handshake   : rtscts  
   RTS Asserted - Ready to Receive.  
   ```

The flow control can be disabled by setting _handshake_ parameter to _none_ in step 5 above.

### Bootloading

#### Bootloading Embedded Applications

Bootloading allows you to update application firmware images on your devices. This section provides background information about bootloading using the Silicon
Labs Gecko Bootloader.

- [**Bootloader Fundamentals**](/btmesh/11.0.0/bootloader-fundamentals): Introduces bootloading for Silicon Labs networking devices. Discusses the Gecko Bootloader as well as legacy Ember and Bluetooth bootloaders, and describes the file formats used by each.
- [**Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher**](/mcu-bootloader/11.0.0/bootloader-user-guide-series3-and-higher): Describes the high-level implementation of the Silicon Labs Gecko Bootloader for Series 3 microcontrollers, SoCs (System on Chips), and NCPs (Network Co-Processors), and provides information on different aspects of configuring the Gecko Bootloader.
- [**Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)**](/btmesh/11.0.0/bootloader-user-guide-gsdk-4): Describes the high-level implementation of the Silicon Labs Gecko Bootloader for EFR32 SoCs and NCPs, and provides information on how to get started using the Gecko Bootloader with Silicon Labs wireless protocol stacks in GSDK 4.0 and higher.
- [**Using the Gecko Bootloader with Silicon Labs Bluetooth Applications**](/btmesh/11.0.0/using-gecko-bootloader-with-bluetooth-apps): Includes detailed information on using the Gecko Bootloader with Silicon Labs Bluetooth applications. It supplements the general Gecko Bootloader implementation information provided in Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher.
- [**Series 2 Secure Boot with RTSL**](/btmesh/11.0.0/series2-secure-boot-with-rtsl): Contains detailed information on configuring and using the Secure Boot with hardware Root of Trust and Secure Loader on Series 2 devices, including how to provision the signing key. This is a companion document to UG266: Silicon Labs Gecko Bootloader User's Guide.
- [**Transitioning to the Updated Gecko Bootloader in GSDK 4.0 and Higher**](/btmesh/11.0.0/bootloader-transitioning-guide-gsdk-v40-and-higher): Gecko Bootloader v2.x, introduced in GSDK 4.0, contains a number of changes compared to Gecko Bootloader v1.x. This document describes the differences between the versions, including how to configure the new Gecko Bootloader in Simplicity Studio 5.
- [**Bluetooth Mesh Device Firmware Update**](/btmesh/11.0.0/btmesh-device-firmware-update): Provides background information on the Bluetooth Mesh Device Firmware Update feature, including the BLOB transfer, the DFU roles in a Bluetooth mesh network, the models required for these roles, and the firmware update process.
- [**Bluetooth Mesh Device Firmware Update Example Walkthrough**](/btmesh/11.0.0/btmesh-device-firmware-update-example): Describes the bootloader configurations and the firmware update models in the example projects, and walks through a firmware update demonstration.
- [**Provisioning and Firmware Update Using the DFU Python Script**](/btmesh/11.0.0/btmesh-provisioning-firmware-update-with-dfu-python-script): Walks through a device firmware update demonstration using the DFU Python script.

#### Bootloader Fundamentals

##### Bootloader Fundamentals

> **Note: This section replaces _UG103.06: Bootloader Fundamentals_. Further updates to this user guide will be provided here**.

This guide introduces bootloading for Silicon Labs networking devices. It describes the concepts of standalone and application bootloaders and discusses their relative strengths and weaknesses. In addition, it looks at design and implementation details for each method. Finally, it describes the bootloader file format.

Silicon Labs’ _Fundamentals_ series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs Bluetooth, and associated development tools. These guides can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

##### Introduction

The bootloader is a program stored in reserved flash memory that can initialize a device, update firmware images, and possibly perform some integrity checks. Firmware image update occurs on demand, either by serial communication or over the air. Production-level programming is typically done during the product manufacturing process yet it is desirable to be able to reprogram the system after production is complete. More importantly, it is valuable to be able to update the device's firmware with new features and bug fixes after deployment. The firmware image update capability makes that possible.

Silicon Labs supports devices that do not use a bootloader, but this requires external hardware such as a Debug Adapter (Silicon Labs ISA3 or Wireless Starter Kit (WSTK)) or third-party SerialWire/JTAG programming device to update the firmware. Devices without a bootloader have no supported way of updating the firmware once they are deployed, which is why Silicon Labs strongly advocates implementing a bootloader.

In March of 2017, Silicon Labs introduced the Gecko Bootloader, a code library configurable through Simplicity Studio’s IDE to generate bootloaders that can be used with a variety of Silicon Labs protocol stacks. The Gecko Bootloader can be used with EFM32 and EFR32 Series 1 and later devices. The Gecko Bootloader was restructured into a component-based design and released with Gecko SDK Suite (GSDK) 4.0 in December of 2021. This new version is documented in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/), along with other documents. Documentation for older versions is installed with their respective SDKs.

The Gecko Bootloader uses a customized update image file format. The update image file consumed by a Gecko Bootloader-generated application bootloader is a GBL (Gecko BootLoader) file, and is described in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

Bootloading a firmware update image can be accomplished in two ways. The first is Over-The-Air (OTA), that is, through the wireless network, as shown in the following figure.

![OTA Bootloading Use Case](/bootloader-fundamentals/0.1/images/ota-bootloading-use-case.jpg)

The second is through a hardwired link to the device. The following figure represents the serial bootloader use cases for SoCs (System on Chips) using either a UART (Universal Asynchronous Receiver/Transmitter), SPI (Serial Protocol Interface), or USB (Universal Serial Bus) interface, and for NCPs (Network Coprocessors) using either UART or SPI.

![Serial Bootloading Use Cases](/bootloader-fundamentals/0.1/images/serial-bootloading-use-cases.jpg)

Silicon Labs networking devices use bootloaders that perform firmware updates in two different modes: standalone (also called standalone bootloaders) and application (also called application bootloaders). Application bootloaders are further divided into those that use external storage for the download update image, and those that use local storage. These bootloader types are discussed in the next two sections.

The firmware update situations described in this document assume that the source node (the device sending the firmware image to the target through a serial or OTA link) acquires the new firmware through some other means. For example, if a device on the local Zigbee network has an Ethernet gateway attached, this device could get or receive these firmware updates over the Internet. This necessary part of the firmware update process is system-dependent and beyond the scope of this document.

###### Standalone Bootloader

A standalone bootloader is a program that uses an external communication interface, such as UART or SPI, to get an application image. Standalone firmware update is a single-stage process that allows the application image to be placed into flash memory, overwriting the existing application image, without the participation of the application itself. Very little interaction occurs between the standalone bootloader and the application running in flash. In general, the only time that the application interacts with the bootloader is when it requests a reboot into the bootloader. Once the bootloader is running, it receives firmware update packets containing the (new) firmware image either by physical connections such as UART or SPI, or by the radio (over-the-air).

When the firmware update process is initiated, the new code overwrites the existing stack and application code. If any errors occur during this process, the application cannot be recovered, and the process must start over. For information about configuring the Gecko Bootloader as a standalone bootloader, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

###### Application Bootloader

An application bootloader begins the firmware update process after the running application has completely downloaded the update image file. The application bootloader expects that the image either lives in external memory accessible by the bootloader or in a portion of main flash memory (if the chip has sufficient memory to support this local storage model).

The application bootloader relies on the application to acquire the new firmware image. This image can be downloaded by the application in any way that is convenient (UART, over-the-air, etc.) but it must be stored into a region referred to as the download space. The download space is typically an external memory device such as an EEPROM or dataflash, but it can also be a section of the chip’s internal flash when using a local storage variant of the application bootloader. Once the new image has been stored, the application bootloader is then called to validate the new image and copy it from the download space to flash.

Since the application bootloader does not participate in acquiring the image, and the entire image is downloaded before the firmware update process is started, download errors do not adversely affect the running image. The download process can be restarted or paused to acquire the image over time. The integrity of the downloaded update image can be verified before initiating the firmware update process, to prevent a corrupt or non-functional image from being applied.

The Gecko Bootloader can be configured to accept a list of multiple upgrade images to attempt to verify and apply. This allows the Gecko Bootloader to store what is in effect a backup copy of the update image, which it can access if the first image is corrupt.

Note that the EmberZNet NCP platform does not utilize an application bootloader because the application code resides on the host rather than on the NCP directly. Instead a device acting as a serial coprocessor would utilize a standalone bootloader designed to accept code over the same serial interface as the expected NCP firmware uses. However, the host application (residing on a separate MCU from the NCP) can utilize whatever bootloading scheme is appropriate.

For more information on application bootloaders, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

##### About the Gecko Bootloader

The Silicon Labs Gecko Bootloader is a configurable code library that can be used with all the newer Silicon Labs Gecko MCUs and wireless MCUs. It uses a specially-formatted update image file called a GBL file. The Gecko Bootloader has a two-stage design on Series 1 devices, where a minimal first stage bootloader is used to update the main bootloader. On Series 2 devices, the first stage bootloader is replaced by a Secure Engine and the Gecko Bootloader consists only of the main bootloader. The Secure Engine may be hardware-based, or virtual (software). If hardware-based, the implementation may be either with or without Secure Vault. Throughout this document, the following conventions will be used.

- **HSE**: Hardware Secure Engine, either with or without Secure Vault if not specified
- **VSE**: Virtual Secure Engine
- **SE**: Secure Engine (either HSE or VSE, in general)

Having a first stage bootloader or SE allows for field updates of the main bootloader, including adding new capabilities, changing communication protocols, adding new security features and fixes, and so on. The Gecko Bootloader consists of three component parts:

**Core:** The bootloader core contains the main function of both bootloader stages. It also contains functionality to write to the internal main flash, to perform a bootloader update, and to reset into the application flagging applicable reset reasons.

**Driver:** Different bootloading applications require different hardware drivers for use by the other components of the bootloader.

**Component/Plugin:** All parts of the main bootloader that are either optional or selectable for different configurations are implemented as components (in GSDK 4.0 and higher) or previously in plugins. Each component/plugin has a generic header file, and one or more implementations. The current release contains components for functionality like UART and SPI communication protocols, SPI flash storage, internal flash storage, and different cryptographic operations.

###### Features

Gecko Bootloader features include:

- Field-updatable
- Secure boot
- Signed GBL firmware update image file
- Encrypted GBL firmware update image file

These features are summarized in the following sections and described in more detail in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/). Protocol-specific information about using the Gecko Bootloader may be found in the following documents:

- [Using the Gecko Bootloader with EmberZNet](https://docs.silabs.com/zigbee/latest/using-gecko-bootloader-with-zigbee/)
- [Bootloading and OTA with Silicon Labs Connect SDK v3.x](https://docs.silabs.com/connect-stack/latest/bootloading-and-ota-with-connect-v3x)
- [Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/)

###### Field-Updatable (heading level 7)

###### Series 1 (heading level 8)

On EFM32 and EFR32 Series 1 devices, field update capability for the Gecko bootloader is provided by a two-stage design where the bootloader has a first stage and a main stage. The minimal first stage of the bootloader is not field updatable, and can only update the main bootloader by reading from and writing to fixed addresses in internal flash memory. To perform a main bootloader update, the running main bootloader verifies the integrity and authenticity of the bootloader update image, writes it to internal flash, and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader update image before copying it to the main bootloader location, completing the update

###### Series 2 (heading level 8)

On Series 2 devices, field update capability for the Gecko bootloader is provided by the SE. To perform a main bootloader update, the running main bootloader verifies the integrity and authenticity of the bootloader update image, writes it to internal flash, and requests that the SE installs the update. The SE optionally verifies the authenticity of the main bootloader update image before copying it to the main bootloader location, completing the update. The same mechanism can be used to update the SE itself.

###### Secure Boot (heading level 7)

Secure boot is designed to prevent an untrusted application from running on the device. When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot using asymmetric cryptography. The signature algorithm used is ECDSA-P256-SHA256. The public key is written to the device during manufacturing, while the private key is kept secret. This ensures that the application was created and signed by a trusted party.

###### Signed GBL Update Image File (heading level 7)

The Gecko Bootloader supports enforcing cryptographic signature verification of the update image file in addition to Secure Boot. This allows the bootloader and application to verify that the application or bootloader update comes from a trusted source before starting the update process. The signature algorithm used is ECDSA-P256-SHA256. The public key is the same key as for secure boot, written to the device during manufacturing, while the private key is never distributed. This ensures that the GBL file was created and signed by a trusted party.

###### Encrypted GBL Update File (heading level 7)

The GBL update file can also be encrypted, to prevent eavesdroppers from getting hold of the plaintext firmware image. The encryption algorithm used is AES-CTR-128, and the encryption key is written to the device during manufacturing.

##### Memory Space for Bootloading

The first stage of the Gecko Bootloader on Series 1 devices takes up a single flash page. On devices with 2 kB flash pages, like EFR32MG1, this means that the first stage takes 2 kB.

The size of the main bootloader is dependent on the functionality required. With a typical bootloader configuration, the main bootloader for Series 1 devices takes up 14 kB of flash, bringing the total bootloader size to 16 kB.

Silicon Labs recommends reserving 16 kB for the bootloader for Series 1 and EFR32xG21 devices and 24 kB for EFR32xG22 devices.

On EFR32xG1 devices (Mighty Gecko, Flex Gecko, and Blue Gecko families), the bootloader resides in main flash.

- First stage bootloader @ 0x0
- Main bootloader @ 0x800
- Application @ 0x4000

On EFR32xG12 and later Series 1 devices, the bootloader resides in the bootloader area in the Information Block.

- Application @ 0x0
- First stage bootloader @ 0x0FE10000
- Main bootloader @ 0x0FE10800

On EFR32xG21, the main bootloader resides in main flash:

- Main bootloader @ 0x0
- Application @ 0x4000

On EFR32xG22, the main bootloader resides in main flash:

- Main bootloader @ 0x0
- Application @ 0x6000

On EFR32xG23, the main bootloader resides in main flash:

- Main bootloader @ 0x08000000
- Application @ 0x08006000

On EFR32xG24, the main bootloader resides in main flash:

- Main bootloader @ 0x08000000
- Application @ 0x08006000

##### Design Decisions

The decision of what bootloader type to deploy depends on many factors. Note that the platform type and available flash memory may limit bootloader choices.

Some questions related to this are:

- Where does the device get the new update image? Is this over-the-air via the networking protocol? Using a separate interface connected to the Internet?
- Will the device have an external memory chip to store a new update image? If not, is there enough internal flash memory to store both a current and a newly downloaded copy of the largest expected application image?
- If the device receives the new image over-the-air, will it be multiple hops away from the server holding the download image?
- What kind of image security is needed?
- What communications driver will be used (in the single protocol case)?
- Does the use case require more than one protocol?

The configurable design of the Gecko Bootloader platform means that developers can create bootloaders to fit almost any design choice. See [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

#### Gecko Bootloader User's Guide for Series 3 and Higher

##### Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher

This guide describes the high-level implementation of the Silicon Labs Gecko Bootloader for Series 3 microcontrollers, SoCs (System on Chips), and NCPs (Network Co-Processors), and provides information on different aspects of configuring the Gecko Bootloader.

The Silicon Labs Gecko Bootloader is a common bootloader for all the newer MCUs and wireless MCUs from Silicon Labs. This guide is specific to Series 3 devices and above. The Gecko Bootloader can be configured to perform a variety of functions, from device initialization to firmware upgrades. Key features of the bootloader are:

- Usable across Silicon Labs Gecko microcontroller and wireless microcontroller families
- In-field upgradeable
- Configurable
- Enhanced security features, including:
- **Secure Boot**: When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot, using asymmetric cryptography. This ensures that the application was created and signed by a trusted party.
- **Signed upgrade image file**: The Gecko Bootloader supports enforcing cryptographic signature verification of the upgrade image file. This allows the bootloader and application to verify that the application or bootloader upgrade comes from a trusted source before starting the upgrade process, ensuring that the image file was created and signed by a trusted party.
- **Encrypted upgrade image**: The image file can also be encrypted to prevent eavesdroppers from acquiring the plaintext firmware image.

For Series 3 devices and above, Gecko Bootloader uses a proprietary format for its upgrade images, called GBL V4 (Gecko Bootloader file). These files have the file extension “.gbl”. See the _Gecko Bootloader File Format_ page for more details. Series 3 and above devices do not support GBL versions lesser than v4.

On Series 3 devices, the Gecko bootloader consist of the main stage bootloader. The main bootloader is upgradable through the Secure Engine.

The Secure Engine provides functionality to install an image to code region 0 in the external flash.

To perform a bootloader upgrade, the running bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The bootloader then writes the upgrade image to the upgrade location in external flash and requests that the Secure Engine installs it. On some devices, the Secure Engine is also capable of verifying the authenticity of the main bootloader update image against a root of trust. The Secure Engine itself is upgradable using the same mechanism. See the _Gecko Bootloader Operation - Secure Engine Upgrade_ page for more details.

The bootloader consists of a common core, drivers, and a set of components that give the bootloader specific capabilities. The common bootloader core is provided as a full-source delivery. The common bootloader core contains functionality to parse GBL v4 files and flash their contents to the device.

The Gecko Bootloader can be configured to perform firmware upgrades in standalone mode (also called a standalone bootloader) or in application mode (also called an application bootloader), depending on the component configuration. Components can be installed in and configured through the Simplicity Studio IDE.

A standalone bootloader uses a communications channel to get a firmware upgrade image. NCP (network co-processor) devices always use standalone bootloaders. Standalone bootloaders perform firmware image upgrades in a single-stage process that allows the application image to be placed into flash memory, overwriting the existing application image, without the participation of the application itself. In general, the only time that the application interacts with a standalone bootloader is when it requests to reboot into the bootloader. Once the bootloader is running, it receives packets containing the firmware upgrade image by a physical connection such as UART or SPI. To function as a standalone bootloader with a physical connection, a component providing a communication interface such as UART or SPI must be configured.

An application bootloader relies on the application to acquire the firmware upgrade image. The application bootloader performs a firmware image upgrade by writing the firmware upgrade image to a region of flash memory referred to as the download space. The application transfers the firmware upgrade image to the download space in any way that is convenient (UART, over-the-air, Ethernet, USB, and so on). The download space is data flash or a section of the device’s flash. The Gecko Bootloader can partition the download space into multiple storage slots and store multiple firmware upgrade images simultaneously. To function as an application bootloader, a component providing a bootloader storage implementation must be configured.

Silicon Labs provides example bootloaders that come with a preconfigured set of installed components for configuration in either standalone or application mode. See the _Configuring the Gecko Bootloader_ page. The following sections provide an overview of the Gecko Bootloader common core, drivers, and components. For details, including details on error codes and conditions, see the Gecko Bootloader API Reference, shipped with the SDK in the platform/bootloader/documentation folder.

###### Core

The bootloader core contains the bootloader’s main functions. It also contains functionality to write to the external flash, an image parser to parse and act upon the contents of GBL v4 upgrade files, and functionality to boot the application in main flash.

A version of the GBL v4 image parser without support for encrypted upgrade images is also available. This version can be used in flash space constrained bootloader applications where encryption of the upgrade image is not required.

###### Shared Memory (heading level 7)

To exchange information between the bootloader and application, a section of SRAM is used. The contents of SRAM are preserved through a software reset, making SRAM suitable as a communication channel between bootloader and application.

The shared memory has a size of 4 bytes, and is located at the first address of SRAM, 0x20000000. It is used to store a single word containing the reason for a reset. The structure of the reset cause word is defined in the Reset Information part of the Application Interface, in the file **btl_reset_info.h**, as 16 bits containing the reason, and 16 bits of signature indicating if the word is valid or not. If the signature reads 0xF00F, the reset reason is valid.

All 16-bit reset reasons used by Silicon Labs have the most significant bit set to zero. If custom reset reasons are desired, it is recommended to set the most significant bit to avoid conflicting definitions.

###### Drivers

Different applications for firmware upgrade require different hardware drivers for use by the other components of the bootloader.

Driver modules include:

- Delay: Simple delay routines for use with components that require small delays or timeouts.
- SPI Slave: Flexible SPI Slave driver implementation for use in communication components implementing SPI protocols. This driver supports both blocking and non-blocking operation, with DMA (Direct Memory Access) backing the background transfers to support non-blocking operation.
- UART: Flexible serial UART driver implementation for use in communication components implementing UART protocols. This driver supports both blocking and non-blocking operations, with DMA backing the background transfers to support non-blocking operation. Additionally, support for hardware flow control (RTS/CTS) is included.

###### Components

All parts of the bootloader that are either optional or that may be exchanged for different configurations are implemented as components. Each component may have a configuration header file, and one or more implementations. Components include:

- Communication
- UART: XMODEM
- UART: BGAPI
- Compression
- Debug
- GPIO Activation
- Security
- Storage

###### Communication (heading level 7)

Communication components provide an interface for implementing communication with a host device, such as a computer or a micro-controller. Several components implement the communication interface, using different transports and protocols.

- BGAPI UART DFU: By enabling the BGAPI communication component, the bootloader communication interface implements the UART DFU protocol using BGAPI commands.
- UART XMODEM: By enabling the UART XMODEM communication component, the bootloader communication interface implements the XMODEM-CRC protocol over UART. This component makes the bootloader compatible with the legacy serial-uart-bootloader that was previously released with the EmberZNet wireless stack. See _AN760: Using the Ember Standalone Bootloader_ for more information about legacy Ember standalone bootloaders.

###### Compression (heading level 7)

Compression components provide capability for the bootloader GBL file parser to handle compressed GBL v4 upgrade images. Each compression component provides support for one (de)compression algorithm. At the time of writing, decompression of data compressed with the LZ4 and LZMA algorithms is supported, through the _GBL Compression (LZ4)_ and _GBL Compression (LZMA)_ components.

###### Debug (heading level 7)

This component provides the bootloader with support for debugging output. If the component is configured to enable debug prints, short debug messages will be printed over Serial Wire Output (SWO), which can be accessed in multiple ways, including using Simplicity Commander, and by connecting to port 4900 of the Wireless Starter Kit TCP/IP interface.

To turn on debug prints, enable the Debug component and select **Debug prints**. Select **Debug asserts** to enable assertions in the source code.

###### GPIO Activation (heading level 7)

This component provides functionality to enter firmware upgrade mode automatically after reset if a GPIO pin is active during boot. The GPIO pin location and polarity are configurable.

- GPIO: By enabling the GPIO activation component, the firmware upgrade mode can be activated by push buttons.

###### Security (heading level 7)

Security components provide implementations of cryptographic operations as well as functionality to compute checksums and to read cryptographic keys from manufacturing tokens.

Modules include:

- AES: AES decryption functionality
- CRC16: CRC16 functionality
- CRC32: CRC32 functionality
- ECDSA: ECDSA signature verification functionality
- SHA-256: SHA-256 digest functionality

###### Storage (heading level 7)

These components provide the bootloader with multiple storage options for SoCs. All storage implementations must provide an API to access image files to be upgraded. This API is based on the concept of dividing the download space into storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Some storage implementations also support a raw storage API to access the underlying storage medium. This can be used by applications to store other data in parts of the storage medium that are not used for storing firmware upgrade images. Implementations include:

- **External Flash**: The external flash storage implementation uses the external flash of the device for upgrade image storage. Note that this storage area is only a download space and is separate from the portion of external flash used to hold the active application code.

##### Gecko Bootloader File Format v4

The Gecko Bootloader supports GBL File format v4 for Series 3 device. This format has significant differences as compared to version 3, The file formats described in this section are generated by [Simplicity Commander](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) commands.

###### File Structures

The GBL v4 file format is composed of nested TLV (Type-Length-Value) elements. The format of the TLV is as follows:

|Field|Length (Bytes)|Description|
|---|---|---|
|Type|4|Type indicates the content of the Value field|
|Length|4|Length of the Value field in bytes|
|Value|N|Length size field containing either more TLVs or data|

There are two types of TLVs, data and container. Data TLVs value field contains data whose format is specified in the type field and the container TLVs value filed contains more TLVs, which in turn again may contain data or container TLVs.

###### TLV Descriptions

This section describes each of the TLVs.

###### GBLV4 (heading level 7)

This mandatory TLV is used to identify the GBLv4 file when parsing and tell the length of the file.

|Type|Length|Value|
|---|---|---|
|0x84A617EB|Variable|Contains all the TLVs for the file|

###### MANIFEST (heading level 7)

MANIFEST TLV is present inside the GBLV4 TLV. It has a collection, TLVs, that describes the metadata of the GBLv4 file that is used during the update process.

|Type|Length|Value|
|---|---|---|
|0xAA01012A|Variable|Contains metadata TLVs for applying the file.|

###### MANIFEST_INFO (heading level 7)

The MANIFEST_INFO TVL contains the `ManifestInfo_t` structure that describes the version dependency and the features of the GBL file.

|Type|Length|Value|
|---|---|---|
|0x2B03032B|Variable|manifest_info structure|

The `ManifestInfo_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|version|Minimum version of the GLBv4 parser required, used for future extensions.|
|uint32_t|features|Features requested from the parser (encryption, compression etc.)|

###### BUNDLE_VERSION (heading level 7)

This is the child TVL of MANIFEST TLV, required to identify the bundle/file and is used for versioning and rejection of downgrades.

|Type|Length|Value|
|---|---|---|
|0x2B04042B|Fixed|bundle_version structure|

The `BundleVersion_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|Uint8_t|productId|128 bit unique product ID|
|uint32_t|bundleVersion|Reject if smaller than this exists|
|Uint32_t|minVersion|The minimum previous version to which this update file can be applied|

###### CONTENT_HASH (heading level 7)

An optional TLV that provides integrity checking on the remainder of the file. This TLV is applicable to batch updates only.

|Type|Length|Value|
|---|---|---|
|0x0x2B05052BUL|Fixed|content_hash structure|

The `content_hash` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|hashType|The hash function used to validate (1=SHA, etc.)|
|uint8_t|sha[]|The hash of all contents following the manifest|

###### MANIFEST_CERTIFICATE (heading level 7)

|Type|Length|Value|
|---|---|---|
|0x2B01012B|Fixed|ApplicationCertificate_t|

The `ApplicationCertificate_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint8_t|structVersion|Vesion of the certificate structure|
|uint8_t|flags|Reserved flags|
|uint8_t|key|Public key used to verify GBL file|
|uint32_t|version|Version number of this certificate|
|uint8_t|signature|The signature of the certificate itself (not the GBL file)|

###### MANIFEST_SIGNATURE (heading level 7)

|Type|Length|Value|
|---|---|---|
|0x2B02022BUL|Variable|Manifest signature structure|

The `Manifest_signature` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|Signature function|The function used for signing|
|uint8_t[]|Signature|The signature for authentication|

###### UPDATE_PROCESS (heading level 7)

This is a collection of TLVs that describes the update process. Parsing this TLV does not happen until the MANIFEST_TLV is authenticated. Each TLV contained in this is parsed and processed one at a time in the order they are listed.

|Type|Length|Value|
|---|---|---|
|0xAB06062BUL|Variable|TLVs describing the steps to update the system|

###### UPDATE_SE (heading level 7)

This is an optional TLV that is used to update the SE.

|Type|Length|Value|
|---|---|---|
|0x2C02022CUL|Fixed|UpdateSe_t structure|

The `UpdateSe_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|version|Version number of the SE update image.|
|uint32_t|tlvPosition|The absolute position of the SE update image Blob TLV|

###### UPDATE_MEMORY_SECTION (heading level 7)

The memory section’s content is present in the file and needs to be updated.

|Type|Length|Value|
|---|---|---|
|0x2C03032CUL|Fixed|UpdateMemorySection_t structure|

The `UpdateMemorySection_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint8_t|targetMemory|Which memory this definition is for (0=main memory, 0x1-0x7f = reserved, 0x80-0xff=defined by the user)|
|uint8_t|plainImageSize|Represents the size of the plain image in 3 bytes|
|uint32_t|targetAddr|The target memory address for the update|
|uint32_t|type|Bitfield representing the type of application|
|uint32_t|version|Version number for this application (customer-defined)|
|uint32_t|capabilities|Bitfield representing the capabilities of this application|
|uint32_t|memorySectionPos|The absolute position of the MEMORY_SECTION_TLV in the file|
|HashVaule_t|memSecHash|A hash value for verifying the integrity of the memory section|

###### MANIFEST_FINISH (heading level 7)

TLV to indicate the end of an update.

|Type|Length|Value|
|---|---|---|
|0x2C04042CUL|Fixed|Empty|

###### MEMORY_SECTION (heading level 7)

This TLV contains TLVs for a memory section update.

|Type|Length|Value|
|---|---|---|
|0xBA01013AUL|Variable|TLVs for the region|

###### MEMORY_SECTION_INFO (heading level 7)

This TLV contains information about how the blob data is read and where the data is to be written to. This is a common wrapper for all data as it allows the data to be compressed, verified and processed in a unified manner.

The data can be divided into blocks, with each block having its own hash. This can then be compared with the hashes in the memory section info to authenticate the block. This is useful during streaming updates to avoid writing unauthenticated data to flash.

|Type|Length|Value|
|---|---|---|
|0x3B01013BUL|Fixed|MemSectionPartialInfo_t|

The `MemSectionPartialInfo_t` structure is as follows:

<table>
    <thead>
        <tr>
            <th>Data Type</th>
            <th>Field</th>
            <th>Purpose</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>uint8_t</td>
            <td>compressionScheme</td>
            <td>
                <p>0 = No compression</p>
                <p>1 = LZ4 compression</p>
                <p>2 = LMZA compression</p>
            </td>
        </tr>
        <tr>
            <td>uint8_t</td>
            <td>encryptionScheme</td>
            <td>
                <p>0 = No encryption</p>
                <p>1 = AES CCM</p>
            </td>
        </tr>
        <tr>
            <td>uint8_t</td>
            <td>secureBootScheme</td>
            <td>Reserved for future use.</td>
        </tr>
        <tr>
            <td>uint8_t</td>
            <td>reserved</td>
            <td></td>
        </tr>
        <tr>
            <td>uint16_t</td>
            <td>signBlockSize</td>
            <td>Block size if DFU authentication is done for each block.</td>
        </tr>
        <tr>
            <td>uint16_t</td>
            <td>numBlocks</td>
            <td>Number of blocks inside the BLOB.</td>
        </tr>
        <tr>
            <td>uint8_t[]</td>
            <td>nonce</td>
            <td>Nonce for encryption</td>
        </tr>
        <tr>
            <td>uint8_t[]</td>
            <td>finalImageHash</td>
            <td>Reserved for future use.</td>
        </tr>
        <tr>
            <td>uint8_t[]</td>
            <td>secureBootSign</td>
            <td>Reserved for future use.</td>
        </tr>
    </tbody>
</table>

###### BLOB (heading level 7)

This TLV contains variable length binary data.

|Type|Length|Value|
|---|---|---|
|0x3B02023BUL|Variable|Binary Data|

The figure below shows the structure of a GBL v4 file.

![Structure of GBL V4 file](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image1.png)

##### Gecko Bootloader Operation - Application Upgrade

This section summarizes Gecko Bootloader operation for updating application firmware, first if the Gecko Bootloader is configured in standalone mode and then if it is configured in application mode. The _Gecko Bootloader Operation - Bootloader Upgrade_ provides the same information for updating the bootloader firmware.

###### Standalone Bootloader Operation

Standalone bootloader operation is illustrated in the following figure:

![Standalone Bootloader Operation](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image2.png)

1. The device reboots into the bootloader.
2. A GBL file containing an application image is transmitted from the host to the device. If image encryption is enabled in the  bootloader and the image is encrypted, decryption is performed during the process of receiving and parsing the GBL file.
3. The bootloader applies the application upgrade from the GBL upgrade file on-the-fly. If image authentication is enabled in the bootloader and the GBL file contains a signature, the authenticity of the image is verified before completing the process.
4. The device boots into the application. Application upgrade is complete.

###### Rebooting Into the Bootloader (heading level 7)

The Gecko Bootloader supports multiple mechanisms for triggering the bootloader. If the **GPIO activation** component is installed, the host device can keep this pin low/high (depending on configuration) through reset to make the device enter the bootloader. The bootloader can also be entered through software. The `bootloader_rebootAndInstall` API first signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it will enter firmware upgrade mode instead of booting the existing application.

###### Downloading and Applying a GBL Upgrade File (heading level 7)

When the bootloader enters firmware upgrade mode, it enters a receive loop waiting for data from the host device. The specifics of the receive loop depend on the protocol. Received packets are passed to the image parser, a state machine that parses the data and returns a callback containing any data that should be acted upon. The bootloader core implements this callback and flashes the data to external flash at the specified address. If GBL file authentication or encryption is enabled, the image parser will enforce this, and abort the image upgrade if the authentication fails The bootloader prevents a newly uploaded image from being bootable by holding back parts of the application vector table until the GBL file hash and GBL signature (if required) have been verified.

###### Booting Into the Application (heading level 7)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid and also if the lock bit is set. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

###### Error Handling (heading level 7)

If the application upgrade is interrupted at any time, the device will be without a working application. The bootloader then resets the device, and re-enters firmware upgrade mode. The host device can easily restart the application upgrade process, to try loading the upgrade image again.

###### Application Bootloader Operation

The following figure illustrates the application bootloader operation both for a single image/single storage slot, and multiple images/ multiple storage slots.

![Application Bootloader Operation: Single Storage Slot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image3.png)

![Application Bootloader Operation: Multiple Storage Slots](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image4.png)

1. A GBL file is downloaded onto the storage medium of the device, as described below, and the presence of an upgrade image is indicated.
2. The device reboots into the bootloader, and the bootloader enters firmware upgrade mode.
3. The device applies the application upgrade.
4. The device boots into the application. Application upgrade is complete.

###### Downloading and Storing a GBL Upgrade Image File (heading level 7)

To prepare for receiving an upgrade image, the application finds an available storage slot or erases an existing one using `bootloader_eraseStorageSlot`. If the bootloader only supports a single storage slot, a value of 0 should be used for the slot ID.

The application then receives a GBL file using an applicable protocol, such as Ethernet, USB, Zigbee, OpenThread or Bluetooth, and stores it in the slot by calling `bootloader_writeStorage`.

When the download is complete, the application can optionally verify the integrity of the GBL file by calling `bootloader_verifyImage`. This is also done by the bootloader before applying the image but can be done from the application to avoid rebooting into the bootloader if the received image was corrupt.

If multiple storage slots are supported, the application should write a bootload list by calling `bootloader_setImageToBootload`. The list is written to the two bootload info pages as shown in the figure above. The bootload list is a prioritized list of slots indicating the order the bootloader should use when attempting to perform a firmware upgrade. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader treats the entire download space as a single storage slot.

###### Rebooting and Applying a GBL Upgrade File (heading level 7)

The bootloader can be entered through software. The `bootloader_rebootAndInstall` API signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it enters firmware upgrade mode instead of booting the existing application.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the image stored in each. Once it finds a valid GBL upgrade file, firmware upgrade is attempted from this GBL file. If the upgrade fails, the bootloader moves to the next image in the list. If no images pass verification, the bootloader reboots back into the existing application with a message in the shared memory location in SRAM indicating that no good upgrade images were found.

###### Booting Into the Application (heading level 7)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid as well as if the lock bit is set. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

##### Gecko Bootloader Operation - Bootloader Upgrade

Bootloader upgrade functionality is provided by the Secure Engine on Series 3 devices. The Secure Engine itself is also upgradable. For more details, see the _Gecko Bootloader Operation - Secure Engine Upgrade_ page.

Requirements for upgrading the main bootloader vary depending on the bootloader configuration:

- Application bootloader with storage: Upgrading the main bootloader requires a single GBL file containing both bootloader and application upgrade images.
- Standalone bootloader with communication interface: Upgrading the bootloader requires a GBL file with only the bootloader upgrade image.

Security of the bootloader upgrade process is provided by signing the GBL file. See _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ on the _Gecko Bootloader Security Features_ page.

###### Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)

The process is illustrated in the following figure:

![Standalone Bootloader: Bootloader Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image5.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a bootloader upgrade image is transmitted from the host to the device.
3. The contents of the GBL Bootloader tag are written to the data region in flash
4. The device reboots into the Secure Engine.
5. The Secure Engine replaces the main bootloader with the new version found in the bootloader upgrade GBL.
6. The device boots into the new main bootloader. Bootloader upgrade is complete.

A bootloader upgrade is started in the same way as an application upgrade.

###### Downloading and Applying a Bootloader GBL Upgrade File (heading level 7)

When the bootloader has entered the receive loop, a GBL upgrade file containing a bootloader upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns bootloader upgrade data in a callback. The bootloader core implements this callback and flashes the data to the flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file hash and GBL signature (if required) have been verified.

When a complete bootloader upgrade image is received, the bootloader signals the Secure Engine that it should enter firmware upgrade mode. Secure Engine communication is used to signal that bootloader upgrade is ready to be performed.

The authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See _Setting a Version Number_ on the _Configuring the Gecko Bootloader_ page for more information about versioning bootloader images.

###### Upgrading Bootloaders without Secure Boot to Bootloaders with Secure Boot (heading level 7)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature, using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. Key locations are defined in the bootloader project file btl_security_tokens.c.
4. Create a GBL file using the Gecko Bootloader image. The GBL file needs to be signed/unsigned depending on the current configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
5. Upload the GBL file. For more details on the upgrade process, see the _Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)_ section.

###### Enabling Secure Boot RTSL on Series 3 Devices (heading level 7)

Secure Boot RTSL (Root of Trust and Secure Loader) can be enabled using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in the VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more information on installing public keys, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See the _Signing an Application Image for Secure Boot_ section on the _Gecko Bootloader Security Features_ page for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2.
6. Create a GBL file using the Gecko Bootloader image from step 4.
7. Create a GBL file using the application from step 5. The GBL file need to be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1.
8. Upload the GBL file containing the Gecko Bootloader image.
9. Upload the GBL file containing the application.

###### Bootloader Upgrade on Application Bootloaders with Storage

The process is illustrated in the following figure.

![Application Bootloader: Bootloader Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image6.png)

1. A single GBL file containing a bootloader upgrade image is downloaded onto the storage medium of the device.
2. The device reboots into the main bootloader.
3. The main bootloader verifies the integrity of the upgrade image and then resets the device with reset reason BOOTLOADER_RESET_REASON_UPGRADE to apply the upgrade.
4. The device reboots into the Secure Engine.
5. The Secure Engine replaces the main bootloader with the new version.
6. The device boots into the new main bootloader.

A bootloader upgrade is started in the same way as an Application Upgrade. A GBL file containing a bootloader is written to storage by the application, and the bootloader is entered.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the GBL file stored within. Verification returns information about whether the GBL file contains a bootloader, or both a bootloader and an application. The image parser parses the file. If the GBL file contains a bootloader, the bootloader upgrade data is returned in a callback. The bootloader core implements this callback and flashes the data to internal flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file hash  and GBL signature (if required) have been verified.

Secure Engine communication interface is used to signal the Secure Engine that a bootloader upgrade is ready to be performed.

On Series 3 devices, the authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See the _Setting a Version Number_ section on the _Configuring the Gecko Bootloader_ page for more information about versioning bootloader images.

The new main bootloader is entered, and the images in the list of storage slots marked for bootload are verified. When the image parser parses the slot containing the GBL file with the bootloader + application upgrade, the version number of the bootloader upgrade is equal to the running main bootloader version, so another bootloader upgrade will not be performed. Instead, the application upgrade data are returned in a callback. Bootloading of the new application proceeds as described in the _Application Bootloader Operation_ section on the _Gecko Bootloader Operation Application Upgrade_ page.

###### Storage Space Size Configuration (heading level 7)

The storage space size must be configured to have enough space to store the upgrade images.

###### Upgrading Bootloaders without Secure Boot to Bootloaders with Secure Boot (heading level 7)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature. The procedure is as follows:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. This key can be written by application code running on the device. The Gecko Bootloader prepared from step 1 can be modified to look for the decryption and signature keys in a different location. Key locations are defined in the bootloader project file `btl_security_tokens.c`.
4. Prepare a signed application image using the private key generated in step 2. See the _Signing an Application Image for Secure Boot_ section on the _Gecko Bootloader Security Features_ page for more information on signing an application.
5. Create a GBL file using the Gecko Bootloader image and the signed application image. The GBL file needs to be signed/unsigned depending on the configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
6. Upload the GBL file. For more details on the upgrade process, see the _Bootloader Upgrade on Application Bootloaders with Storage_ section.

###### Enabling Secure Boot RTSL on Series 3 Devices (heading level 7)

Secure Boot RTSL can be enabled by using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See the _Signing an Application Image for Secure Boot_ section on the _Gecko Bootloader Security Features_ page for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2. For more details on how to turn on secure boot on the Secure Engine.
6. Create a GBL file using the Gecko Bootloader image from step 4 and the application from step 5. The GBL file must be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
7. Upload the GBL file containing the Gecko Bootloader image and the application.

##### Gecko Bootloader Operation - Secure Engine Upgrade

The Secure Engine is upgradable and for both application and standalone type of bootloader a GBL file containing the Secure Engine Upgrade image has to be flashed or sent to the bootloader.

A bootloader upgrade can also be included in the same GBL file in application mode, or as a second GBL file in standalone mode. The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the _Memory Space for Bootloading_ section in [Bootloader Fundamentals](https://docs.silabs.com/bootloader/latest/bootloader-fundamentals/).

Signed and encrypted Secure Engine upgrade images are provided by Silicon Labs through Simplicity Studio. Upgrade images with the same or lower version number than the running Secure Engine will be ignored.

To download Secure Engine firmware images, connect a Series 3 device and select a preferred SDK. The Secure Firmware **Update to x.x.x** link appears in the Launcher Perspective, as shown in the following figure.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image7.jpg)

Click **Update to x.x.x** next to Secure FW: x.x.x. A warning dialog box appears. Click **Yes** to continue.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image8.jpg)

The Launcher Perspective is then updated so that the current Secure Firmware version and link version are the same.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image9.jpg)

The Secure Engine firmware images can be found in the _util/se_release/public_ directory under the Gecko SDK. Simplicity Studio displays the SE firmware version available in the Gecko SDK selected.

###### Secure Engine Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)

The process is illustrated in the following figure.

![Standalone Bootloader: Secure Engine Bootloader Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image10.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a Secure Engine upgrade image is transmitted from the host to the device.
3. The device reboots into the Secure Engine.
4. The Secure Engine is replaced by the new version found in the pre-configured upgrade location.
5. The device boots into the bootloader.

###### Downloading and Applying a Secure Engine GBL Upgrade File (heading level 7)

When the bootloader has entered the receive loop, a GBL upgrade file containing a Secure Engine upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns Secure Engine upgrade data in a callback. The bootloader core implements this callback and flashes the data to flash at the pre-configured storage data region.

When a complete Secure Engine upgrade image is received, the bootloader signals the Secure Engine that it should enter firmware upgrade mode. This is done by the Secure Engine communication interface that is used to signal that bootloader upgrade is ready to be performed.

###### Secure Engine Upgrade on Application Bootloaders with Storage

The process is illustrated in the following figure.

![Application Bootloader: Secure Engine Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image11.png)

1. A single GBL file containing a Secure Engine upgrade image is downloaded onto the storage medium of the device.
2. The device reboots into the bootloader.
3. The upgrade image will be fetched directly from the GBL file in storage instead of first copying the image to the pre-configured upgrade location.
4. The device reboots into the Secure Engine.
5. The Secure Engine is replaced by the new version found in the pre-configured upgrade location (or directly from storage, ref. 3b).
6. The device boots into the main bootloader.
7. The bootloader applies the application image from the GBL upgrade file.
8. The device boots into the application. Secure Engine upgrade is complete.

##### Getting Started with the Gecko Bootloader

This section describes how to build a Gecko Bootloader from one of the provided examples. These instructions assume that you have installed Simplicity Studio 5, the SiSDK and associated utilities as described in the SDK’s quick start guide, and that you are familiar with generating, compiling, and flashing an example application in the relevant version.

1. Create a project based on the Gecko Bootloader example of your choice. The project opens with a tab describing the example.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image12.png)
2. Click the project (*.slcp) tab to move to the Project Configurator interface.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image13.png)
3. The Software Components tab shows the list of available components that can be installed in the project.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image14.png)
4. The **Storage Slot Setup** component allows you to configure storage slots to be used if a storage component is also installed. The default configuration matches the target part and bootloader type. This component supports a maximum of three storage slots.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image15.png)
5. Click the **Build** (hammer) icon.
6. After the build is complete, the bootloader binaries are available in the **artifact** folder as depicted in the image below.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image16.png)

The image containing only a bootloader must be used to create a GBL file for bootloader upgrade.

##### Configuring the Gecko Bootloader

###### Configuring Storage

Gecko Bootloaders configured as application bootloaders must include an API to store and access image files. This API is based on the concept of storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Slots are configured in the **Bootloader Storage Slot Setup** component.

When multiple storage slots are configured, a bootload list is used to indicate the order in which the bootloader should access slots to find upgrade images. If multiple storage slots are supported, the application should write the bootload list by calling bootloader_setImageToBootload before rebooting into the bootloader to initiate a firmware upgrade process. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader uses this slot implicitly. A maximum of three slots may be configured in the **Bootloader Storage Slot Setup** component.

###### Storage Configuration (heading level 7)

When configuring a Gecko Bootloader to obtain images fromflash, modify the following.

The **base address of the storage area** should be configured in the **Common Storage** component. This is the address at which the bootloader will place the prioritized list of storage slots to attempt to bootload from, if more than one storage slot is configured. In the default configuration, only a single storage slot is configured, so this value is set to 0, and isn’t used. If more than one storage slot is configured, this value needs to be configured too.

The **location and size of the storage slots** can be configured using the **Bootloader Storage Slot Setup** Component (supports a maximum of three configurable storage slots). The addresses input here are absolute addresses (they are not offsets from the base address). If more than a single slot is configured, enough space must be reserved between the base address as configured in the **Common Storage** component and the first storage slot configured in the **Bootloader Storage Slot Setup** component. Enough space to fit two copies of the bootload list must be reserved. These two copies need to reside on different flash pages, to provide redundancy in case of power loss during writing. Two full flash pages therefore need to be reserved. The following figure illustrates how the storage area can be partitioned.

![Internal Storage Area Configurations](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image17.png)

> **Note**: The storage area partitioning in the example for two storage slots above does not take any NVM system into account. If using an NVM3 , take care to place and size the storage area in such a way that bootloader storage does not overlap with NVM3.

###### Compressed Upgrade Images

The Gecko Bootloader optionally supports compressed GBL files. In a compressed GBL file, only the application upgrade data and bootloader upgrade data is compressed, any metadata (if present) stays uncompressed.  Signature and encryption operations on a compressed GBL work identically to on an uncompressed GBL.

To be able to use compressed upgrade images, a decompressor for the relevant compression algorithm must be added to the Gecko bootloader. The following table shows which compression algorithms are supported by the Gecko Bootloader, and which Bootloader component should be added to enable the feature. The table also shows how much space the decompressor takes up in the bootloader, and how big of a size reduction to expect for the compressed application upgrade image. Be aware of the bootloader size requirement. The bootloader space might be too small to fit the decompressors, depending on the device and enabled components.

|Compression Algorithm|Component|Bootloader Size Requirement|Application Upgrade Size Reduction (typical)|
|---|---|---|---|
|LZ4|GBL Compression (LZ4)|< 1 kB|~ 10%|
|LZMA|Bootloader Compression (LZMA)|~5 kB flash, 18 kB RAM|~ 30%|

It is important to note that the compressed GBL file stays compressed while being transferred to the device, and while it is stored in the upgrade area. It is decompressed by the bootloader when the upgrade is applied. This means that the running application in main flash will be identical to one that was installed using an uncompressed (normal) GBL file.

Compressed GBL files can only be decompressed by the bootloader when running standalone, not through the Application Interface. This means that upgrade image verification performed by the application prior to reboot will not attempt to decompress the application upgrade, it will only verify the signature of the compressed payload. After rebooting into the bootloader, it will decompress the image as part of the upgrade process.

###### LZMA Compression Settings (heading level 7)

LZMA decompression is only supported for images compressed with certain compression settings. Simplicity Commander automatically uses these settings during gbl4 creation.

- Probability model counters: lp + lc <= 2. Simplicity Commander uses lp=1, lc=1.
- Dictionary size no greater than 8 kB. Simplicity Commander uses 8 kB.

Together, these settings cause the decompressor to require 18 kB of RAM for decompression – 10 kB for the counters and 8 kB for the dictionary.

The Gecko bootloader only supports decompressing payloads that contain the end mark as the last 8 bytes of the compressed stream.

###### Bootloader Example Configurations

The following sections describe the key configuration options for the example bootloader applications.

> **Note**: Security features are disabled for all example configurations. In development, Silicon Labs strongly recommends enabling security features to prevent unauthorized parties from uploading untrusted program code. See the _Using Application Image Security Features_ section on the _Gecko Bootloader Security Features_ page to learn how to configure the security features of the Gecko Bootloader.

###### UART XMODEM Bootloader (heading level 7)

Standalone bootloader for Series 3 devices running the EmberZNet PRO and Silicon Labs Connect protocol stacks, using XMODEM-CRC over UART.

In this configuration, the **UART XMODEM** communication component, **XMODEM Parser** component, and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The **GPIO activation** component is also installed by default, allowing bootloader entry into firmware upgrade mode by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### BGAPI UART DFU Bootloader (heading level 7)

Standalone bootloader for the Bluetooth protocol stack, using the BGAPI protocol for UART DFU. This bootloader should be used for all NCP-mode Bluetooth applications.

In this configuration, the **BGAPI UART DFU** communication component and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The GPIO activation component is also installed by default, allowing bootloader entry by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### Storage Bootloader (heading level 7)

Application bootloader for all wireless protocol stacks, using flash to store upgrade images received over the air by the application.

Multiple examples are provided, including configurations for 2 MB, 3 MB, 4 MB & 8 MB flash memory devices . **The storage layout should be modified before running the bootloader on any other devices**. In this configuration, the flash and common storage components are installed. The base address of the storage area is configured in the **Common Storage** component. The location and size of the storage slots can be configured using the **Bootloader Storage Slot Setup** component (provides up to three configurable storage slots). Default example applications are provided with configurations for both single storage slot and multiple storage slots.

The default storage slot configurations provided by the Gecko Bootloader **must** be configured to match the use-case-specific application configurations, as shown below.

|Sample Applications|Storage Offset|Storage Size|
|---|---|---|
|Storage Bootloader (Single OTA Image of size 792kB)|0x010E0000|0x000C6000 (811,008 bytes)|
|Storage Bootloader (Single OTA Image of size 1180kB)|0x0128F000|0x00127000 (1,210,368 bytes)|
|Storage Bootloader (Single OTA Image of size 1540kB)|0x01379000|0x00181000 (1,577,984 bytes)|

###### Image Acquisition Application Example Configuration

These examples illustrate applications that acquire and store a GBL upload image for an application bootloader. For the running bootloader to accept an application upgrade, the new application version must be higher than the existing version.

###### Setting a Version Number

To distinguish between different builds of the Gecko Bootloader, it is useful to set a version number. To perform a bootloader upgrade, not only must the running bootloader pass its integrity checks (see the _Downloading and Applying a Bootloader GBL Upgrade File_ section on the _Gecko Bootloader Operation Bootloader Upgrade_ page), but the bootloader upgrade image must also have a higher version number than the running bootloader image. A version number can be set using Simplicity Studio by configuring the **Bootloader Version Main Customer** option of the **Bootloader Core** component. This macro will be picked up by the config file **btl_config.h**, where it is combined with the version number of the Gecko Bootloader files provided by Silicon Labs.

###### Hardware Configuration

The Gecko Bootloader uses the Pin Tool for configuration of pinout and other hardware-related settings. When Pin Tool configuration is available for a bootloader component, the relevant settings are shown in the Component Editor for that component.

![Example of USART Configuration for UART Driver](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image18.png)

The standalone Pin Tool User Interface can also be used to configure settings for Gecko Bootloader if desired.

While the Pin Tool provides configuration for many different peripherals, the Gecko Bootloader uses only the following Pin Tool modules:

- SERIAL is used by the UART Driver component to configure baud rate, flow control mode and pinout.
- VCOM is used by the UART Driver component to enable the serial interface if necessary (only on Silicon Labs Wireless Starter Kits).
- BTL_BUTTON is used by the GPIO Activation component.
- CMU HFXO frequency setting is used by the delay driver to calibrate timing if the core is running from the HFXO.

Other settings, like CMU oscillator configuration or DCDC configuration, are not taken into consideration by the default bootloader code. If using these configuration settings is desired, the required code must be added in btl_main.c.

> **Note**: While the delay driver uses the HFXO frequency setting from Pin Tool, the HFXO enable setting is not used to initialize the HFXO on startup. This setting is only used when calling the bootloader through the Application Interface, and the application has switched to the HFXO prior to calling the Bootloader Application Interface API.

##### Simplicity Commander and the Gecko Bootloader

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple CLI (Command Line Interface) that is also scriptable. You can use Simplicity Commander to perform these essential tasks:

- Generating key files for signing and encryption
- Signing application images for Secure Boot
- Creating GBL images (encrypted or unencrypted, signed, or unsigned)
- Parsing GBL images

Simplicity Commander is used throughout the examples in the following sections. For more information on executing commands to complete these tasks, see the [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

> **Note**: Simplicity Commander also offers a GUI (Graphical User Interface) that can be used in the lab for typical tasks such as flashing device images. The functions described in this User Guide are performed from the CLI.

###### Creating GBL V4 Files Using Simplicity Commander

To create an unsigned GBL V4 file from an application **myapp.s37**, execute `commander gbl4 create myapp.gbl -–config configfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
updates:
  - data: myapp.s37
    block_size: 0
```

To create an unsigned GBL V4 file from a bootloader upgrade **mybootloader.s37**, execute `commander gbl4 create mybootloader.gbl –-config confligfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
updates:
  - data: mybootloader.s37
    block_size: 0
```

This file can be used with the standalone bootloader configurations of the Gecko Bootloader.

To create an unsigned GBL file from a Secure Engine, upgrade **mySecureElement.seuv2**, and execute `commander gbl4 create mySecureElement.gbl –config configfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
se_upgrade:
  se_file: mysecureElement.seuv2
```

The Secure Engine images, .seuv2, are provided by Silicon Labs and can be found through Simplicity Studio. See the _Gecko Bootloader Operation - Secure Engine Upgrade_ section on the _Gecko Bootloader Operation Secure Engine Upgrade_ page.

The command can also be used to create a single upgrade image, suitable for use with application bootloader configurations of the Gecko Bootloader: `commander gbl4 create myupgrade.gbl –config configfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
updates:
  - data: myapp.s37
  - data:mybootloader.s37

se_upgrade:
  se_file: mysecureElement.seuv2
```

##### Gecko Bootloader Security Features

###### About Bootloader Image Security

Secure Boot and Secure Firmware Upgrade, discussed in the following sections, enables Gecko Bootloader to provide authenticity and integrity checks on the Application image, which provides a sufficient level of security for many applications. However, in systems without a hardware root of trust, no process checks the authenticity or integrity of the Gecko Bootloader itself. Its security is provided solely by the device hardware and the robustness of the software running on the device.

The native behavior of Firmware Upgrade will prevent accidental version rollback of Gecko Bootloader under normal usage conditions.

###### About Application Image Security

The Gecko Bootloader can enforce security on two levels:

- Secure Boot refers to the verification of the authenticity of the application image in main flash on every boot of the device.
- Secure Firmware Upgrade refers to the verification of the authenticity of an upgrade image before performing a bootload, and optionally enforcing that upgrade images are encrypted.

###### Secure Boot Procedure (heading level 7)

When Secure Boot is enabled, the cryptographic signature of the application image in flash is verified on every boot before the application is allowed to run. Secure Boot is not enabled by default in the example configurations provided by Silicon Labs, but enabling it is highly recommended to ensure the validity and integrity of firmware images.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA (elliptical curve digital signature algorithm) of the SHA-256 digest of the application firmware image, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

1. On boot, the bootloader checks the application image for information about whether it is signed.
2. The type of signature and signature location is determined.
3. If the type of signature does not match the requirements of the bootloader, the bootloader enters device firmware upgrade mode and prevents the application from running.
4. According to the chosen signature algorithm, the signature of the contents of flash from the beginning of the application to the location of the signature is compared to the signature at the signature location.
5. If the signatures do not match, the bootloader enters device firmware upgrade mode and prevents the application from running.

**Secure Boot using ECDSA-P256-SHA256**

For an image to be signed for Secure Boot, the application needs to contain a copy of the **ApplicationProperties_t** struct. This struct contains information about which signature algorithm is used, and where to find the signature.

On every boot, the bootloader calculates the SHA-256 digest of the application image, from the beginning of the application to the start of the signature. The signature of the SHA-256 digest is then verified using ECDSA-P256.

If the signature is valid, the application is allowed to boot. Else, the bootloader is entered, and an application upgrade is attempted if one is available.

Simplicity Commander can be used to generate a key pair and write the public key to the device. See the [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more information.

**Secure Boot with Application Rollback Protection**

On every boot, the application version in the **ApplicationData_t** struct is stored at the end of the bootloader area in flash, which is used to prevent applications from being downgraded. The application version can remain the same for upgrades.

If application rollback prevention component is installed in the bootloader project, then before applying the upgrade image, the bootloader will check the application version in the application properties structure that resides inside the signed/encrypted GBL file and will only apply the OTA image to application area if the application version in ApplicationData structure is equal or higher than the highest application version last seen.

The application rollback prevention feature can be enabled in the **Bootloader Core** component by selecting the **Enable application rollback protection** option. The **Minimum application version allowed** option can be used to configure the minimum application version that should be allowed to boot.

The application versions are stored in the SE OTP area.

**Secure Boot Using a Certificate**

On Series 3 devices, a certificate-based secure boot operation is supported. The Certificate contains:

- Struct version: The version of the certificate structure.
- Public key: ECDSA-P256 public key, X and Y coordinates concatenated, used to validate the image.
- Certificate version: The version of the running certificate.
- Signature: ECDSA-P256 signature, used for the authentication of the public key and the certificate version.

The definition of the certificate struct can be found in `api/application_properties.h`.

To utilize certificate-based secure boot, configure Secure Engine to authenticate the bootloader image by configuring the certificate-based secure boot option in the Secure Engine OTP. Configure the Gecko Bootloader to enable certificate-based secure boot in the **Bootloader Core** component by selecting the **Enable certificate support** option. The Gecko Bootloader certificate must be signed by the private key pair of the public key stored in the Secure Engine OTP. For more information on the key storage, see the _Key Storage_ section.

The certificate-based secure boot procedure is illustrated in the following figure.

![Certificate-Based Secure Boot Procedure](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image19.jpg)

Once the certificate-based secure boot option on Secure Engine is turned on, Secure Engine verifies the Gecko Bootloader certificate. The public key stored in the certificate is used to validate the signature of the Gecko Bootloader. Secure Engine will not accept bootloader images without a certificate.

If only the secure boot option is enabled (not certificate-based) on Secure Engine, and Secure Engine identifies a certificate, the certificate will be used to validate the bootloader image. If the certificate version from the bootloader image is higher than 0 and it gets verified once, Secure Engine will never again accept direct signed bootloader images without a certificate.

The Gecko Bootloader will authenticate the direct signed application using the public key stored in the Gecko Bootloader certificate. If the application contains a certificate, Gecko Bootloader will authenticate it. The procedure is illustrated in the following figure.

![Advanced Certificate-Based Secure Boot Procedure](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image20.jpg)

After authentication of the application certificate, Gecko Bootloader verifies the signature of the application using the public key from the application certificate. In addition, Gecko Bootloader compares the Gecko Bootloader certificate version against the application certificate version. All application images with certificate version lower than the certificate version of the Gecko Bootloader will be rejected. Gecko Bootloader can be configured to only allow applications with certificates to boot by configuring the **Bootloader Core** component by selecting the **Reject direct signed images** option.

The **ApplicationProperties_t** struct contains the certificate struct **ApplicationCertificate_t**. The certificate struct can be injected to images that contain an **ApplicationProperties_t** with **ApplicationCertificate_t**. To inject a certificate to an image, issue the following command from Simplicity Commander:

```C
commander convert <image file> --secureboot --keyfile <signing key> --certificate <certificate>
--outfile <signed image file with certificate>
```

###### Secure Firmware Upgrade (heading level 7)

The Gecko Bootloader supports a secure firmware upgrade process. This is achieved by using symmetric encryption to encrypt the upgrade image, and asymmetric cryptography to sign the upgrade image. Symmetric encryption provides confidentiality, and asymmetric cryptography provides integrity and authenticity. Note that encryption alone is not enough to provide authenticity.

**Encryption Algorithms**

The Gecko Bootloader supports the AES-CTR-128 encryption algorithm. The GBL upgrade file is encrypted using 128-bit AES in Counter mode with a random nonce as the initial counter value.

To make use of the OTA decryption key stored in the Secure Engine OTP, the **Use symmetric key stored in Secure Engine storage** option in the **Bootloader Core** component must be selected. Simplicity Commander can be used to generate an OTA decryption key and write the key to the device. For more information on storing the OTA decryption key on Series 3 devices, see [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

The Secure Engine OTP key support depends on the SE Manager component, which is enabled by default.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA signature of the SHA-256 digest of the GBL upgrade file, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

Before starting a firmware upgrade process, the application can verify an image in storage by calling into the bootloader verification functions. For bootloaders with Communication Interface, the host device should verify the image before sending it to the NCP or RCP.

During firmware upgrade, the GBL file is parsed, and if encrypted, decrypted on-the-fly. A GBL Signature Tag in the GBL file indicates to the bootloader that the file is signed, and the signature is verified. If signature verification fails, the firmware upgrade process is aborted.

On Series 3 devices, Gecko Bootloader will authenticate the GBL signature tag using the public key stored in the bootloader certificate if the **Enable certificate support** option is selected in the **Bootloader Core** component. A GBL Certificate tag in the GBL file indicates to the bootloader that the GBL certificate tag needs to be authenticated using the public key stored in the bootloader certificate. The certificate version in the GBL certificate tag is compared with the bootloader certificate and only a version equal or higher than the bootloader certificate is accepted. Once the GBL certificate tag is authenticated, the GBL file's signature is verified using the authenticated public key from the GBL certificate tag.

###### Using Application Image Security Features

This example assumes that a bootloader called **bootloader-uart-xmodem** has been built in Simplicity Studio.The relevant version can be flashed to the device using the Flash Programmer in Simplicity Studio or using Simplicity Commander.

This example provides two ways of signing the upgrade images. The first option uses Simplicity Commander to generate key material and sign data. This is suitable for development. The second option uses an external signer, such as a dedicated Hardware Security Module (HSM) to protect private key material and perform signing operations. Silicon Labs recommends using an HSM to safeguard private keys.

###### Generating Keys (heading level 7)

To use the security features of the Gecko Bootloader, encryption and signing keys need to be generated. These keys must then be written to the device. The encryption key is used with the GBL file for secure firmware upgrade. The signing keys are used both with the GBL file for secure firmware upgrade and to sign the application image for Secure Boot.

**Generating a Signing Key Using Simplicity Commander**

```C
commander util genkey --type ecc-p256 --privkey signing-key --pubkey signing-key.pub
```

This creates an ECDSA-P256 key pair for signing; `signing-key` contains the private key in PEM format and **must be kept secret from third parties**. This key will later be used to sign images and GBL files. `signing-key.pub` contains the public key in PEM format and can be used to verify GBL files using commander gbl4 info.

**Generating a Signing Key Using a Hardware Security Module**

When using a Hardware Security Module, the private key is kept secret inside the HSM. According to the instructions from your HSM vendor, have it generate an ECDSA-P256 key pair and export the public key in PEM format to the file **signing-key.pub**. Then use Simplicity Commander to convert the key to token format, suitable for writing to the Series 3 device.

```C
commander gbl keyconvert --type ecc-p256 signing-key.pub
```

**Generating an Encryption Key**

```C
commander util genkey --type aes-ccm --outfile encryption-key
```

This creates an AES-128 key for encryption in the file **encryption-key**.

**Writing Keys to the Device**

> **Note**: Refer to the sections, _Writing the AES Decryption Key_ and _Writing the Public Key to the Device_ in the [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### Signing an Application Image for Secure Boot (heading level 7)

If the bootloader enforces Secure Boot, the application needs to be signed to pass verification. On every boot, a SHA-256 digest of the application is calculated. The signature is verified using ECDSA-P256, with the same public key as for the GBL file signing. Signature verification failure prevents the application from booting.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see the _Application Properties_ section on the _Application Interface_ page.

**Using Simplicity Commander**

Signing the application can be done with the command:

```C
commander convert myapp.s37 --secureboot --keyfile signing-key --outfile myapp-signed.s37
```

**Using a Hardware Security Module**

The application can be prepared for signing by issuing the command:

```C
commander convert myapp.s37 --secureboot --extsign --outfile myapp-for-signing.s37
```

Using an HSM, sign the output file **myapp-for-signing.s37**, and supply the resulting DER-formatted signature file **signature.der** back to Simplicity Commander:

```C
commander convert myapp-for-signing.s37 --secureboot --signature signature.der --verify signing-key.pub

--outfile myapp-signed.s37
```

###### Creating a Signed and Encrypted GBL Upgrade Image File from an Application (heading level 7)

To create a GBL file from an application, use `commander gbl4 create`.

Note that, as of this writing, secure application images can only be constructed through Simplicity Commander, not through the configuration options available through Simplicity Studio.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see the _Application Properties_ section on the _Application Interface_ page.

**Using Simplicity Commander to Sign**

For an application called **myapp.s37**, use:

```C
commander gbl4 create myapp.gbl -–config configfile.yaml

```

Example of a config file is as follows:

```C
manifest:
 product_id: "[16 B ID] (default from app or 00000000000000000000000000000000)"
 bundle_version: "[version] (default 0x00000000)"
 min_version: "[version] (default 0x00000000)"
 hash_function: "[none | sha256] (default sha256)"
 certificate: "[path to file] (optional)"
 signing_key: "[path to file] (optional)"
se_upgrade:
 se_file: "[path to file] (optional)"
updates:
 - data: <path to file>
  app_type: "[uint32] (default from app or 0x00000000)"
  app_capabilities: "[uint32] (default from app or 0x00000000)"
  version: "[uint32] (default from app or 0x00000000)"
  compression_scheme: "[none | lz4 | lzma] (default none)"
  encryption_scheme: "[none | aes-ctr-128] (default none)"
  block_size: "[size in bytes] (default 0/disabled)"
```

This single command performs three actions:

- Creates a GBL file
- Encrypts the GBL file
- Signs the GBL file

If Secure Boot is also desired, the application must be signed using `commander convert --secureboot` prior to creating the GBL.

###### System Security Considerations

The Gecko bootloader security features can be used to create a secure device, but do not create a secure system by themselves. This section goes over considerations that need to be taken when designing a secure system where the Gecko Bootloader is a component.

###### Key Storage (heading level 7)

On Series 3 devices, the decryption key and the sign key used by the Gecko Bootloader in the Secure Engine OTP. The decryption key can be provisioned in the Secure Engine OTP using Simplicity Commander or using the Secure Engine Mailbox interface. Once a key value has been programmed into the Secure Engine OTP, it cannot be changed.

##### Application Interface

The bootloader has an application interface exposed through a function table in the bootloader. The application interface provides APIs to use bootloader functions for storing and retrieving upgrade images and verifying their integrity. APIs to reboot into the bootloader are also provided. For details see the Gecko Bootloader API Reference, at [https://docs.silabs.com/gecko-platform/5.1.2/platform-bootloading-overview/folder](https://docs.silabs.com/gecko-platform/5.1.2/platform-bootloading-overview/folder).

If you are not using a protocol stack from Silicon Labs, the **api/btl_interface.h** header provides the bootloader application interface API. If you are using a protocol stack from Silicon Labs, the recommended bootloader interface API for the specific protocol stack should be used instead. The following files provide the implementation of the bootloader interface:

**api/btl_interface.c** (common interface)

**api/btl_interface_storage.c** (interface to storage functionality)

The application interface consists of functions that can be included in the customer application, and that communicate with the bootloader through the **MainBootloaderTable_t**. This table contains function pointers into the bootloader. The 10th word of the bootloader contains a pointer to this structure, allowing any application to easily locate it. Using the wrapper functions provided in the Bootloader Interface API is preferred over accessing the bootloader table directly. Modules include:

- **Application Storage Interface**: Application interface for interfacing with bootloader storage. The Storage Interface is only available on bootloaders that support the storage interface.
- **Common Application Interface**: Generic application interface available on all versions of the bootloader, independently of which components are present.

###### Application Properties

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. The Simplicity Commander extracts the metadata contained in this structure from the application and places it in the UPDATE_MEMORY_SECTION tag in the GBL upgrade file. If the structure is not present in the application, Simplicity Commander will raise an error. The **ApplicationProperties_t** struct is added to the application on installing the **bootloader_interface** component to the application. The **bootloader_interface** component installs **bootloader_app_properties** component which adds an instance of **ApplicationProperties_t** named **sl_app_properties** to the project. The component adds a source file named **app_properties.c** and a configuration file named **app_properties_config.h**. This configuration file allows users to configure the application version via Simplicity Studio’s Component Editor. To open the Component Editor, locate the **App Properties** component under **Platform > Bootloader** as shown below.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image21.png)

Click **Configure** to open the Component Editor.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image22.png)

The application type is automatically populated based on the wireless stack used in building the project. The value of the application type is automatically set during the project generation step and can be found in **autogen/sl_application_type.h** file.

The contents of the **GBL Application Tag** can be extracted from a GBL file by a running application using the Application Storage interface. Note that the **GBL Application Tag** will only be added if the GBL file contains an application image, not if the GBL file only contains a bootloader upgrade or metadata.

The structure in the application is also used to declare whether the application image is signed, and what type of signature is used. This information is added by Simplicity Commander when signing the image using `commander convert (--secureboot, --extsign or -- signature)`. For the bootloader to locate the **ApplicationProperties_t** struct, if not already done by the linker, Simplicity Commander modifies word 13 of the application to insert a pointer to the **ApplicationProperties_t** struct when signing the application image for Secure Boot.

###### Error Codes

Most Gecko bootloader APIs return error codes. The following table lists the groups of error codes that may be returned. The full list of error codes within each group can be found in _api/btl_errorcode.h_ in the platform/bootloader directory of the SDK, as well as in the API Reference.

|ID|Description|
|---|---|
|0x0|OK|
|0x01xx|Initialization error|
|0x02xx|Image verification error|
|0x04xx|Storage error|
|0x05xx|Bootload error|
|0x06xx|Security error|
|0x07xx|Communication error|
|0x09xx|XMODEM parser error|
|0x10xx|GBL file parser error|
|0x11xx|SPI slave driver error|
|0x12xx|UART driver error|
|0x13xx|Compression error|
|0x14xx|RTOS error|

#### Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher

##### Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher

> **Note: This section replaces _UG489: Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher_. Further updates to this user guide will be provided here**.

This document describes the high-level implementation of the Silicon Labs Gecko Bootloader for EFM32 and EFR32 Series 1 and Series 2 microcontrollers, SoCs (System on Chips) and NCPs (Network Co-Processors), and provides information on different aspects of configuring the Gecko Bootloader. If you are not familiar with the basic principles of performing a firmware upgrade or want more information about upgrade image files, refer to [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/). For more information on using the Gecko Bootloader with different wireless stacks, see the following:

- [Using the Gecko Bootloader with EmberZNet](https://docs.silabs.com/zigbee/latest/using-gecko-bootloader-with-zigbee/)
- [Bootloading and OTA with Silicon Labs Connect v3.x](https://docs.silabs.com/connect-stack/latest/bootloading-and-ota-with-connect-v3x)
- [Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/)

For more information on Series 2 device security, see:

- [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)
- [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/)
- [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/)

For more information on security using Series 2 devices with Secure Vault, see:

- [Anti-Tamper Protection Configuration and Use](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/)
- [Authenticating Silicon Labs Devices using Device Certificates](https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/)
- [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/)

##### Overview

The Silicon Labs Gecko Bootloader is a common bootloader for all the newer MCUs and wireless MCUs from Silicon Labs. The Gecko Bootloader can be configured to perform a variety of functions, from device initialization to firmware upgrades. Key features of the bootloader are:

- Useable across Silicon Labs Gecko microcontroller and wireless microcontroller families
- In-field upgradeable
- Configurable
- Enhanced security features, including:  
  - **Secure Boot**: When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot, using asymmetric cryptography. This ensures that the application was created and signed by a trusted party.  
  - **Signed upgrade image file**: The Gecko Bootloader supports enforcing cryptographic signature verification of the upgrade image file. This allows the bootloader and application to verify that the application or bootloader upgrade comes from a trusted source before starting the upgrade process, ensuring that the image file was created and signed by a trusted party.  
  - **Encrypted upgrade image file**: The image file can also be encrypted to prevent eavesdroppers from acquiring the plaintext firmware image.

The Gecko Bootloader uses a proprietary format for its upgrade images, called GBL (Gecko Bootloader file). These files have the file extension “.gbl”. See section [Gecko Bootloader File Format](02-gecko-bootloader-file-format#gecko-bootloader-file-format) for more details.

On Series 1 devices, the Gecko Bootloader has a two-stage design, first stage and main stage, where a minimal first stage bootloader is used to upgrade the main bootloader. The first stage bootloader only contains functionality to read from and write to fixed addresses in internal flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to a fixed location in internal flash and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader firmware upgrade image, by computing a CRC32 checksum before copying the upgrade image to the main bootloader location.

On Series 2 devices, the Gecko bootloader consists only of the main stage bootloader. The main bootloader is upgradable through the Secure Engine. The Secure Engine may be hardware-based, or virtual (software). If hardware-based, the implementation may be either with or without Secure Vault. Throughout this document, the following conventions will be used.

- HSE - Hardware Secure Engine, either with or without Secure Vault if not specified
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE, in general)

The Secure Engine provides functionality to install an image to address 0x0 in internal flash, by copying from a configurable location in internal flash. This makes it possible to have a 2-stage design, where the main bootloader is not present. However, the presence of a main bootloader is assumed throughout this document.

To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to the upgrade location in flash and requests that the Secure Engine installs it. On some devices, the Secure Engine is also capable of verifying the authenticity of the main bootloader update image against a root of trust. The Secure Engine itself is upgradable using the same mechanism. See [Gecko Bootloader Operation - Secure Engine Upgrade](05-gecko-bootloader-operation-secure-engine-upgrade#gecko-bootloader-operation-secure-engine-upgrade) for more details.

The main bootloader consists of a common core, drivers, and a set of components that give the bootloader specific capabilities. The common bootloader core is now provided as a full-source delivery, as opposed to previously being a combination of compiled libraries and source code while the components continue to be delivered as source code. The common bootloader core contains functionality to parse GBL files and flash their contents to the device.

The Gecko Bootloader can be configured to perform firmware upgrades in standalone mode (also called a standalone bootloader) or in application mode (also called an application bootloader), depending on the component configuration. Components can be installed in and configured through the Simplicity Studio IDE.

A standalone bootloader uses a communications channel to get a firmware upgrade image. NCP (network co-processor) devices always use standalone bootloaders. Standalone bootloaders perform firmware image upgrades in a single-stage process that allows the application image to be placed into flash memory, overwriting the existing application image, without the participation of the application itself. In general, the only time that the application interacts with a standalone bootloader is when it requests to reboot into the bootloader. Once the bootloader is running, it receives packets containing the firmware upgrade image over-the-air using Bluetooth or by a physical connection such as UART or SPI. To function as a standalone bootloader with a physical connection, a component providing a communication interface such as UART or SPI must be configured.

An application bootloader relies on the application to acquire the firmware upgrade image. The application bootloader performs a firmware image upgrade by writing the firmware upgrade image to a region of flash memory referred to as the download space. The application transfers the firmware upgrade image to the download space in any way that is convenient (UART, over-the-air, Ethernet, USB, and so on). The download space is either an external memory device such as an EEPROM or dataflash or a section of the device’s internal flash. The Gecko Bootloader can partition the download space into multiple storage slots and store multiple firmware upgrade images simultaneously. To function as an application bootloader, a component providing a bootloader storage implementation has to be configured.

Silicon Labs provides example bootloaders that come with a preconfigured set of installed components for configuration in either standalone or application mode. See section [Configuring the Gecko Bootloader](07-configuring-the-gecko-bootloader#configuring-the-gecko-bootloader). The Silicon Labs Gecko SDK Suite also includes precompiled bootloader images for several different EFR32 devices. As of this writing, the images shown in the following table are provided.

> **Note**: The bootloader security features are not enabled in these precompiled images.

Table Prebuilt Bootloader Images

<table>
    <thead>
        <tr>
            <th>Use</th>
            <th>Wireless Stack</th>
            <th>Image Name</th>
            <th>Mode</th>
            <th>Interface</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SoC</p>
            </td>
            <td>
                <p>EmberZNet PRO</p>
            </td>
            <td>
                <p>SPI Flash Storage Bootloader</p>
            </td>
            <td>
                <p>Application</p>
            </td>
            <td>
                <p>SPI Serial Flash</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SoC</p>
            </td>
            <td>
                <p>Bluetooth</p>
            </td>
            <td>
                <p>Bluetooth In-Place OTA DFU Bootloader</p>
            </td>
            <td>
                <p>Application</p>
            </td>
            <td>
                <p>OTA/internal flash</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>NCP</p>
            </td>
            <td>
                <p>EmberZNet PRO</p>
            </td>
            <td>
                <p>UART XMODEM Bootloader</p>
            </td>
            <td>
                <p>Standalone</p>
            </td>
            <td>
                <p>UART (EZSP)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>NCP</p>
            </td>
            <td>
                <p>Bluetooth</p>
            </td>
            <td>
                <p>BGAPI UART DFU Bootloader</p>
            </td>
            <td>
                <p>Standalone</p>
            </td>
            <td>
                <p>UART (BGAPI)</p>
            </td>
        </tr>
    </tbody>
</table>

Note that on devices with a dedicated bootloader area (EFR32xG12 and later Series 1 devices), if the device is configured to boot to the bootloader area (that is, if bit 1 of the Config Lock Word 0 CLW0[1] is set), an image always must be present in the bootloader area. The device is factory-programmed with a dummy bootloader that simply jumps directly to the application in main flash. This means that when flashing a bootloader to a device with a dedicated bootloader area, this dummy bootloader is replaced. If later during development using the bootloader is no longer desired, CLW0[1] must be cleared or the dummy bootloader needs to be re-flashed. Platform-specific prebuilt dummy bootloader images are located in _./platform/bootloader/util/bin/_. Note that since the dummy bootloader only consists of a few instructions and doesn't pad out the remainder of the bootloader area, only the first flash page (where the first-stage bootloader resides) is overwritten, so the main stage bootloader would likely remain intact after programming the dummy bootloader. If desired, the rest of the flash pages in the bootloader area can then be erased separately.

On devices that do not have a dedicated bootloader area (EFR32xG1 and EFR32 Series 2), a dummy bootloader is not needed.

The following sections provide an overview of the Gecko Bootloader common core, drivers, and components. For details, including details on error codes and conditions, see the Gecko Bootloader API Reference, shipped with the SDK in the platform/bootloader/documentation folder.

The bootloader area can be fully erased using the `commander device pageerase --region @bootloader` command with Simplicity Commander. In this state, the device will not boot until CLW0[1] is cleared or the dummy bootloader is flashed. For more information on how to use Simplicity Commander with Gecko bootloader, see section [Simplicity Commander and the Gecko Bootloader](08-simplicity-commander-and-the-gecko-bootloader#simplicity-commander-and-the-gecko-bootloader).

###### Core

The bootloader core contains the bootloader’s main functions. It also contains functionality to write to the internal flash, an image parser to parse and act upon the contents of GBL upgrade files, and functionality to boot the application in main flash.

The image parser can also optionally support the legacy Ember Bootloader (EBL) file format, but none of the security features offered by the Gecko Bootloader are supported if support for legacy EBL files is enabled.

A version of the GBL image parser without support for encrypted upgrade images is also available. This version can be used in flash space constrained bootloader applications where encryption of the upgrade image is not required.

###### Shared Memory (heading level 7)

To exchange information between the bootloader and application, a section of SRAM is used. The contents of SRAM are preserved through a software reset, making the SRAM suitable as a communication channel between bootloader and application.

The shared memory has a size of 4 bytes, and is located at the first address of SRAM, 0x20000000. It is used to store a single word containing the reason for a reset. The structure of the reset cause word is defined in the Reset Information part of the Application Interface, in the file **btl_reset_info.h**, as 16 bits containing the reason, and 16 bits of signature indicating if the word is valid or not. If the signature reads 0xF00F, the reset reason is valid.

All 16-bit reset reasons used by Silicon Labs have the most significant bit set to zero. If custom reset reasons are desired, it is recommended to set the most significant bit to avoid conflicting definitions.

In addition to the reset causes defined in the Reset Information documentation, the bootloader will enter firmware upgrade mode if the shared memory contains the value 0x00000001. This value is supported for compatibility with certain legacy Bluetooth applications.

###### Drivers

Different applications of firmware upgrade require different hardware drivers for use by the other components of the bootloader.

Driver modules include:

- Delay: Simple delay routines for use with components that require small delays or timeouts.
- SPI: Simple, blocking SPI master implementation for communication with external devices such as SPI flashes.
- SPI Slave: Flexible SPI Slave driver implementation for use in communication components implementing SPI protocols. This driver supports both blocking and non-blocking operation, with DMA (Direct Memory Access) backing the background transfers to support non-blocking operation.
- UART: Flexible serial UART driver implementation for use in communication components implementing UART protocols. This driver supports both blocking and non-blocking operation, with DMA backing the background transfers to support non-blocking operation. Additionally, support for hardware flow control (RTS/CTS) is included.

###### Components

All parts of the bootloader that are either optional or that may be exchanged for different configurations are implemented as components. Each component may have a configuration header file, and one or more implementations. Components include:

- Communication  
  - UART: XMODEM  
  - UART: BGAPI  
  - SPI: EZSP  
  - Bluetooth: AppLoader
- Compression
- Debug
- GPIO Activation
- Security
- Storage  
  - Internal flash  
  - External SPI flash

###### Communication (heading level 7)

The Communication components provide an interface for implementing communication with a host device, such as a computer or a micro-controller. Several components implement the communication interface, using different transports and protocols.

- BGAPI UART DFU: By enabling the BGAPI communication component, the bootloader communication interface implements the UART DFU protocol using BGAPI commands. See _AN1053: Bluetooth® Device Firmware Update over UART for EFR32xG1 and BGM11x Series Products_ for more information about this legacy bootloader.
- Bluetooth:AppLoader: By enabling the Bluetooth AppLoader communication component, the bootloader communication interface implements over-the-air device firmware upgrade functionality using Bluetooth. See [Using the Gecko Bootloader with the Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/) for more information.
- EZSP-SPI: By enabling the EZSP-SPI communication component, the bootloader communication interface implements the EZSP protocol over SPI. This component makes the bootloader compatible with the legacy ezsp-spi-bootloader that was previously released with the EmberZNet wireless stack. See _AN760: Using the Ember Standalone Bootloader_ for more information about legacy Ember standalone bootloaders.
- UART XMODEM: By enabling the UART XMODEM communication component, the bootloader communication interface implements the XMODEM-CRC protocol over UART. This component makes the bootloader compatible with the legacy serial-uart-bootloader that was previously released with the EmberZNet wireless stack. See _AN760: Using the Ember Standalone Bootloader_ for more information about legacy Ember standalone bootloaders.

###### Compression (heading level 7)

The Compression components provide capability for the bootloader GBL file parser to handle compressed GBL upgrade images. Each compression component provides support for one (de)compression algorithm. At the time of writing, decompression of data compressed with the LZ4 and LZMA algorithms is supported, through the _GBL Compression (LZ4)_ and _GBL Compression (LZMA)_ components.

###### Debug (heading level 7)

This component provides the bootloader with support for debugging output. If the component is configured to enable debug prints, short debug messages will be printed over Serial Wire Output (SWO), which can be accessed in multiple ways, including using Simplicity Commander, and by connecting to port 4900 of the Wireless Starter Kit TCP/IP interface.

To turn on debug prints, enable the Debug component and select **Debug prints**. Select **Debug asserts** to enable assertions in the source code.

On Series 1 devices, also select the GPIO peripheral in the Pin Tool.

###### GPIO Activation (heading level 7)

This component provides functionality to enter firmware upgrade mode automatically after reset if a GPIO pin is active during boot. The GPIO pin location and polarity are configurable.

- GPIO: By enabling the GPIO activation component, the firmware upgrade mode can be activated by the push buttons.
- EZSP GPIO: The EZSP communication protocol over SPI can be used together with this component. By enabling the EZSP GPIO component, the firmware upgrade mode can be entered by activating the _nWake_ pin.

###### Security (heading level 7)

Security components provide implementations of cryptographic operations as well as functionality to compute checksums and to read cryptographic keys from manufacturing tokens.

Modules include:

- AES: AES decryption functionality
- CRC16: CRC16 functionality
- CRC32: CRC32 functionality
- ECDSA: ECDSA signature verification functionality
- SHA-256: SHA-256 digest functionality

###### Storage (heading level 7)

These components provide the bootloader with multiple storage options for SoCs. All storage implementations have to provide an API to access image files to be upgraded. This API is based on the concept of dividing the download space into storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Some storage implementations also support a raw storage API to access the underlying storage medium. This can be used by applications to store other data in parts of the storage medium that are not used for storing firmware upgrade images. Implementations include:

- **Internal Flash**: The internal flash storage implementation uses the internal flash of the device for upgrade image storage. Note that this storage area is only a download space and is separate from the portion of internal flash used to hold the active application code.
- **SPI Flash**: Two components are available for SPI Flash storage implementation.  
  1. **SPI Flash Storage**: The SPI flash storage implementation supports a variety of SPI flash parts. The subset of devices supported can be configured in this component in Gecko Bootloader. (The default configuration if no devices are selected is to include drivers for all supported parts.) Including support for multiple devices requires more flash space in the bootloader. The SPI flash storage implementation does not support any write protection functionality. Supported SPI flash parts are shown in Table 1.2.  
  2. **SPI Flash Storage SFDP**: The SPI Flash storage SFDP implementation supports all the SPI flash parts that support SFDP (Serial Flash Description Parameter) Standard from JEDEC. The SPI Flash type is detected automatically by querying the SFDP Parameter table present within the flash memory. All the properties of the SPI Flash are accessed from this parameter table. This component is not configurable since the flash is automatically detected. Any flash that supports the SFDP standard can be used with the Gecko Bootloader. However, performance delays might occur when compared to using the **SPI Flash Storage** component.

> **Note**: Low power devices are recommended for battery-operated applications. Use of the other listed devices will decrease battery life due to higher quiescent current, but this can be mitigated with external shutdown FET circuitry, if desired.

Table Supported Serial Dataflash/EEPROM External Memory Parts

<table>
    <thead>
        <tr>
            <th>Manufacturer Part Number</th>
            <th>Size (kB)</th>
            <th>Quiescent Current (µA Typical)*</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Macronix MX25R8035F (low power)</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>0.007</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25R6435SF (low power)</p>
            </td>
            <td>
                <p>8192</p>
            </td>
            <td>
                <p>0.007</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25R3235F (low power)</p>
            </td>
            <td>
                <p>4096</p>
            </td>
            <td>
                <p>0.007</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Spansion S25FL208K</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>15</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Winbond W25X20BVSNIG (W25X20CVSNJG for high-temperature support)</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Winbond W25Q80BVSNIG (W25Q80BVSNJG for high-temperature support)</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L2006EM1I-12G (MX25L2006EM1R-12G for high-temperature support)</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L4006E</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L8006EM1I-12G (MX25L8006EM1R-12G for high-temperature support)</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L1606E</p>
            </td>
            <td>
                <p>2048</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25U1635E (2V)</p>
            </td>
            <td>
                <p>2048</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Atmel/Adesto AT25DF041A</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>15</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Atmel/Adesto AT25DF081A</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Atmel/Adesto AT25SF041</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P20</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P40</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P80</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P16</p>
            </td>
            <td>
                <p>2048</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ025B</p>
            </td>
            <td>
                <p>32</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ512B</p>
            </td>
            <td>
                <p>64</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ010B</p>
            </td>
            <td>
                <p>126</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ020B</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ040B</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
    </tbody>
</table>

* Quiescent current values are as of December 2017; check the latest part specifications for any changes.

###### Compatibility

1. Silicon Labs recommends building the Gecko Bootloader and the application using the same GSDK. This implies that, if the Gecko Bootloader has been built using GSDK v4.0, it is recommended that the application also be built using GSDK v4.0.
2. Backward compatibility is supported wherein the Gecko Bootloader is built using a previous SDK version and the application is built using a newer SDK version.
3. In general, Silicon Labs does not recommend building the Gecko Bootloader using a newer SDK version with the application built using an older SDK version.

The below table attempts to explain the above-mentioned guidelines:

<table>
    <thead>
        <tr>
            <th>
                <p>SDK version X &lt; SDK version Y</p>
            </th>
            <th>
                <p>Application built using SDK version X</p>
            </th>
            <th>
                <p>Application built using SDK version Y</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Gecko Bootloader built using SDK version X</p>
            </td>
            <td>
                <p>Recommended</p>
            </td>
            <td>
                <p>Compatible</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Gecko Bootloader built using SDK version Y</p>
            </td>
            <td>
                <p>Not recommended</p>
            </td>
            <td>
                <p>Recommended</p>
            </td>
        </tr>
    </tbody>
</table>

##### Gecko Bootloader File Format

The GBL file format is used by the Gecko Bootloader. File formats described in this section are generated by Simplicity Commander commands. For more information, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### File Structures

The GBL file format is composed of several tags that indicate a format of the subsequent data and the length of the entire tag. The format of a tag is as follows:

<table>
    <thead>
        <tr>
            <th>
                <p>Tag ID</p>
            </th>
            <th>
                <p>Tag Length</p>
            </th>
            <th>
                <p>Tag Payload</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>4 bytes</p>
            </td>
            <td>
                <p>4 bytes</p>
            </td>
            <td>
                <p>Variable (according to tag length)</p>
            </td>
        </tr>
    </tbody>
</table>

###### Plaintext Tag Description

<table>
    <thead>
        <tr>
            <th>
                <p>Tag Name</p>
            </th>
            <th>
                <p>ID</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>GBL Header Tag</p>
            </td>
            <td>
                <p>0x03A617EB</p>
            </td>
            <td>
                <p>This must be the first tag in the file. The header tag contains the version number of the GBL file specification, and flags indicating the type of GBL file - whether it is signed or encrypted.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Version Dependency Tag</p>
            </td>
            <td>
                <p>0x76A617EB</p>
            </td>
            <td>
                <p>This optional tag contains encoded version dependencies that the software currently running on the device must satisfy before an upgrade can be attempted. Only available on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Application Info Tag</p>
            </td>
            <td>
                <p>0xF40A0AF4</p>
            </td>
            <td>
                <p>This tag contains information about the application update image that is contained in this GBL file</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL SE Upgrade Tag</p>
            </td>
            <td>
                <p>0x5EA617EB</p>
            </td>
            <td>
                <p>This tag contains a complete encrypted Secure Element update image. Only applicable on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Bootloader Tag</p>
            </td>
            <td>
                <p>0xF50909F5</p>
            </td>
            <td>
                <p>This tag contains a complete bootloader update image.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Program Data Tag</p>
            </td>
            <td>
                <p>0xFE0101FE / 0xFD0303FD</p>
            </td>
            <td>
                <p>This tag contains information about what application data to program at a specific address into the main flash memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Delta Tag</p>
            </td>
            <td>
                <p>0xF80A0AF8UL</p>
            </td>
            <td>
                <p>This tag contains the information about the delta patch that should be used to create the new app.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Program LZ4 Compressed Data Tag</p>
            </td>
            <td>
                <p>0xFD0505FD</p>
            </td>
            <td>
                <p>This tag contains LZ4 compressed information about what application data to program at a specific address into the main flash memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Delta LZ4 Compressed Data Tag</p>
            </td>
            <td>
                <p>0xF80B0BF8UL</p>
            </td>
            <td>
                <p>This tag contains LZ4 compressed information about the delta patch that should be used to create the new app.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Program LZMA Compressed Data Tag</p>
            </td>
            <td>
                <p>0xFD0707FD</p>
            </td>
            <td>
                <p>This tag contains LZMA compressed information about what application data to program at a specific address into the main flash memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Delta LZMA Compressed Data Tag</p>
            </td>
            <td>
                <p>0xF80C0CF8UL</p>
            </td>
            <td>
                <p>This tag contains LZMA compressed information about the delta patch that should be used to create the new app.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Metadata Tag</p>
            </td>
            <td>
                <p>0xF60808F6</p>
            </td>
            <td>
                <p>This tag contains metadata that the bootloader does not parse but can be returned to the application through a callback.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Certificate Tag</p>
            </td>
            <td>
                <p>0xF30B0BF3</p>
            </td>
            <td>
                <p>This tag contains a certificate that will be used to verify the authenticity of the GBL file.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Signature Tag</p>
            </td>
            <td>
                <p>0xF70A0AF7</p>
            </td>
            <td>
                <p>This tag contains the ECDSA-P256 signature of all preceding data in the file.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL End Tag</p>
            </td>
            <td>
                <p>0xFC0404FC</p>
            </td>
            <td>
                <p>This tag indicates the end of the GBL file. It contains a 32-bit CRC for the entire file as an integrity check. The CRC is a non-cryptographic check. This must be the last tag.</p>
            </td>
        </tr>
    </tbody>
</table>

The allowed sequence of GBL tags in a GBL file is shown in the following figure.

![GBL Tag Sequence](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image1.png)

###### Encrypted Tag Descriptions

The encrypted GBL file format is like the unencrypted version. It introduces several new tags.

<table>
    <thead>
        <tr>
            <th>
                <p>Tag Name</p>
            </th>
            <th>
                <p>ID</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>GBL Header Tag</p>
            </td>
            <td>
                <p>0x03A617EB</p>
            </td>
            <td>
                <p>The GBL header is the same as for a plaintext GBL file, but the flag indicating that the GBL file is encrypted must be set.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Encryption Init Header</p>
            </td>
            <td>
                <p>0xFA0606FA</p>
            </td>
            <td>
                <p>This contains information about the image encryption such as the Nonce and the amount of encrypted data.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Encrypted Program Data</p>
            </td>
            <td>
                <p>0xF90707F9</p>
            </td>
            <td>
                <p>This contains an encrypted payload containing a plaintext GBL tag, one of Application Info, Bootloader, Metadata or Program Data. The data is encrypted using AES-CTR-128.</p>
            </td>
        </tr>
    </tbody>
</table>

The allowed sequence of GBL tags in an encrypted GBL file is shown in the following figure.

![Encrypted GBL Tag Sequence](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image2.png)

###### GBL Tag Data Structures and Definitions

**GBL Tag Header**

```C
typedef struct {

uint32_t  tagId;  // Tag ID representing the type of tag (GBL Header Tag, GBL Bootloader Tag, etc.).

uint32_t  length; // Length of the subsequent tag data in bytes.

} GblTagHeader_t;
```

**GBL Header Tag**

```C
typedef struct {

GblTagHeader_t header;  // Tag header.

uint32_t       version; // Version of the GBL file format specification. E.g. 0x03000000.

uint32_t       type;    // Flags indicating whether the GBL file is encrypted and/or signed.

// See definitions below.

} GblHeader_t;
```

```C
// GBL types

#define GBL_TYPE_NONE                 0x00000000UL

#define GBL_TYPE_ENCRYPTION_AESCCM    0x00000001UL

#define GBL_TYPE_SIGNATURE_ECDSA      0x00000100UL
```

**GBL Version Dependency Tag**

```C
typedef struct {

uint8_t  imageType;  // Type of image (application, bootloader, SE)

uint8_t  statement;  // Encoded dependency statement (ex. appVersion > (0).1.2.3)

uint16_t reserved;   // Reserved

uint32_t version;    // The version number used in the statement (ex. (0).1.2.3)

} VersionDependency_t;

// Image types

#define GBL_VERSION_DEPENDENCY_TYPE_APPLICATION             0x01U

#define GBL_VERSION_DEPENDENCY_TYPE_BOOTLOADER              0x02U

#define GBL_VERSION_DEPENDENCY_TYPE_SE                      0x03U

// Operator encoding

#define GBL_VERSION_DEPENDENCY_OPERATOR_MASK                0x0FU

#define GBL_VERSION_DEPENDENCY_OPERATOR_SHIFT               0x00U

#define GBL_VERSION_DEPENDENCY_OPERATOR_TYPE_MASK           0x0EU

#define GBL_VERSION_DEPENDENCY_OPERATOR_NEGATOR_BIT_MASK    0x01U

#define GBL_VERSION_DEPENDENCY_OPERATOR_LT                  0x00U

#define GBL_VERSION_DEPENDENCY_OPERATOR_LEQ                 0x02U

#define GBL_VERSION_DEPENDENCY_OPERATOR_EQ                  0x04U

#define GBL_VERSION_DEPENDENCY_OPERATOR_GEQ                 0x06U

#define GBL_VERSION_DEPENDENCY_OPERATOR_GT                  0x08U

// Connective encoding

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_MASK              0xF0U

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_SHIFT             0x04U

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_TYPE_MASK         0x0EU

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_NEGATOR_BIT_MASK  0x01U

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_AND               0x00U

// SE version mask for ignoring the compatibility byte when comparing versions

#define GBL_VERSION_DEPENDENCY_SE_VERSION_MASK              0x00FFFFFFUL
```

**GBL Application Info Tag**

```C
typedef struct {

GblTagHeader_t    header;  // Tag header.

ApplicationData_t appInfo; // Application information structure. See definition below.

} GblApplication_t;
```

```C
typedef struct ApplicationData {

uint32_t type;           // Bitfield representing the type of application.

// See definitions below for possible values.

uint32_t version;        // Version number for this application (customer-defined).

uint32_t capabilities;   // Bitfield representing the capabilities of this application.

uint8_t  productId[16];  // Unique ID (UUID or GUID) for the product this application is built for.

} ApplicationData_t;
```

```C
// Application types

#define APPLICATION_TYPE_ZIGBEE          (1UL << 0UL)

#define APPLICATION_TYPE_THREAD          (1UL << 1UL)

#define APPLICATION_TYPE_FLEX            (1UL << 2UL)

#define APPLICATION_TYPE_BLUETOOTH       (1UL << 3UL)

#define APPLICATION_TYPE_MCU             (1UL << 4UL)

#define APPLICATION_TYPE_BLUETOOTH_APP   (1UL << 5UL)

#define APPLICATION_TYPE_BOOTLOADER      (1UL << 6UL)

#define APPLICATION_TYPE_ZWAVE           (1UL << 7UL)
```

**GBL SE Upgrade Tag**

```C
typedef struct {

GblTagHeader_t header;   // Tag header.

uint32_t       blobSize; // Size of the SE upgrade data blob.

uint32_t       version;  // Version of the SE image.

uint8_t        data[];   // Array of data containing the SE upgrade blob.

} GblSeUpgrade_t;
```

**GBL Bootloader Tag**

```C
typedef struct {

GblTagHeader_t header;            // Tag header.

uint32_t       bootloaderVersion; // Version number of the bootloader.

uint32_t       address;           // Base address of the bootloader image.

uint8_t        data[];            // Array of data containing the bootloader upgrade image.

} GblBootloader_t;
```

**GBL Program Data Tag**

```C
typedef struct {

GblTagHeader_t header;            // Tag header.

uint32_t       flashStartAddress; // Address at which to start flashing data.

uint8_t        data[];            // Array of data to be flashed

// (compressed data in the LZ4 and LZMA variants of the tag).

} GblProg_t;
```

**GBL Metadata Tag**

```C
typedef struct {

GblTagHeader_t header;     // Tag header.

uint8_t        metadata[]; // Array containing the metadata.

} GblMetadata_t;
```

**GBL Certificate Tag**

```C
typedef struct {

GblTagHeader_t           header;      // Tag header.

ApplicationCertificate_t certificate; // Certificate used to verify the GBL file. See definition below.

} GblCertificateEcdsaP256_t;

typedef struct ApplicationCertificate {

uint8_t  structVersion;     // Version of the certificate structure.

uint8_t  flags[3];          // Reserved flags.

uint8_t  key[64];           // Public key used to verify the GBL file.

uint32_t version;           // Version number of this certificate.

uint8_t  signature[64];     // The signature of the certificate itself (not the GBL file).

} ApplicationCertificate_t;
```

**GBL Signature Tag**

```C
typedef struct {

GblTagHeader_t header; // Tag header.

uint8_t        r[32];  // The r value of the ECDSA signature.

uint8_t        s[32];  // The s value of the ECDSA signature.

} GblSignatureEcdsaP256_t;
```

**GBL End Tag**

```C
typedef struct {

GblTagHeader_t header; // Tag header.

uint32_t       gblCrc; // CRC32 checksum of the entire GBL file.

} GblEnd_t;
```

**GBL Encryption Init Header Tag**

```C
typedef struct {

GblTagHeader_t header;    // Tag header.

uint32_t       msgLen;    // Length of the ciphertext in bytes.

uint8_t        nonce[12]; // Random AES-CTR nonce.

} GblEncryptionInitAesCcm_t;
```

**GBL Encrypted Data Tag**

```C
typedef struct {

GblTagHeader_t header;             // Tag header.

uint8_t        encryptedGblData[]; // Array containing the ciphertext (encrypted GBL data).

// Note that the corresponding plaintext must contain one or

// more complete GBL tags. Put differently: A single plaintext GBL

// tag cannot be split across multiple encrypted tags.

} GblEncryptionData_t;
```

##### Gecko Bootloader Operation - Application Upgrade

This section summarizes Gecko Bootloader operation for updating application firmware, first if the Gecko Bootloader is configured in standalone mode and then if it is configured in application mode. Section [Gecko Bootloader Operation - Bootloader Upgrade](04-gecko-bootloader-operation-bootloader-upgrade#gecko-bootloader-operation-bootloader-upgrade) provides the same information for updating the bootloader firmware.

The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the section "Memory Space for Bootloading" in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

###### Standalone Bootloader Operation

Standalone bootloader operation is illustrated in the following figure:

![Standalone Bootloader Operation](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image3.png)

1. The device reboots into the bootloader.
2. A GBL file containing an application image is transmitted from the host to the device. If image encryption is enabled in the main stage bootloader and the image is encrypted, decryption is performed during the process of receiving and parsing the GBL file.
3. The bootloader applies the application upgrade from the GBL upgrade file on-the-fly. If image authentication is enabled in the main stage bootloader and the GBL file contains a signature, the authenticity of the image is verified before completing the process.
4. The device boots into the application. Application upgrade is complete.

###### Rebooting Into the Bootloader (heading level 7)

The Gecko Bootloader supports multiple mechanisms for triggering the bootloader. If the **GPIO activation** component is installed, the host device can keep this pin low/high (depending on configuration) through reset to make the device enter the bootloader. The bootloader can also be entered through software. The `bootloader_rebootAndInstall` API first signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it will enter firmware upgrade mode instead of booting the existing application.

###### Downloading and Applying a GBL Upgrade File (heading level 7)

When the bootloader enters firmware upgrade mode, it enters a receive loop waiting for data from the host device. The specifics of the receive loop depend on the protocol. Received packets are passed to the image parser, a state machine that parses the data and returns a callback containing any data that should be acted upon. The bootloader core implements this callback and flashes the data to internal flash at the address specified. If GBL file authentication or encryption is enabled, the image parser will enforce this, and abort the image upgrade if the authentication fails.

The bootloader prevents a newly uploaded image from being bootable by holding back parts of the application vector table until the GBL file CRC and GBL signature (if required) have been verified.

###### Booting Into the Application (heading level 7)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If a valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

###### Error Handling (heading level 7)

If the application upgrade is interrupted at any time, the device will be without a working application. The bootloader then resets the device, and re-enters firmware upgrade mode. The host device can easily restart the application upgrade process, to try loading the upgrade image again.

###### Application Bootloader Operation

The following figure illustrates the application bootloader operation both for a single image/single storage slot, and multiple images/ multiple storage slots.

![Application Bootloader Operation: Single Storage Slot](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image4.png)

![Application Bootloader Operation: Multiple Storage Slots](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image5.png)

1. A GBL file is downloaded onto the storage medium of the device (internal flash or external dataflash), as described below, and the presence of an upgrade image is indicated.
2. The device reboots into the bootloader, and the bootloader enters firmware upgrade mode.
3. The bootloader applies the application upgrade from the GBL upgrade file.
4. The device boots into the application. Application upgrade is complete.

###### Downloading and Storing a GBL Upgrade Image File (heading level 7)

To prepare for receiving an upgrade image, the application finds an available storage slot, or erases an existing one using `bootloader_eraseStorageSlot`. If the bootloader only supports a single storage slot, a value of 0 should be used for the slot ID.

The application then receives a GBL file using an applicable protocol, such as Ethernet, USB, Zigbee, OpenThread, or Bluetooth, and stores it in the slot by calling `bootloader_writeStorage`.

When download is complete, the application can optionally verify the integrity of the GBL file by calling `bootloader_verifyImage`. This is also done by the bootloader before applying the image but can be done from the application in order to avoid rebooting into the bootloader if the received image was corrupt.

If multiple storage slots are supported, the application should write a bootload list by calling `bootloader_setImageToBootload`. The list is written to the two bootload info pages as shown in Figure The bootload list is a prioritized list of slots indicating the order the bootloader should use when attempting to perform a firmware upgrade. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader treats the entire download space as a single storage slot.

###### Rebooting and Applying a GBL Upgrade File (heading level 7)

The bootloader can be entered through software. The `bootloader_rebootAndInstall` API signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it enters firmware upgrade mode instead of booting the existing application.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the image stored in each. Once it finds a valid GBL upgrade file, firmware upgrade is attempted from this GBL file. If the upgrade fails, the bootloader moves to the next image in the list. If no images pass verification, the bootloader reboots back into the existing application with a message in the shared memory location in SRAM indicating that no good upgrade images were found.

###### Booting Into the Application (heading level 7)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

##### Gecko Bootloader Operation - Bootloader Upgrade

Bootloader upgrade functionality is provided by the first stage bootloader on Series 1 devices, or the Secure Engine on Series 2 devices. The Secure Engine itself is also upgradable. For more details, see section [Gecko Bootloader Operation - Secure Engine Upgrade](05-gecko-bootloader-operation-secure-engine-upgrade#gecko-bootloader-operation-secure-engine-upgrade). On Series 1 devices, the first stage bootloader is not upgradable.

Requirements for upgrading the main bootloader vary depending on the bootloader configuration:

- Application bootloader with storage: Upgrading the main bootloader requires a single GBL file containing both bootloader and application upgrade images.
- Standalone bootloader with communication interface: Upgrading the bootloader requires two GBL files, one with only the bootloader upgrade image, and one with only the application upgrade image.

Security of the bootloader upgrade process is provided by signing the GBL file. See section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).

The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the “Memory Space for Bootloading” section in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/). For convenience, the figures do not distinguish between SE and VSE.

###### Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)

The process is illustrated in the following figure:

![Standalone Bootloader: Bootloader Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image6.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a bootloader upgrade image is transmitted from the host to the device.
3. The contents of the GBL Bootloader tag are written to the bootloader upgrade location in internal flash, overwriting the existing application.
4. The device reboots into the first stage bootloader / Secure Engine.
5. The first stage bootloader / Secure Engine replaces the main bootloader with the new version found in the bootloader upgrade location.
6. The device boots into the new main bootloader.
7. A GBL file containing only an application image is transmitted from the host to the device.
8. The bootloader applies the application image from the GBL upgrade file on-the-fly.
9. The device boots into the application. Bootloader upgrade is complete.

A bootloader upgrade is started in the same way as an application upgrade.

###### Downloading and Applying a Bootloader GBL Upgrade File (heading level 7)

When the bootloader has entered the receive loop, a GBL upgrade file containing a bootloader upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns bootloader upgrade data in a callback. The bootloader core implements this callback and flashes the data to internal flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file CRC and GBL signature (if required) have been verified.

When a complete bootloader upgrade image is received, the main bootloader signals the first stage bootloader / Secure Engine that it should enter firmware upgrade mode. On Series 1 devices, this is done by writing a command to the shared memory location at the bottom of SRAM, and then performing a software reset. On Series 2 devices, Secure Engine communication is used to signal that bootloader upgrade is ready to be performed.

On Series 1 devices, the first stage bootloader verifies the CRC on the current main bootloader and verifies the CRC of the bootloader upgrade present in the bootloader upgrade location in internal flash.

- If the CRC in the upgrade image location and the CRC in the current main bootloader are both valid, then the upgrade image will be copied over the main bootloader if the version number of the upgrade is higher than the current main bootloader version.
- If the CRC in the upgrade image location is valid and the CRC in the current main bootloader location is not valid, the upgrade image will be copied over the main bootloader regardless of the version. This is because the version of the main bootloader cannot be relied upon if the main bootloader image is corrupt.
- If the CRC in the upgrade location is not valid, the upgrade will not be applied.

On Series 2 devices, the authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See section [Setting a Version Number](07-configuring-the-gecko-bootloader#setting-a-version-number) for more information about versioning bootloader images.

###### Upgrading Bootloaders Without Secure Boot to Bootloaders with Secure Boot (heading level 7)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature, using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. This key can be written by application code running on the device as long as the Lock Bits page is configured to allow flash writes. If the Lock Bits page is locked, it can only be erased by the debugger. Therefore, signing/decryption keys residing in the Lock Bits page cannot be erased from firmware. This means that, for devices in the field, those areas in flash cannot be replaced with new ones. However, the Gecko Bootloader prepared from step 1 can be modified to look for the decryption and signature keys in a different location. Key locations are defined in the bootloader project file `btl_security_tokens.c`.
4. Create a GBL file using the Gecko Bootloader image. The GBL file needs to be signed/unsigned depending on the current configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
5. Upload the GBL file. For more details on the upgrade process, see section [Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)](#bootloader-upgrade-on-bootloaders-with-communication-interface-standalone-bootloaders).

###### Enabling Secure Boot RTSL on Series 2 Devices (heading level 7)

Secure Boot RTSL (Root of Trust and Secure Loader) can be enabled using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - For EFR32xG21, in the **Bootloader Core** component, disable the **Allow use of public key from manufacturing token storage** option. This means that the Gecko Bootloader will never make use of the public key stored in the last page of the main flash  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in the VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more information on installing public keys, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See section [Signing an Application Image for Secure Boot](09-gecko-bootloader-security-features#signing-an-application-image-for-secure-boot) for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2. For more details on how to turn on secure boot on the Secure Engine, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).
6. Create a GBL file using the Gecko Bootloader image from step 4.
7. Create a GBL file using the application from step 5. The GBL file need to be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1.
8. Upload the GBL file containing the Gecko Bootloader image.
9. Upload the GBL file containing the application.

###### Downloading and Applying an Application GBL Upgrade File (heading level 7)

Once the bootloader upgrade is completed, the existing application is rendered invalid, since the bootloader upgrade location overlaps with the application. A GBL upgrade file containing an application upgrade is transmitted to the bootloader. The application upgrade process follows that in section [Standalone Bootloader Operation](03-gecko-bootloader-operation-application-upgrade#standalone-bootloader-operation).

###### Bootloader Upgrade on Application Bootloaders with Storage

The process is illustrated in the following figure.

![Application Bootloader: Bootloader Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image7.png)

1. A single GBL file containing both a bootloader upgrade image and an application image is downloaded onto the storage medium of the device (internal flash or external SPI flash).
2. The device reboots into the main bootloader.
3. The main bootloader parses its upgrade image into internal flash at the bootloader upgrade location. Depending on the application size as well as how the “scratch space” is configured for the bootloader on Series 2 devices, the existing application may be overwritten.
4. The main bootloader verifies the integrity of the upgrade image and then resets the device with reset reason BOOTLOADER_RESET_REASON_UPGRADE to apply the upgrade.
5. The device reboots into the first stage bootloader / Secure Engine.
6. The first stage bootloader / Secure Engine replaces the main bootloader with the new version.
7. The device boots into the new main bootloader.
8. The bootloader applies the application image from the GBL upgrade file.
9. The device boots into the application. Bootloader upgrade is complete.

A bootloader upgrade is started in the same way as an Application Upgrade. A single GBL file containing both a bootloader and an application upgrade is written to storage by the application, and the bootloader is entered.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the GBL file stored within. Verification returns information about whether the GBL file contains an application, or both a bootloader and an application. The image parser parses the file. If the GBL file contains a bootloader, the bootloader upgrade data is returned in a callback. The bootloader core implements this callback and flashes the data to internal flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file CRC and GBL signature (if required) have been verified.

On Series 1 devices, the main bootloader signals the first stage bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performing a software reset. On Series 2 devices, Secure Engine communication interface is used to signal the Secure Engine that a bootloader upgrade is ready to be performed.

On Series 1 devices, the first stage bootloader verifies the CRC of the bootloader upgrade present in the bootloader upgrade location in internal flash and copies the bootloader upgrade over the main bootloader if the version number of the upgrade is higher than the version number of the existing main bootloader. On Series 2 devices, the authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See section [Setting a Version Number](07-configuring-the-gecko-bootloader#setting-a-version-number) for more information about versioning bootloader images.

The new main bootloader is entered, and the images in the list of storage slots marked for bootload are verified. When the image parser parses the slot containing the GBL file with the bootloader + application upgrade, the version number of the bootloader upgrade is equal to the running main bootloader version, so another bootloader upgrade will not be performed. Instead, the application upgrade data are returned in a callback. Bootloading of the new application proceeds as described in section [Application Bootloader Operation](03-gecko-bootloader-operation-application-upgrade#application-bootloader-operation).

###### Storage Space Size Configuration (heading level 7)

The storage space size must be configured to have enough space to store the upgrade images. Depending on the configuration, the bootloader size can vary. For size requirements of the bootloader, see section [Size Requirements for Different Bootloader Configurations for Series 1 Devices](07-configuring-the-gecko-bootloader#size-requirements-for-different-bootloader-configurations-for-series-1-devices).

###### Upgrading Bootloaders without Secure Boot to Bootloaders with Secure Boot (heading level 7)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature. The procedure is as follows:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. This key can be written by application code running on the device as long as the Lock Bits page is configured to allow flash writes. If the Lock Bits page is locked, it can only be erased by the debugger. Therefore, signing/decryption keys residing in the Lock Bits page cannot be erased from firmware. This means that, for devices in the field, those areas in flash cannot be replaced with new ones. However, the Gecko Bootloader prepared from step 1 can be modified to look for the decryption and signature keys in a different location. Key locations are defined in the bootloader project file `btl_security_tokens.c`.
4. Prepare a signed application image using the private key generated in step 2. See section [Signing an Application Image for Secure Boot](09-gecko-bootloader-security-features#signing-an-application-image-for-secure-boot) for more information on signing an application.
5. Create a GBL file using the Gecko Bootloader image and the signed application image. The GBL file needs to be signed/unsigned depending on the configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
6. Upload the GBL file. For more details on the upgrade process, see section [Bootloader Upgrade on Application Bootloaders with Storage](#bootloader-upgrade-on-application-bootloaders-with-storage).

###### Enabling Secure Boot RTSL on Series 2 Devices (heading level 7)

Secure Boot RTSL can be enabled by using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.  
   - For EFR32xG21, in the **Bootloader Core** component, disable the **Allow use of public key from manufacturing token storage** option. This means that the Gecko Bootloader will never make use of the public key stored in the last page of the main flash.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more information on installing public keys, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/). For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See section [Signing an Application Image for Secure Boot](09-gecko-bootloader-security-features#signing-an-application-image-for-secure-boot) for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2. For more details on how to turn on secure boot on the Secure Engine, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).
6. Create a GBL file using the Gecko Bootloader image from step 4 and the application from step 5. The GBL file must be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1. For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
7. Upload the GBL file containing the Gecko Bootloader image and the application.

##### Gecko Bootloader Operation - Secure Engine Upgrade

The Secure Engine is upgradable and requirements for upgrading the Secure Engine vary depending on the bootloader configuration:

- **Application bootloader with storage**: Upgrading the Secure Engine requires a single GBL file containing both Secure Engine and application upgrade images.
- **Standalone bootloader with communication interface**: Upgrading the Secure Engine requires two GBL files, one with only the Secure Engine upgrade image, and one with only the application upgrade image and optionally a third image containing only the Main bootloader upgrade.

A bootloader upgrade can also be included in the same GBL file in application mode, or as a third GBL file in standalone mode. The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the section “Memory Space for Bootloading” in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

Signed and encrypted Secure Engine upgrade images are provided by Silicon Labs through Simplicity Studio. Upgrade images with the same or lower version number than the running Secure Engine will be ignored.

To download Secure Engine firmware images, connect a Series 2 device and select a preferred SDK. The Secure Firmware **Update to x.x.x** link appears in the Launcher Perspective, as shown in the following figure.

![Launcher Perspective](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image8.jpg)

Click **Update to x.x.x** next to Secure FW: x.x.x. A warning dialog box appears. Click **[Yes]** to continue.

![Warning dialog box when click Update to x.x.x](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image9.jpg)

The Launcher Perspective is then updated so that the current Secure Firmware version and link version are the same.

![Launcher Perspective after clicking Update to x.x.x](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image10.jpg)

The Secure Engine firmware images can be found in the _util/se_release/public_ directory under the Gecko SDK. Simplicity Studio displays the SE firmware version available in the Gecko SDK selected.

###### Secure Engine Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)

The process is illustrated in the following figure.

![Standalone Bootloader: Secure Engine Bootloader Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image11.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a Secure Engine upgrade image is transmitted from the host to the device.
3. The contents of the GBL Secure Engine tag are written to the pre-configured upgrade location in internal flash, overwriting the existing application.
4. The device reboots into the Secure Engine.
5. The Secure Engine is replaced by the new version found in the pre-configured upgrade location.
6. The device boots into the main bootloader.
7. A GBL file containing only an application image is transmitted from the host to the device.
8. The bootloader applies the application image from the GBL upgrade on the fly.
9. The device boots into the application. Secure Engine upgrade is complete.

###### Downloading and Applying a Secure Engine GBL Upgrade File (heading level 7)

When the bootloader has entered the receive loop, a GBL upgrade file containing a Secure Engine upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns Secure Engine upgrade data in a callback. The bootloader core implements this callback and flashes the data to internal flash at the pre-configured bootloader upgrade location.

When a complete Secure Engine upgrade image is received, the main bootloader signals the Secure Engine that it should enter firmware upgrade mode. This is done by the Secure Engine communication interface that is used to signal that bootloader upgrade is ready to be performed.

###### Downloading and Applying an Application GBL Upgrade File (heading level 7)

Once the Secure Engine upgrade is completed, the existing application is rendered invalid if the Secure Engine upgrade location overlaps with the application. A GBL upgrade file containing an application upgrade is transmitted to the bootloader. The application upgrade process follows that. For more information, see section [Standalone Bootloader Operation](03-gecko-bootloader-operation-application-upgrade#standalone-bootloader-operation).

###### Secure Engine Upgrade on Application Bootloaders with Storage

The process is illustrated in the following figure.

![Application Bootloader: Secure Engine Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image12.png)

1. A single GBL file containing both a Secure Engine upgrade image and an application image is downloaded onto the storage medium of the device (internal flash or external SPI flash).
2. The device reboots into the bootloader.
3. a) The main bootloader copies its upgrade image into internal flash at the pre-configured upgrade location.  
   b) Alternatively, if the no-staging Secure Engine upgrade option has been enabled, the upgrade image will be fetched directly from the GBL file in storage instead of first copying the image to the pre-configured upgrade location.
4. The device reboots into the Secure Engine.
5. The Secure Engine is replaced by the new version found in the pre-configured upgrade location (or directly from storage, ref. 3b).
6. The device boots into the main bootloader.
7. The bootloader applies the application image from the GBL upgrade file.
8. The device boots into the application. Secure Engine upgrade is complete.

###### Storage Space Size Configuration (heading level 7)

The storage space size must be configured to have enough space to store the upgrade images. The following table shows the reserved SE upgrade image sizes.

<table>
    <thead>
        <tr>
            <th>
                <p>Device Family</p>
            </th>
            <th>
                <p>Reserved Flash for SE Upgrade Image</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>EFR32xG21</p>
            </td>
            <td>
                <p>48 kB</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EFR32xG22</p>
            </td>
            <td>
                <p>24 kB</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EFR32xG23</p>
            </td>
            <td>
                <p>96 kB</p>
            </td>
        </tr>
    </tbody>
</table>

Depending on the configuration, the bootloader size can vary. For size requirements of the bootloader, see section [Size Requirements for Different Bootloader Configurations for Series 1 Devices](07-configuring-the-gecko-bootloader#size-requirements-for-different-bootloader-configurations-for-series-1-devices). The bootloader size for EFR32xG21 devices can be up to 16 kB and for EFR32xG22, EFR32xG23, and EFR32xG24 devices the bootloader size can be up to 24 kB. For more details, see [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

##### Getting Started with the Gecko Bootloader

This section describes how to build a Gecko Bootloader from one of the provided examples. Simplicity Studio 5, used with Gecko SDK Suite (GSDK) v3.x and higher, differs from Simplicity Studio 4, used with GSDK v2.x, in how sample applications are selected and how projects are created. Refer to the documentation provided with your SDK for details. These instructions assume that you have installed Simplicity Studio 5, the GSDK and associated utilities as described in the SDK’s quick start guide, and that you are familiar with generating, compiling, and flashing an example application in the relevant version.

- [Bluetooth Getting Started Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-getting-started-overview/)
- [Proprietary Flex SDK v3.x Quick-Start Guide](https://docs.silabs.com/connect-stack/latest/proprietary-flex-sdk-v3x-quick-start-guide/)
- [Silicon Labs OpenThread SDK Quick-Start Guide](https://docs.silabs.com/openthread/latest/openthread-quick-start-guide/)
- [Zigbee EmberZNet Quick-Start Guide for SDK 7.0 and Higher](https://docs.silabs.com/zigbee/latest/zigbee-7x-quick-start-guide/)

1. Create a project based on the Gecko Bootloader example of your choice. The project opens with a tab describing the example.  
   ![Project based on the Gecko Bootloader example](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image13.png)
2. Click the project (*.slcp) tab to move to the Project Configurator interface.  
   ![Project Configurator interface](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image14.png)
3. The Software Components tab shows the list of available components that can be installed in the project.  
   ![Software Components tab](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image15.png)
4. The **Storage Slot Setup** component allows you to configure storage slots to be used if a storage component is also installed. The default configuration matches the target part and bootloader type. This component supports a maximum of three storage slots.  
   ![Storage Slot Setup](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image16.png)
5. Click the **Build** (hammer) icon.
6. After the build is complete, the bootloader binaries are available in the **artifact** folder as depicted in the image below.  
   ![Bootloader binaries files in the artifact folder](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image17.png)

On Series 1 devices, three bootloader images are generated into the build directory: a main bootloader, a main bootloader with CRC32 checksum, and a combined first stage and main bootloader with CRC32 checksum. The main bootloader image is called **<projectname>.s37**, the main bootloader with CRC32 checksum is called **<projectname>-crc.s37**, while the combined first stage image + main bootloader image with a CRC32 checksum is called **<projectname>-combined.s37**. The first time a device is programmed, whether during development or manufacturing, the combined image needs to be programmed. For subsequent programming, when a first stage bootloader is already present on the device, it is okay to download an image containing just the main bootloader. In this case, the main bootloader with CRC32 should be used.

The requirement is that any main bootloader image that is programmed via serial wire must contain the CRC32 in the image. Files downloaded via serial wire are “s37” files. Most often, the **<projectname>-combined.s37** file is the one downloaded during production programming. However, it is possible to download only the main bootloader over serial wire, in which case **<projectname>-crc.s37** should be used.

Any main bootloader that is upgraded with the OTA or host method should already contain CRC32 because bootloader-initiated upgrades use GBL files (not “s37” files) and Simplicity Commander adds the CRC32 when it constructs the GBL file. The input files to Simplicity Commander can (and should) use the non-CRC “s37” file.

On Series 2 devices, the combined image is not present, since the first stage bootloader does not exist. The image containing only a main bootloader is the image that must be used to create a GBL file for bootloader upgrade.

##### Configuring the Gecko Bootloader

###### Configuring Storage

Gecko Bootloaders configured as application bootloaders must include an API to store and access image files. This API is based on the concept of storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Slots are configured in the **Bootloader Storage Slot Setup** component.

When multiple storage slots are configured, a bootload list is used to indicate the order in which the bootloader should access slots to find upgrade images. If multiple storage slots are supported, the application should write the bootload list by calling bootloader_setImageToBootload before rebooting into the bootloader to initiate a firmware upgrade process. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader uses this slot implicitly. A maximum of three slots may be configured in the **Bootloader Storage Slot Setup** component.

###### SPI Flash Storage Configuration (heading level 7)

When configuring a Gecko Bootloader to obtain images from SPI flash, modify the following.

The **base address of the storage area** should be configured in the **Common Storage** component. This is the address at which the bootloader places the bootload list, if more than one storage slot is configured. In the default configuration, this address is set to 0. If only a single storage slot is configured, the bootload list is not used, so configuring it may be omitted.

The **location and size of the storage slots** can be configured using the **Bootloader Storage Slot Setup** component (supports a maximum of three configurable storage slots). The addresses input here are absolute addresses (they are not offsets from the base address). If more than a single slot is configured, space must be reserved between the base address as configured in the **Common Storage** component and the first storage slot configured in the **Bootloader Storage Slot Setup** component. Enough space to fit two copies of the bootload list must be reserved. These two copies need to reside on different flash pages, to provide redundancy in case of power loss during writing. Two full flash pages therefore need to be reserved. In the default example application, a SPI flash part with 4 kB flash sectors is used. This means that 8 kB must be reserved before the first storage slot. The following figure illustrates how the storage area can be partitioned, where the numbers in the top row represent the starting addresses.

![SPI Flash Storage Area Configuration](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image18.png)

###### Internal Storage Configuration (heading level 7)

When configuring a Gecko Bootloader to obtain images from internal flash, modify the following.

The **base address of the storage area** should be configured in the **Common Storage** component. This is the address at which the bootloader will place the prioritized list of storage slots to attempt to bootload from, if more than one storage slot is configured. In the default configuration, only a single storage slot is configured, so this value is set to 0, and isn’t used. If more than one storage slot is configured, this value needs to be configured too.

The **location and size of the storage slots** can be configured using the **Bootloader Storage Slot Setup** Component (supports a maximum of three configurable storage slots). The addresses input here are absolute addresses (they are not offsets from the base address). If more than a single slot is configured, enough space must be reserved between the base address as configured in the **Common Storage** component and the first storage slot configured in the **Bootloader Storage Slot Setup** component. Enough space to fit two copies of the bootload list must be reserved. These two copies need to reside on different flash pages, to provide redundancy in case of power loss during writing. Two full flash pages therefore need to be reserved. The following figure illustrates how the storage area can be partitioned.

![Internal Storage Area Configurations](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image19.png)

> **Note**: The storage area partitioning in the example for two storage slots above does not take any NVM system into account. If using an NVM system like SimEE or PS Store, take care to place and size the storage area in such a way that bootloader storage does not overlap with NVM.

###### Compressed Upgrade Images

The Gecko Bootloader optionally supports compressed GBL files. In a compressed GBL file, only the application upgrade data is compressed, any metadata and bootloader upgrade data (if present) stay uncompressed. This means that a compressed GBL file is identical to a normal (uncompressed) GBL file, except that the GBL Programming Tag containing the application upgrade image (as described in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/)) has been replaced by a GBL LZ4 Compressed Programming Tag or GBL LZMA Compressed Programming Tag. Signature and encryption operations on a compressed GBL work identically to on an uncompressed GBL.

To be able to use compressed upgrade images, a decompressor for the relevant compression algorithm must be added to the Gecko bootloader. The following table shows which compression algorithms are supported by the Gecko Bootloader, and which Bootloader component should be added to enable the feature. The table also shows how much space the decompressor takes up in the bootloader, and how big of a size reduction to expect for the compressed application upgrade image. Be aware of the bootloader size requirement. The bootloader space might be too small to fit the decompressors, depending on the device and enabled components.

<table>
    <thead>
        <tr>
            <th>
                <p>Compression Algorithm</p>
            </th>
            <th>
                <p>Component</p>
            </th>
            <th>
                <p>Bootloader Size Requirement</p>
            </th>
            <th>
                <p>Application Upgrade Size Reduction (typical)</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>LZ4</p>
            </td>
            <td>
                <p>GBL Compression (LZ4)</p>
            </td>
            <td>
                <p>&lt; 1 kB</p>
            </td>
            <td>
                <p>~ 10%</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>LZMA</p>
            </td>
            <td>
                <p>Bootloader Compression (LZMA)</p>
            </td>
            <td>
                <p>~5 kB flash, 18 kB RAM</p>
            </td>
            <td>
                <p>~ 30%</p>
            </td>
        </tr>
    </tbody>
</table>

It is important to note that the compressed GBL file stays compressed while being transferred to the device, and while it is stored in the upgrade area. It is decompressed by the bootloader when the upgrade is applied. This means that the running application in main flash will be identical to one that was installed using an uncompressed (normal) GBL file.

Compressed GBL files can only be decompressed by the bootloader when running standalone, not through the Application Interface. This means that upgrade image verification performed by the application prior to reboot will not attempt to decompress the application upgrade, it will only verify the signature of the compressed payload. After rebooting into the bootloader, it will decompress the image as part of the upgrade process.

> **Note**: The above means that Bluetooth in-place application upgrades cannot be compressed, as they are processed by the Bluetooth Supervisor or AppLoader using functionality in the bootloader through the Application Interface. Supervisor/stack and AppLoader updates can be compressed, but the user application cannot.

###### LZMA Compression Settings (heading level 7)

LZMA decompression is only supported for images compressed with certain compression settings. Simplicity Commander automatically uses these settings when using the `commander gbl create --compress lzma` command.

- Probability model counters: lp + lc <= 2. Simplicity Commander uses lp=1, lc=1.
- Dictionary size no greater than 8 kB. Simplicity Commander uses 8 kB.

Together, these settings cause the decompressor to require 18 kB of RAM for decompression – 10 kB for the counters and 8 kB for the dictionary.

The GBL LZMA Compressed Programming Tag contains a full LZMA file, containing the LZMA header, raw stream, and end mark. The Gecko bootloader only supports decompressing payloads that contain the end mark as the last 8 bytes of the compressed stream.

###### Bootloader Example Configurations

The following sections describe the key configuration options for the example bootloader applications.

> **Note**: Security features are disabled for all example configurations. In development, Silicon Labs strongly recommends enabling security features to prevent unauthorized parties from uploading untrusted program code. See section [Using Application Image Security Features](09-gecko-bootloader-security-features#using-application-image-security-features) to learn how to configure the security features of the Gecko Bootloader.

###### UART XMODEM Bootloader (heading level 7)

Standalone bootloader for EFM32 and EFR32 devices running the EmberZNet PRO and Silicon Labs Connect protocol stacks, using XMODEM-CRC over UART.

In this configuration, the **UART XMODEM** communication component, **XMODEM Parser** component, and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The **GPIO activation** component is also installed by default, allowing bootloader entry into firmware upgrade mode by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### BGAPI UART DFU Bootloader (heading level 7)

Standalone bootloader for the Bluetooth protocol stack, using the BGAPI protocol for UART DFU. This bootloader should be used for all NCP-mode Bluetooth applications.

In this configuration, the **BGAPI UART DFU** communication component and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The GPIO activation component is also installed by default, allowing bootloader entry by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### EZSP SPI Bootloader (heading level 7)

Standalone bootloader for EmberZNet PRO and Silicon Labs Connect protocol stacks using EZSP for SPI.

In this configuration, the **EZSP-SPI** communication component, **XMODEM Parser** component, and **Bootloader SPI Peripheral Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for SPI and EZSP signaling need to be configured in the **Bootloader SPI Peripheral Driver** and **EZSP-SPI** components, respectively.

The **EZSP GPIO activation** component is also installed by default, allowing bootloader entry into firmware upgrade mode by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### Bluetooth AppLoader OTA DFU Bootloader (heading level 7)

Standalone bootloader for the Bluetooth protocol stack, using Bluetooth for Over-The-Air DFU.

In this configuration, the **Bluetooth AppLoader** communication component is installed.

###### SPI Flash Storage Bootloader (heading level 7)

Application bootloader for all wireless protocol stacks, using an external SPI flash to store upgrade images received over the air by the application.

In this configuration, the **SPI Flash Storage** and **Common Storage** components, as well as the **Bootloader SPI Controller Driver** component, are installed. For the example application to run on a custom board, the GPIO ports and pins used for SPI communication with the external flash need to be configured in the **Bootloader SPI Controller Driver** component, and the type of SPI flash needs to be configured in the **SPI Flash Storage** component. The base address of the storage area can be configured in the **Common Storage** component. The location and size of the storage slots themselves can be configured using the **Bootloader Storage Slot Setup** component (supports up to three configurable storage slots).

The SPI Flash storage bootloader provides customizable callback functions, which can be found in _bootloader-callback-stubs.c_. The callback functions _storage_customInit_ and _storage_customShutdown_, for example, can be used for custom hardware setups. Those callback functions can be interfaced from the applications using the bootloader interface functions such as _bootloader_init_ and _bootloader_deinit_ from _api/btl_interface.h_.

Currently, Silicon Labs supports the following SPI Flash storage bootloaders:

1. SPI Flash storage bootloader (multiple images)
2. SPI Flash storage bootloader (single image)
3. SPI Flash storage bootloader (single image with slot size of 1MB). **Note: This bootloader should only be used for systems with an external SPI Flash size >= 1 MB**.

###### SPI Flash Storage Bootloader SFDP (heading level 7)

Application bootloader for all wireless protocol stacks, using an external SPI flash to store upgrade images received over the air by the application.

In this configuration, the **SPI Flash Storage SFDP** and **Common Storage** components, as well as the **Bootloader SPI Controller Driver** component, are installed. For the example application to run on a custom board, the GPIO ports and pins used for SPI communication with the external flash need to be configured in the **Bootloader SPI Controller Driver** component. The type of SPI flash is detected at runtime. The base address of the storage area can be configured in the **Common Storage** component. The location and size of the storage slots themselves can be configured using the **Bootloader Storage Slot Setup** component (supports up to three configurable storage slots).

The SPI Flash storage bootloader SFDP provides customizable callback functions, which can be found in _bootloader-callback-stubs.c_. The callback functions _storage_customInit_ and _storage_customShutdown_, for example, can be used for custom hardware setups. Those callback functions can be interfaced from the applications using the bootloader interface functions such as _bootloader_init_ and _bootloader_deinit_ from _api/btl_interface.h_.

###### Internal Storage Bootloader (heading level 7)

Application bootloader for all wireless protocol stacks, using internal flash to store upgrade images received over the air by the application.

Multiple examples are provided, including configurations for 512 kB flash memory devices like EFR32xG13, 1024 kB flash memory devices like EFR32xG12, and 2048 kB flash memory devices like EFM32GG11. **The storage layout should be modified before running the bootloader on any other devices**. In this configuration, the internal flash and common storage components are installed. The base address of the storage area is configured in the **Common Storage** component. The location and size of the storage slots can be configured using the **Bootloader Storage Slot Setup** component (provides up to three configurable storage slots). Default example applications are provided with configurations for both single storage slot and multiple storage slots.

The default storage slot configurations provided by the Gecko Bootloader **must** be configured to match the use-case-specific application configurations.

**Table**: Internal Storage Bootloader Default Storage Configurations

<table>
    <thead>
        <tr>
            <th>
                <p>Sample Applications</p>
            </th>
            <th>
                <p>Storage Offset</p>
            </th>
            <th>
                <p>Storage Size</p>
            </th>
            <th>
                <p>Additional Notes</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 256 kB device)</p>
            </td>
            <td>
                <p>0x21800 (137216)</p>
            </td>
            <td>
                <p>88064</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8021800 (134354944)</p>
            </td>
            <td>
                <p>88064</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 352 kB device)</p>
            </td>
            <td>
                <p>0x28000 (163840)</p>
            </td>
            <td>
                <p>147456</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8028000 (134381568)</p>
            </td>
            <td>
                <p>147456</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 512 kB device)</p>
            </td>
            <td>
                <p>0x44000 (278528)</p>
            </td>
            <td>
                <p>196608</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8044000 (134496256)</p>
            </td>
            <td>
                <p>196608</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 1 MB device)</p>
            </td>
            <td>
                <p>0x84000 (540672)</p>
            </td>
            <td>
                <p>458752</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8084000 (134758400)</p>
            </td>
            <td>
                <p>458752</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 2 MB device)</p>
            </td>
            <td>
                <p>0x10000 (1048576)</p>
            </td>
            <td>
                <p>1011712</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8100000 (135266304)</p>
            </td>
            <td>
                <p>1011712</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (multiple images on 1 MB device)</p>
            </td>
            <td>
                <p>0x5A000 (368640)</p>
            </td>
            <td>
                <p>337920</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0xAC800 (706560)</p>
            </td>
            <td>
                <p>337920</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 1536kB device)</p>
            </td>
            <td>
                <p>0xC0000 (786432)</p>
            </td>
            <td>
                <p>737280</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x80C0000 (135004160)</p>
            </td>
            <td>
                <p>737280</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 1920kB device)</p>
            </td>
            <td>
                <p>0x80E8000 (135168000)</p>
            </td>
            <td>
                <p>966656</p>
            </td>
            <td>
                <p>This example application is available for device families with flash size of 1920kB or higher (for example xG25 device family)</p>
            </td>
        </tr>
    </tbody>
</table>

###### Image Acquisition Application Example Configuration

These examples illustrate applications that acquire and store a GBL upload image for an application bootloader. For the running bootloader to accept an application upgrade, the new application version must be higher than the existing version. The version number can be set in Appbuilder by defining the macro “APP_PROPERTIES_VERSION” in the **Additional Macros** field on the **Other** tab.

###### Setting a Version Number

To distinguish between different builds of the Gecko Bootloader, it is useful to set a version number. To perform a bootloader upgrade, not only must the running bootloader pass its integrity checks (see section [Downloading and Applying a Bootloader GBL Upgrade File](04-gecko-bootloader-operation-bootloader-upgrade#downloading-and-applying-a-bootloader-gbl-upgrade-file)), but the bootloader upgrade image must also have a higher version number than the running bootloader image. A version number can be set using Simplicity Studio by configuring the **Bootloader Version Main Customer** option of the **Bootloader Core** component. This macro will be picked up by the config file **btl_config.h**, where it is combined with the version number of the Gecko Bootloader files provided by Silicon Labs.

###### Placing Bootloader in Main Flash

For device families xG13 and xG14, the entire main stage bootloader might not fit into the bootloader flash if the user installs some extra components. In such scenarios, the main stage bootloader can be placed in the main flash by installing the Bootloader in Main Flash core component. This component internally provides a MACRO named MAIN_BOOTLOADER_IN_MAIN_FLASH which is used to set the appropriate address required to place the main bootloader in main flash. The MACRO is used to generate the linker file from the common linker template with the appropriate addresses to place the main stage bootloader in the main flash.

###### Hardware Configuration

The Gecko Bootloader uses the Pin Tool for configuration of pinout and other hardware-related settings. When Pin Tool configuration is available for a bootloader component, the relevant settings are shown in the Component Editor for that component.

![Example of USART Configuration for UART Driver](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image20.png)

The standalone Pin Tool User Interface can also be used to configure settings for Gecko Bootloader if desired.

While the Pin Tool provides configuration for many different peripherals, the Gecko Bootloader uses only the following Pin Tool modules:

- SERIAL is used by the UART Driver component to configure baud rate, flow control mode and pinout.
- VCOM is used by the UART Driver component to enable the serial interface if necessary (only on Silicon Labs Wireless Starter Kits).
- EXTFLASH is used by the SPI Driver to configure frequency and pinout.
- SPINCP is used by the SPI Slave Driver to configure pinout.
- BTL_BUTTON is used by the GPIO Activation component.
- CMU HFXO frequency setting is used by the delay driver to calibrate timing if the core is running from the HFXO.

Other settings, like CMU oscillator configuration or DCDC configuration, are not taken into consideration by the default bootloader code. If using these configuration settings is desired, the required code must be added in btl_main.c.

> **Note**: While the delay driver uses the HFXO frequency setting from Pin Tool, the HFXO enable setting is not used to initialize the HFXO on startup. This setting is only used when calling the bootloader through the Application Interface (see section [Gecko Bootloader and TrustZone](10-gecko-bootloader-and-trustzone#gecko-bootloader-and-trustzone)), and the application has switched to the HFXO prior to calling the Bootloader Application Interface API.

###### Size Requirements for Different Bootloader Configurations for Series 1 Devices

Enabling different configuration options for the Gecko Bootloader changes the size of the resulting image. The following table shows a list of example bootloader configurations and the resulting approximate size of the main bootloader. Note that any size above 14 kB will be too large to fit in the bootloader area of flash of EFR32xG13, and that any size above 16 kB will be too large to fit in the bootloader area of flash on EFR32xG14 and EFM32TG11. This table was last updated for Gecko SDK Suite 4.0 (Gecko Bootloader 2.0), and no guarantees are made that a configuration of a specific size with one SDK version will maintain that size in future releases.

**Table**: Bootloader Size Requirements

<table>
    <thead>
        <tr>
            <th>
                <p>Base Configuration</p>
            </th>
            <th>
                <p>Enabled Options</p>
            </th>
            <th>
                <p>Size (kB)</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>XMODEM UART</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.7</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>17.9</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal storage, single slot</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>11.5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>11.5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>12.4</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>16.6</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal storage, multiple slots</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>17.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SPI flash, single slot</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.6</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.6</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>17.7</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SPI flash, multiple slots</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>14</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>18</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SPI flash using SFDP, single slot</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>18</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>BGAPI UART</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>11.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>11.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>12.7</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>16.9</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EZSP SPI</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.9</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>18.1</p>
            </td>
        </tr>
    </tbody>
</table>

###### EM4 GPIO Retention for OTA Upgrades

The EM4 GPIO Retention feature allows Series 2 devices to retain GPIO pin states during Over-The-Air (OTA) firmware upgrades by entering EM4 sleep mode instead of performing a full system reset. This is particularly useful for applications that must preserve GPIO states, such as LED indicators, relay outputs, or control signals throughout the upgrade process.

Normally, an OTA upgrade triggers a system reset that clears all GPIO configurations and output states. EM4 GPIO Retention avoids this by saving the GPIO configuration in Backup RAM (BURAM), which remains powered through EM4 sleep and wake cycles. When the device wakes, the GPIO configuration and output levels are automatically restored, ensuring uninterrupted operation during the upgrade.

When an OTA upgrade with GPIO retention is initiated, the bootloader performs the following sequence:

- Saves GPIO configurations to **BURAM**, which retains data during EM4 sleep.
- Configures **EM4 GPIO retention mode** to `SWUNLATCH`.
- Sets up the **Backup Real-Time Counter (BURTC)** for the wake event.
- Enters **EM4 sleep mode** instead of issuing a system reset.
- On wakeup, validates BURAM contents and restores GPIO states.
- Continues with the OTA process according to the reset reason stored in BURAM.

To protect against repeated boot failures, the bootloader uses a reset counter stored in BURAM. The counter increments whenever the device cannot find or validate a valid application image. After three failed wakeups, the system halts in a controlled infinite loop, requiring user intervention (e.g., a manual reset or power cycle) to recover.

The reason for boot failure is stored in BURAM using one of the following codes:

- `BADAPP`: Invalid application
- `BADIMAGE`: Invalid or missing upgrade image
- `FATAL`: Other unrecoverable error

###### Enabling and Usage of EM4 GPIO Retention (heading level 7)

To use the EM4 GPIO Retention during OTA upgrades, complete the following two steps:

###### Step-1: Install the EM4 GPIO Retention Compoenent (heading level 8)

Install the following component in the application via Simplicity Studio Configurator.

Component: **BTL_EM4_GPIO_RETENTION**

Path: **Platform → Bootloader → EM4 GPIO Retention**

This component enables the EM4 GPIO retention capability in the bootloader, to manage save and restore the GPIO states during OTA updates.

###### Step-2: Call the API from Application (heading level 8)

After the OTA image has been received and stored, `bootloader_rebootAndInstallWithGpioRetention()` API must be called in the application.

This API saves the current GPIO configurations to BURAM and instructs the bootloader to perform OTA upgrade using EM4 sleep instead of a system reset. GPIO settings are defined with the `gpio_em4_retention_t` structure, which specifies the port, pin number, and output state. A maximum of 16 GPIO pins can be retained as mentioned in `MAX_EM4_RETAINED_PINS`.

For detailed API usage, parameter descriptions, and return values, refer to the README file located at `<Simplicity SDK>/platform/bootloader/em4-gpio-retention/`

###### Limitations and Considerations (heading level 7)

**Upgrade Type Support**

- GPIO retention is supported only for **application-level upgrades**.
- Upgrades involving the Secure Engine (SE) or the Bootloader are not supported because they involve multiple reset cycles that clear GPIO states.

**GPIO Configuration Limits**

- Maximum of **16 GPIO pins** can be retained.
- Supported ports: **A, B, C, and D** (ports 0–3).
- Pins are restored as **push-pull outputs**.
- Only **output states** are retained; input states are not preserved.

**Power Requirements**

- BURAM retains data only while the device remains powered.
- If power is lost during EM4, BURAM contents and GPIO states will be cleared.
- Continuous power must be maintained throughout the OTA process to ensure successful restoration of GPIO states.

##### Simplicity Commander and the Gecko Bootloader

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple CLI (Command Line Interface that is also scriptable. You can use Simplicity Commander to perform these essential tasks:

- Generating key files for signing and encryption
- Signing application images for Secure Boot
- Creating GBL images (encrypted or unencrypted, signed, or unsigned)
- Parsing GBL images

Simplicity Commander is used throughout the examples in the following sections. For more information on executing the commands to complete these tasks, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

> **Note**: Simplicity Commander also offers a GUI (Graphical User Interface) that can be used in the lab for typical tasks such as flashing device images. The functions described in this User Guide are performed from the CLI.

###### Creating GBL Files Using Simplicity Commander

To create an unsigned GBL file from an application **myapp.s37**, execute `commander gbl create myapp.gbl --app myapp.s37`.

To create an unsigned GBL file from a main bootloader upgrade **mybootloader.s37**, execute `commander gbl create mybootloader.gbl --bootloader mybootloader.s37`. This file can be used with the standalone bootloader configurations of the Gecko Bootloader.

To create an unsigned GBL file from a Secure Engine, upgrade **mySecureElement.seu**, and execute `commander gbl create mySecureElement.gbl --seupgrade mySecureElement.seu`. The Secure Engine images, .seu, are provided by Silicon Labs and  can be found through Simplicity Studio. See section [Gecko Bootloader Operation - Secure Engine Upgrade](05-gecko-bootloader-operation-secure-engine-upgrade#gecko-bootloader-operation-secure-engine-upgrade).

These commands can also be combined to create a single upgrade image, suitable for use with application bootloader configurations of the Gecko Bootloader: `commander gbl create myupgrade.gbl --app myapp.s37 --bootloader mybootloader.s37 --seupgrade mySecureElement.seu`.

##### Gecko Bootloader Security Features

###### About Bootloader Image Security

Secure Boot and Secure Firmware Upgrade, discussed in the following sections, enable Gecko Bootloader to provide authenticity and integrity checks on the Application image, which provides a sufficient level of security for many applications. However, in systems without a hardware root of trust, no process checks the authenticity or integrity of the Gecko Bootloader itself. Its security is provided solely by the device hardware and the robustness of the software running on the device.

The native behavior of Firmware Upgrade will prevent accidental version rollback of Gecko Bootloader under normal usage conditions. However, without a hardware root of trust, intentional downgrade attacks may be feasible. If a higher level of security assurance is required by the application, using a Series 2 device with hardware root of trust and anti-rollback protection is recommended. For more information, refer to [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

###### About Application Image Security

The Gecko Bootloader can enforce security on two levels:

- Secure Boot refers to the verification of the authenticity of the application image in main flash on every boot of the device.
- Secure Firmware Upgrade refers to the verification of the authenticity of an upgrade image before performing a bootload, and optionally enforcing that upgrade images are encrypted.

###### Secure Boot Procedure (heading level 7)

When Secure Boot is enabled, the cryptographic signature of the application image in flash is verified on every boot before the application is allowed to run. Secure Boot is not enabled by default in the example configurations provided by Silicon Labs, but enabling it is highly recommended to ensure the validity and integrity of firmware images.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA (elliptical curve digital signature algorithm) of the SHA-256 digest of the application firmware image, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

1. On boot, the bootloader checks the application image for information about whether it is signed.
2. The type of signature and signature location is determined.
3. If the type of signature does not match the requirements of the bootloader, the bootloader enters device firmware upgrade mode and prevents the application from running.
4. According to the chosen signature algorithm, the signature of the contents of flash from the beginning of the application to the location of the signature is compared to the signature at the signature location.
5. If the signatures do not match, the bootloader enters device firmware upgrade mode and prevents the application from running.

**Secure Boot using ECDSA-P256-SHA256**

For an image to be signed for Secure Boot, the application needs to contain a copy of the **ApplicationProperties_t** struct. This struct contains information about which signature algorithm is used, and where to find the signature.

On every boot, the bootloader calculates the SHA-256 digest of the application image, from the beginning of the application to the start of the signature. The signature of the SHA-256 digest is then verified using ECDSA-P256.

If the signature is valid, the application is allowed to boot. Else, the bootloader is entered, and an application upgrade is attempted if one is available.

The public key used for signature verification is stored as a manufacturing token on Series 1 and EFR32xG22 devices. OnEFR32xG21 devices, the public key can either be stored as a manufacturing token or stored in the Secure Engine One-time Programmable memory (OTP). Simplicity Commander can be used to generate a key pair and write the public key to the device. See [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more information.

**Secure Boot with Application Rollback Protection**

On every boot, the application version in the **ApplicationData_t** struct is stored at the end of the bootloader area in flash, which is used to prevent applications from being downgraded. The application version can remain the same for upgrades. The bootloader will only allow applications to increment its version 6 times by default. The bootloader can be upgraded after that to reset the stored application versions and to allow application upgrades again. The allowed number of upgrades can be increased by modifying linkerfiles to reserve an extra 4 bytes for each version and by increasing SL_GBL_APPLICATION_VERSION_STORAGE_CAPACITY from _btl_bootload.c_. **For Series 2 devices, this option is not applicable on devices with Secure Engine configured to perform full page lock**. If the bootloader area in flash is locked by Secure Engine, the bootloader will not be able to store the application versions in flash, and it would continue without performing that function.

When the application upgrade version check option is enabled in the **Bootloader Core** component, the bootloader checks where App properties points into flash. If app properties struct is present, then it will check compatibility of the application properties struct and check if the upgrade version is greater than the installed app; otherwise, it will check if product ID is correct before applying the upgrade image.

If app properties struct is absent at the app properties location, it is assumed that the previous upgrade was interrupted, and allows the upgrade to continue.

If application rollback prevention component is installed in the bootloader project, then before applying the upgrade image, the bootloader will check the application version in the application properties structure that resides inside the signed/encrypted GBL file and will only apply the OTA image to application area if the application version in ApplicationData structure is equal or higher than the highest application version last seen.

The application rollback prevention feature can be enabled in the **Bootloader Core** component by selecting the **Enable application rollback protection** option. The **Minimum application version allowed** option can be used to configure the minimum application version that should be allowed to boot.

The application versions are stored in the bootloader area in flash. To properly protect the stored application versions, it is recommended to lock the bootloader flash by selecting the **Prevent bootloader write/erase** option in the **Bootloader Core** component.

**Secure Boot Using a Certificate**

On Series 2 devices, a certificate-based secure boot operation is supported. The Certificate contains:

- Struct version: The version of the certificate structure.
- Public key: ECDSA-P256 public key, X and Y coordinates concatenated, used to validate the image.
- Certificate version: The version of the running certificate.
- Signature: ECDSA-P256 signature, used for the authentication of the public key and the certificate version.

The definition of the certificate struct can be found in api/application_properties.h.

To utilize certificate-based secure boot, configure Secure Engine to authenticate the bootloader image by configuring the certificate-based secure boot option in the Secure Engine OTP. Configure the Gecko Bootloader to enable certificate-based secure boot in the **Bootloader Core** component by selecting the **Enable certificate support** option. The Gecko Bootloader certificate must be signed by the private key pair of the public key stored in the Secure Engine OTP. For more information on the key storage, see section [Key Storage](#key-storage).

The certificate-based secure boot procedure is illustrated in the following figure.

![Certificate-Based Secure Boot Procedure](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image21.jpg)

Once the certificate-based secure boot option on Secure Engine is turned on, Secure Engine verifies the Gecko Bootloader certificate. The public key stored in the certificate is used to validate the signature of the Gecko Bootloader. Secure Engine will not accept bootloader images without a certificate.

If only the secure boot option is enabled (not certificate-based) on Secure Engine, and Secure Engine identifies a certificate, the certificate will be used to validate the bootloader image. If the certificate version from the bootloader image is higher than 0 and it gets verified once, Secure Engine will never again accept direct signed bootloader images without a certificate.

The Gecko Bootloader will authenticate the direct signed application using the public key stored in the Gecko Bootloader certificate. If the application contains a certificate, Gecko Bootloader will authenticate it. The procedure is illustrated in the following figure.

![Advanced Certificate-Based Secure Boot Procedure](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image22.jpg)

After authentication of the application certificate, Gecko Bootloader verifies the signature of the application using the public key from the application certificate. In addition, Gecko Bootloader compares the Gecko Bootloader certificate version against the application certificate version. All application images with a certificate version lower than the certificate version of the Gecko Bootloader will be rejected. Gecko Bootloader can be configured to only allow applications with certificate to boot by configuring the **Bootloader Core** component by selecting the **Reject direct signed images** option.

The **ApplicationProperties_t** struct contains the certificate struct **ApplicationCertificate_t**. The certificate struct can be injected to images that contain an **ApplicationProperties_t** with **ApplicationCertificate_t**. To inject a certificate to an image, issue the following command from Simplicity Commander:

`commander convert <image file> --secureboot --keyfile <signing key> --certificate <certificate>--outfile <signed image file with certificate>`

###### Secure Firmware Upgrade (heading level 7)

The Gecko Bootloader supports a secure firmware upgrade process. This is achieved by using symmetric encryption to encrypt the upgrade image, and asymmetric cryptography to sign the upgrade image. Symmetric encryption provides confidentiality and asymmetric cryptography provides integrity and authenticity. Note that encryption alone is not enough to provide authenticity.

**Encryption Algorithms**

The Gecko Bootloader supports the AES-CTR-128 encryption algorithm. The GBL upgrade file is encrypted using 128-bit AES in Counter mode with a random nonce as the initial counter value. Through configuration, the GBL file’s decryption duration can be improved by increasing the counter's block size. The block size is configurable with options 1, 2, 4, or 8 blocks. The configuration is available as part of the AES CTR Stream Block Config component.

The AES-128 key used for decryption, more commonly called the OTA decryption key, is stored as a manufacturing token on Series 1 and EFR32xG22 devices. On EFR32xG21 devices, the OTA decryption key can either be stored as a manufacturing token or stored in the Secure Engine OTP. To make use of the OTA decryption key stored in the Secure Engine OTP, the **Use symmetric key stored in Secure Engine storage** option in the **Bootloader Core** component must be selected. Simplicity Commander can be used to generate an OTA decryption key and write the key to the device. See [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more information. For more information on storing the OTA decryption key on Series 2 devices, see [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/).

The Secure Engine OTP key support depends on the SE Manager component, which is enabled by default.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA signature of the SHA-256 digest of the GBL upgrade file, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

Before starting a firmware upgrade process, the application can verify an image in storage by calling into the bootloader verification functions. For bootloaders with Communication Interface, the host device should verify the image before sending it to the NCP or RCP.

During firmware upgrade, the GBL file is parsed, and if encrypted, decrypted on-the-fly. A GBL Signature Tag in the GBL file indicates to the bootloader that the file is signed, and the signature is verified. If signature verification fails, the firmware upgrade process is aborted.

On Series 2 devices, Gecko Bootloader will authenticate the GBL signature tag using the public key stored in the bootloader certificate if the **Enable certificate support** option is selected in the **Bootloader Core** component. A GBL Certificate tag in the GBL file indicates to the bootloader that the GBL certificate tag needs to be authenticated using the public key stored in the bootloader certificate. The certificate version in the GBL certificate tag is compared with the bootloader certificate and only a version equal or higher than the bootloader certificate is accepted. Once the GBL certificate tag is authenticated, the GBL file's signature is verified using the authenticated public key from the GBL certificate tag. On EFRxG21 devices, the GBL certificate tag can also be signed by the private key pair of the public key stored in the Secure Engine OTP.

###### Using Application Image Security Features

This example assumes that a bootloader called **bootloader-uart-xmodem** has been built in Simplicity Studio. For a Series 1 device, three files of interest have been generated in the output directory:

- **bootloader-uart-xmodem.s37** – This file contains the main bootloader. Can be used for bootloader upgrade.
- **bootloader-uart-xmodem-crc.s37** - This file contains the main bootloader with CRC32 checksum.
- **bootloader-uart-xmodem-combined.s37** – This file contains the first stage and main bootloader with a CRC32 checksum in a single image. Can be used for manufacturing and initial deployment of the bootloader.

The relevant version can be flashed to the EFR32 using the Flash Programmer in Simplicity Studio or using Simplicity Commander. For Series 2 devices, only the main bootloader binary is generated.

This example provides two ways of signing the upgrade images. The first option uses Simplicity Commander to generate key material and sign data. This is suitable for development. The second option uses an external signer, such as a dedicated Hardware Security Module (HSM) to protect private key material and perform signing operations. Silicon Labs recommends using an HSM to safeguard private keys.

###### Generating Keys (heading level 7)

To use the security features of the Gecko Bootloader, encryption and signing keys need to be generated. These keys must then be written to the EFR32 device. The encryption key is used with the GBL file for secure firmware upgrade. The signing keys are used both with the GBL file for secure firmware upgrade and to sign the application image for Secure Boot.

**Generating a Signing Key Using Simplicity Commander**

`commander util genkey --type ecc-p256 --privkey signing-key --pubkey signing-key.pub --tokenfile signing-key-tokens.txt`

This creates an ECDSA-P256 key pair for signing; **signing-key** contains the private key in PEM format and **must be kept secret from third parties**. This key will later be used to sign images and GBL files. **signing-key.pub** contains the public key in PEM format and can be used to verify GBL files using commander gbl parse. **signing-key-tokens.txt** contains the public key in token format, suitable for writing to the EFR32 device.

**Generating a Signing Key Using a Hardware Security Module**

When using a Hardware Security Module, the private key is kept secret inside the HSM. According to the instructions from your HSM vendor, have it generate an ECDSA-P256 key pair and export the public key in PEM format to the file **signing-key.pub**. Then use Simplicity Commander to convert the key to token format, suitable for writing to the EFR32 device.

`commander gbl keyconvert --type ecc-p256 signing-key.pub --outfile signing-key-tokens.txt`

**Generating an Encryption Key**

`commander util genkey --type aes-ccm --outfile encryption-key`

This creates an AES-128 key for encryption in the file **encryption-key**. The file has token format, making it suitable to write to the EFR32 device using `commander flash --tokenfile`.

**Writing Keys to the Device**

To write the two token files containing the encryption key and public key as manufacturing tokens to the device, issue the following command:

`commander flash --tokengroup znet --tokenfile encryption-key --tokenfile signing-key-tokens.txt`

###### Signing an Application Image for Secure Boot (heading level 7)

If the bootloader enforces Secure Boot, the application needs to be signed to pass verification. On every boot, a SHA-256 digest of the application is calculated. The signature is verified using ECDSA-P256, with the same public key as for the GBL file signing. Signature verification failure prevents the application from booting.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see section [Application Properties](12-application-interface#application-properties).

**Using Simplicity Commander**

Signing the application can be done with the command:

`commander convert myapp.s37 --secureboot --keyfile signing-key --outfile myapp-signed.s37`

**Using a Hardware Security Module**

The application can be prepared for signing by issuing the command:

`commander convert myapp.s37 --secureboot --extsign --outfile myapp-for-signing.s37`

###### Creating a Signed and Encrypted GBL Upgrade Image File from an Application (heading level 7)

To create a GBL file from an application, use `commander gbl create`.

Note that, as of this writing, secure application images can only be constructed through Simplicity Commander, not through the configuration options available through Simplicity Studio.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see section [Application Properties](12-application-interface#application-properties).

**Using Simplicity Commander to Sign**

For an application called **myapp.s37**, use:

`commander gbl create myapp.gbl --app myapp.s37 --sign signing-key --encrypt  encryption-key`

This single command performs three actions:

- Creates a GBL file
- Encrypts the GBL file
- Signs the GBL file

If Secure Boot is also desired, the application must be signed using `commander convert --secureboot` prior to creating the GBL.

**Using a Hardware Security Module to Sign**

For an application called **myapp-signed.s37**, which has previously been signed for Secure Boot, use:

`commander gbl create myapp-for-signing.gbl --app myapp-signed.s37 --extsign --encrypt  encryption-key`

This command performs the following actions:

- Creates a partial GBL file
- Encrypts the partial GBL file
- Prepares the partial GBL file for signing by an external signer

Using an HSM, sign the output file **myapp-for-signing.gbl.extsign**, and supply the resulting DER-formatted signature file **signature.der** back to Simplicity Commander:

`commander gbl sign myapp-for-signing.gbl.extsign --signature signature.der --verify signing-key.pub --outfile myapp.gbl`

The GBL file is not valid until the signature has been applied using gbl sign.

###### System Security Considerations

The Gecko bootloader security features can be used to create a secure device, but do not create a secure system by themselves. This section goes over considerations that need to be taken when designing a secure system where the Gecko Bootloader is a component.

###### Key Storage (heading level 7)

On Series 1 devices, the decryption and public sign keys used by the Gecko bootloader are stored in the Lockbits page in flash. To prevent a rogue application from being able to change or wipe the keys, the Lockbits page should be write protected after the keys have been written in manufacturing.

On Series 2 devices, the decryption key and the sign key used by the Gecko Bootloader can either be stored in the topmost page of the main flash or in the Secure Engine OTP. The decryption key can be provisioned in the Secure Engine OTP using Simplicity Commander or using the Secure Engine Mailbox interface. The keys are not accessible from the user applications on EFR32xG22 devices, which means that the keys used by Gecko Bootloader need to be stored in the topmost page of the main flash. Once a key value has been programmed into the Secure Engine OTP, it cannot be changed. For more details, refer to [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) and [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

The default behavior of the Gecko Bootloader is to use the sign key stored in the Secure Engine OTP to perform the signature verification. If the sign key is not provisioned, the Gecko Bootloader will try to use the public sign key stored in the topmost page of the main flash. This fallback mechanism can be disabled by disabling the “Allow use of public key from manufacturing token storage” component option from the **Bootloader Core** component in Simplicity Studio.

###### Write-Protecting the Bootloader (heading level 7)

By default, the region in flash used by the Gecko bootloader is readable and writeable. The region needs to stay readable for the Application Interface to be able to interact with the bootloader. Immediately after reset, the region also needs to be writable to be able to perform bootloader upgrades.

###### Series 1 (heading level 8)

It is possible to write-protect the bootloader region on EFR32xG12 and newer. This is done by setting the write-once MSC_BOOTLOADERCTRL_BLWDIS bit on every bootup on Series 1 devices. The pages are write-protected until the next reboot. This is done by the Gecko bootloader main stage if the “Prevent bootloader write/erase” component option is enabled in the **Bootloader Core** component in Simplicity Studio.

On EFR32xG1, where the bootloader resides in main flash rather than the information block, the BLWDIS option does not exist. On EFR32xG1, the first flash page containing the first stage bootloader can be write-protected with a Page Lock word, using commander `device protect --write --range 0x0:+0x800`. If bootloader upgrades are to be supported, the pages containing the main bootloader need to stay writeable.

> **Note**: Setting MSC_BOOTLOADERCTRL_BLWDIS will also prevent debuggers from flashing a new bootloader. This means that debug tools that do not completely halt and reset the target device before re-flashing might fail to flash the new bootloader, as the flash is write-protected. If you are unsure whether your debug tools will handle this gracefully, Silicon Labs recommends keeping this setting disabled during development, and enabling it before going into production. If your debug tools halt and reset the target device before flashing, this is not an issue, and Silicon Labs recommends enabling this setting early in the development cycle.

###### Series 2 (heading level 8)

On Series 2 devices, the write-once MSC_PAGELOCKx register is used to write-protect the pages used by the bootloader if the “Prevent bootloader write/erase” component option is enabled in the **Bootloader Core** component in Simplicity Studio. The pages are write-protected until the next reboot.

###### Write-Protecting the Application (heading level 7)

On Series 2 devices, it is also possible to write-protect the application. When the component option “Prevent write/erase of verified application” is enabled, the bootloader will write-protect the pages used by the application after successfully verifying the application signature, before allowing the application to start. This option is only available when Secure Boot of the application is enabled. The MSC_PAGELOCKx register is used to protect the pages, and the write protection lasts until the next reboot.

###### Debug Access (heading level 7)

###### Series 1 (heading level 8)

To prevent debugger access to the Series 1 devices, the Debug Lock word needs to be written. Device recovery after enabling the Debug Lock is possible but will erase the main flash and the Lockbits page. This will erase the main application and the key material stored in the Lockbits page. The Userdata page and bootloader area will survive Debug Unlock, so secrets should not be stored in these locations. To debug lock the device, issue `commander device lock --debug enable`. The AAP Lock can be used to permanently lock the debug port. This also prevents Debug Unlock. To AAP lock the device, please see the reference manual for your device for the address location of the AAP lock word, and use `commander flash --patch` to write the appropriate value to this address.

###### Series 2 (heading level 8)

On Series 2 devices, debugger access can be prevented through Secure Engine. Debugger access can be re-enabled after enabling the Debug Lock by issuing device erase. To debug-unlock the device, issue commander device lock --debug disable from Simplicity Commander. This also erases the main flash, which results in the top page of main flash that stores the encryption and signing keys being erased. To permanently lock the debug port, the device erase disable command can first be issued through Secure Engine. Thereafter, the debug lock command can be issued to the Secure Engine. For more details, refer to [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

###### Disabling Debug Access from Software (heading level 8)

The software APIs `DBG_DisableDebugAccess(dbgLockModeAllowErase)` and `DBG_DisableDebugAccess (dbgLockModePermanent)` from the EMLIB DBG module can be used from the application to lock the debug interface.

##### Gecko Bootloader and TrustZone

With GSDK v4.2.2, Gecko Bootloader comes with TrustZone support to build TrustZone aware solutions. This section outlines the major points that should be considered when using a TrustZone aware bootloader.

###### Gecko Bootloader Operation

A TrustZone aware application can have the following configurations:

- Secure app only
- Non-secure app only
- Secure and Non-secure pair

With TrustZone enabled, the application bootloaders are entirely configured as Secure applications whereas the communication bootloaders are split into Secure and Non-secure application pairs. The communication interfaces are typically in the Non-secure part of the application and the GBL parser, and other functionalities are in the Secure part of the application. TrustZone aware applications are generated and built using pre-defined workspace applications. Refer to [Series 2 TrustZone](https://docs.silabs.com/mcu-bootloader/latest/series2-trustzone/) and [Software Project Generation and Configuration with SLC-CLI](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-slc-cli/) for more details regarding TrustZone workspaces and the SLC CLI tool.

For the communication bootloaders to function properly, a combined bootloader binary image (containing both the Secure and Non-secure binary images) needs to be programmed onto the device. A combined bootloader binary can be obtained by either using the post-build steps defined for the workspace or using the Commander tool. Refer to [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more details on how to use the Commander tool to combine multiple binaries into a single binary. Application bootloaders need to be built with the **Bootloader TrustZone Secure** component when building a TrustZone aware solution. The **Bootloader TrustZone Secure** component is required to set up the necessary configuration for the application to function correctly within a TrustZone aware solution.

To create a bootloader upgrade file, the combined bootloader binary (Secure and Non-secure) should be used. Refer to [Series 2 TrustZone](https://docs.silabs.com/mcu-bootloader/latest/series2-trustzone/) for more details on upgrading an existing application to TrustZone. Special care must be taken while building the TrustZone aware communication bootloaders for the xG21 family as the bootloader size increases from 16kB (non TrustZone aware solution) to 24kB (TrustZone aware solution). Similarly, the Bootloader – SoC Bluetooth Apploader OTA DFU application’s size increases from 72kB to 80kB with TrustZone enabled.

###### Gecko Bootloader Configuration

The following table provides three of the configuration options available as part of the Bootloader Interface with TrustZone enabled.

<table>
    <thead>
        <tr>
            <th>
                <p>Configuration Option</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>BOOTLOADER_DISABLE_OLD_BOOTLOADER_MITIGATION</p>
            </td>
            <td>
                <p>Disables multi-tiered fallback logic. The fault handling logic as well as the USART auto-detection logic will be disabled. Default value is set to 0.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>BOOTLOADER_DISABLE_NVM3_FAULT_HANDLING</p>
            </td>
            <td>
                <p>Disables peripheral access fault handling. The fault handling triggered by an erroneous access of peripherals will be disabled. This should be disabled if all the peripherals that are in use by the bootloader have been properly configured by the Manually override security state of peripherals option. Default value is set to 0.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>BOOTLOADER_MANUAL_OVERRIDE_SECURITY_STATE</p>
            </td>
            <td>
                <p>Manually override the security state of peripherals in use by the bootloader. This option can be used to manually set a peripheral's access state before calling into the bootloader. Default value is set to 0.</p>
            </td>
        </tr>
    </tbody>
</table>

##### Gecko Bootloader and Delta DFU Upgrades

With GSDK v2024.6.1, Gecko Bootloader support comes with support for delta DFU upgrades. This section provides an introduction to Delta DFU upgrades and describes the major points that should be considered while using the Delta DFU component.

###### Introduction to Delta DFU

The main function of the image delta DFU is to calculate the difference between the current firmware stored on the device and the new firmware to be updated. This difference is used to create a patch file that can be applied to the current firmware, resulting in the new firmware. The patch file is created using the Simplicity Commander tool, transferred to the device with any wireless protocol as a GBL, and applied on top of the current firmware by the Gecko Bootloader. The patch file creation and application are both implemented in a library that is shared between these tools.

The following diagram illustrates the complete process.

![Delta DFU process: patch creation, transfer, and firmware update](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image23.png)

###### Gecko Bootloader Operation

The Delta DFU upgrades can be enabled by including the Delta DFU component in the Gecko Bootloader. Simplicity Commander supports the creation of a Delta DFU GBL file.

With Delta DFU enabled, the application bootloaders are equipped to accept Delta DFU GBL files. These GBL files contain a patch file that is extracted into the slot. The Gecko Bootloader creates the new firmware using this patch file and the currently running firmware within the slot. The slot size should have enough number of pages to hold the GBL file, patch file, and the new firmware binary in the slot. Each file starts on a new page.

The Delta DFU upgrades are triggered in the same way as in an application bootloader. Once the bootloader finds a GBL that contains Delta Patch, it extracts the patch file and then re-constructs the new firmware file within the slot. If the new firmware is created correctly, then the bootloader copies this new firmware to the application area, completing the upgrade.

To create the GBL file, Commander needs two input files, one of the firmware that is current and one that is the upgrade. For Delta DFU upgrades to work, it is essential that the firmware on the device and the firmware used to create the GBL are the same. Also, the version dependency tag is included in Delta DFU and should be correctly set by the user.

Delta DFU operation is illustrated in the following figure:

![Delta DFU flow: patch extraction, firmware reconstruction, and upgrad](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image24.png)

##### Application Interface

The bootloader has an application interface exposed through a function table in the bootloader. The application interface provides APIs to use bootloader functions for storing and retrieving upgrade images and verifying their integrity. APIs to reboot into the bootloader are also provided. For details see the Gecko Bootloader API Reference, shipped with the SDK in the platform/bootloader/documentation folder.

If you are not using a protocol stack from Silicon Labs, the **api/btl_interface.h** header provides the bootloader application interface API. If you are using a protocol stack from Silicon Labs, the recommended bootloader interface API for the specific protocol stack should be used instead. The following files provide the implementation of the bootloader interface:

**api/btl_interface.c** (common interface)

**api/btl_interface_storage.c** (interface to storage functionality)

The application interface consists of functions that can be included into the customer application, and that communicate with the bootloader through the **MainBootloaderTable_t**. This table contains function pointers into the bootloader. The 10th word of the bootloader contains a pointer to this structure, allowing any application to easily locate it. Using the wrapper functions provided in the Bootloader Interface API is preferred over accessing the bootloader table directly. Modules include:

- **Application Parser Interface**: Application interface for interfacing with the bootloader image parser.
- **Application Storage Interface**: Application interface for interfacing with the bootloader storage. The Storage Interface is only available on bootloaders that support the storage interface.
- **Common Application Interface**: Generic application interface available on all versions of the bootloader, independently of which components are present.

###### Application Properties

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. Simplicity Commander extracts the metadata contained in this structure from the application and places it in the GBL upgrade file **GBL Application Tag**. If the structure is not present in the application, Simplicity Commander will raise an error. The **ApplicationProperties_t** struct is added to the application on installing the **bootloader_interface** component to the application. The **bootloader_interface** component installs **bootloader_app_properties** component which adds an instance of **ApplicationProperties_t** named **sl_app_properties** to the project. The component adds a source file named **app_properties.c** and a configuration file named **app_properties_config.h**. This configuration file allows users to configure the application version via Simplicity Studio’s Component Editor. To open the Component Editor, locate the **App Properties** component under **Platform > Bootloader** as shown below.

![App Properties component location under Platform > Bootloader menu](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image25.png)

Click **Configure** to open the Component Editor.

![Component Editor interface](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image26.png)

The application type is automatically populated based on the wireless stack used in building the project. The value of the application type is automatically set during the project generation step and can be found in **autogen/sl_application_type.h** file.

The contents of the **GBL Application Tag** can be extracted from a GBL file by a running application using the Application Storage interface. Note that the **GBL Application Tag** will only be added if the GBL file contains an application image, not if the GBL file only contains a bootloader upgrade or metadata.

The structure in the application is also used to declare whether the application image is signed, and what type of signature is used. This information is added by Simplicity Commander when signing the image using `commander convert (--secureboot, --extsign or -- signature)`. For the bootloader to locate the **ApplicationProperties_t** struct, if not already done by the linker, Simplicity Commander modifies word 13 of the application to insert a pointer to the **ApplicationProperties_t** struct when signing the application image for Secure Boot.

###### Error Codes

Most Gecko bootloader APIs return error codes. The following table lists the groups of error codes that may be returned. The full list of error codes within each group can be found in _api/btl_errorcode.h_ in the platform/bootloader directory of the SDK, as well as in the API Reference.

<table>
    <thead>
        <tr>
            <th>
                <p>ID</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0x0</p>
            </td>
            <td>
                <p>OK</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x01xx</p>
            </td>
            <td>
                <p>Initialization error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x02xx</p>
            </td>
            <td>
                <p>Image verification error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x04xx</p>
            </td>
            <td>
                <p>Storage error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x05xx</p>
            </td>
            <td>
                <p>Bootload error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x06xx</p>
            </td>
            <td>
                <p>Security error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x07xx</p>
            </td>
            <td>
                <p>Communication error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x09xx</p>
            </td>
            <td>
                <p>XMODEM parser error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x10xx</p>
            </td>
            <td>
                <p>GBL file parser error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x11xx</p>
            </td>
            <td>
                <p>SPI slave driver error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x12xx</p>
            </td>
            <td>
                <p>UART driver error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x13xx</p>
            </td>
            <td>
                <p>Compression error</p>
            </td>
        </tr>
    </tbody>
</table>

#### Using the Gecko Bootloader with Silicon Labs Bluetooth Applications

##### Using the Gecko Bootloader with Silicon Labs Bluetooth Applications

> **Note: This section replaces _AN1086: Using the Gecko Bootloader with Silicon Labs Bluetooth Applications_. Further updates to this application note will be provided here**.

This application note includes detailed information on using the Silicon Labs Gecko Bootloader with Silicon Labs Bluetooth applications for Gecko SDK (GSDK) 4.1.0 and higher or Simplicity SDK (SiSDK) 2024.6.0 and higher. If you are not familiar with the basic principles of performing a firmware upgrade or want more information about upgrading image files, refer to [Bootloader Fundamentals](https://docs.silabs.com/bootloader/latest/bootloader-fundamentals/).

###### Key Points

- Gecko Bootloader overview
- Using Gecko Bootloader for BGAPI UART DFU
- Using Gecko Bootloader for Bluetooth OTA upgrade
- Using Gecko Bootloader to update firmware from the user application
- Delta DFU
- Post-Build Editor

##### Overview

The Silicon Labs Gecko Bootloader is a common bootloader for all the newer MCUs and wireless MCUs from Silicon Labs. The Gecko Bootloader can be configured to perform a variety of bootloader functions, from device initialization to firmware upgrades. The Gecko Bootloader uses a proprietary format for its upgrade images, called GBL (Gecko Bootloader). Currently two formats are actively supported, GBL3 (or just GBL) for Series 2 or older and GBL4 for Series 3. These images are produced with the file extension “.gbl”. Additional information on the GBL file format is provided in [Bootloader Fundamentals](https://docs.silabs.com/bootloader/latest/bootloader-fundamentals/).

The Gecko Bootloader has a two-stage design, where a minimal first stage bootloader is used to upgrade the main bootloader. The first stage bootloader only contains functionality to read from and write to fixed addresses in internal flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to a fixed location in flash and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader firmware upgrade image, by computing a CRC32 checksum before copying the upgrade image to the main bootloader location.

The Gecko Bootloader can be configured to perform firmware upgrades in standalone mode (also called a standalone bootloader) or in application mode (also called an application bootloader), depending on the software component configuration. Software components can be enabled and configured through the Simplicity Studio IDE.

This document describes how to configure and use the Gecko Bootloader for device firmware upgrades [over UART](02-bgapi-uart-device-firmware-upgrade-dfu), and for OTA (over-the-air) upgrades [using Bluetooth](03-bluetooth-ota-upgrade).

The Gecko Bootloader does not come bundled into the application example projects (although some precompiled demos do contain it). Therefore, you must compile and load the bootloader separately from the application image.

##### BGAPI UART Device Firmware Upgrade (DFU)

This is the firmware upgrade used in Network Co-Processor (NCP) Bluetooth applications. For more information on NCP applications, see [Using the Silicon Labs Bluetooth Stack v3.x and Higher in Network Co-Processor Mode](https://docs.silabs.com/bluetooth/latest/bluetooth-network-coprocessor-mode/).

In the BGAPI UART DFU implementation a GBL image containing the new firmware is written to target device using UART as the physical interface.

###### UART DFU Options

The target device must be programmed with the Gecko Bootloader sample project **Bootloader - NCP** **BGAPI UART DFU**. Gecko Bootloader is configured automatically for the selected radio board. The BGAPI UART DFU bootloader is a standalone bootloader, so no storage area needs to be configured. During UART DFU upgrade the bootloader writes the new firmware image directly on top of the old firmware image and therefore no temporary download area is needed.

###### GPIO Settings (heading level 7)

The default settings are suitable for testing with a WSTK (Wireless Starter Kit). These settings can be easily changed by through the Software Components tab. Select the Bootloader UART Driver component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

Flow control settings of the radio board and the WSTK must match. The WSTKs flow control can be configured through the admin console. More information on the admin console can be found in the user guide for the respective development kit. To configure the flow control through the admin console:

- In Simplicity Studios Debug Adapters view, right click on the connected device.
- Select Launch Console.
- In the Admin tab, type _serial vcom config handshake disable/enable_, depending on if you want to disable or enable flow control.

![The bootloaders UART software component](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image1.png)

![The bootloaders UART configuration](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image2.png)

###### UART DFU Process

The basic steps involved in the UART DFU, using NCP, are as follows:

1. Boot the target device into DFU mode by calling the bootloader API `bootloader_rebootAndInstall()`. In NCP-mode, this can be achieved by calling `sl_bt_user_reset_to_dfu()`. When using Series 1 devices, reset into DFU is achieved with `sl_bt_system_reset(1)`. Alternatively, if you have GPIO activation enabled in the bootloader, press the bootloader activation pin while the device is reset.
2. Wait for the `sl_bt_evt_dfu_boot` event.
3. Send the command `sl_bt_dfu_flash_set_address(address)` to start the firmware upgrade.
4. Send the entire contents of the GBL upgrade image with `sl_bt_dfu_flash_upload(data)`.
5. After sending all data, the host sends the command `sl_bt_dfu_flash_upload_finish()`.
6. To finalize the upgrade, the host resets the target device into normal mode with `sl_bt_system_reboot()`. If using Gecko SDK 4.4.x and older, the device is reset with `sl_bt_system_reset(0)`.

A detailed description of the DFU-related BGAPI commands is found in the Bluetooth Software API Reference Manual.

At the beginning of the upgrade, the NCP host uses the command `sl_bt_dfu_flash_set_address` to define the start address. The start address shall always be set as zero. During the data upload (step 4 above) the target device calculates the flash offset automatically. The host does not need to explicitly set any write offset.

The UART DFU procedure may fail if the update image is either corrupted or data upload is interrupted for some reason. Failure due to either of these conditions is detected by the CRC check performed by the UART DFU bootloader before jumping into the main program. In this case, a `dfu_boot_failure` event is sent by the stack. The returned reason codes align with the `sl_status` codes, as shown in the platform documentation.

###### Creating Upgrade Images for the Bluetooth NCP Application

Building a C-based NCP project in Simplicity Studio does not generate the UART DFU upgrade images (GBL files) automatically. The GBL files need to be created separately by using the [Post-Build Editor](06-post-build-editor) or by running a script located in the application projects root folder. Before running the script, the application must be compiled.

Three scripts are provided in the SDK examples:

- create_bl_files.bat (for Windows)
- create_bl_files.sh (for Linux / Mac)
- create_bl_files.py (multiplatform)

The GBL files can be generated by invoking the script from the project directory. As of now, all three are available in the latest releases. In the future releases, the Python version will enjoy exclusive support and the others are going to be deprecated. If they are not present in the project, the **BLE Post Build** component must be installed to make them available. On Unix platforms, the scripts might have to be re-saved with "LF" end of line sequences instead of "CRLF" to avoid interpretation issues.

![BLE Post Build component](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image3.png)

You need to define two environment variables, `PATH_SCMD` and `PATH_GCCARM` before running the script, as shown in the following table.

<table>
    <thead>
        <tr>
            <th>Variable Name</th>
            <th>Example Variable Values</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>PATH_SCMD</td>
            <td>
                <p>C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander</p>
                <p>/Applications/Simplicity Studio 5.app/Contents/Eclipse/developer/adapter_packs/commander</p>
                <p>~/SimplicityStudio_v5/developer/adapter_packs/commander</p>
            </td>
        </tr>
        <tr>
            <td>PATH_GCCARM</td>
            <td>
                <p>C:\SiliconLabs\SimplicityStudio\v5\developer\toolchains\gnu_arm\12.2.rel1_2023.7</p>
                <p>/Applications/Simplicity Studio 5.app/Contents/Eclipse/developer/toolchains/gnu_arm/12.2.rel1_2023.7</p>
                <p>~/SimplicityStudio_v5/developer/toolchains/gnu_arm/12.2.rel1_2023.7</p>
            </td>
        </tr>
    </tbody>
</table>

Running the **create_bl_files** script creates multiple GBL files in a subfolder named **output_gbl**. The file named **full.gbl** is the upgrade image used for UART DFU. The other files are related to OTA upgrades, and they can be ignored.

If signing and/or encryption keys (named **app-sign-key.pem**, **app-encrypt-key.txt**) are present in the same directory, then the script also creates secure variants of the GBL files. More information on creating secure firmware for DFU can be found in our training document: [Secure Firmware Upgrade using OTA](https://www.silabs.com/documents/public/training/wireless/bg22-thunderboard-workshop-secure-ota-ssv5.pdf).

###### UART DFU Host Example

The UART DFU host example is a C program that is located under the Bluetooth SDK examples in the following directory (the exact path depends on the installed SDK version):

```sh
~\SimplicityStudio\SDKs\<simplicity_sdk|gecko_sdk>\app\bluetooth\example_host\bt_host_uart_dfu
```

In Windows this program can be built using MinGW. (It is recommended that you use the MSYS2 development toolchain, available at [https://www.msys2.org/](https://www.msys2.org/). Follow the instructions found in that location on installing GCC.) In Linux or Mac, the program can be built using the GCC toolchain.

The project is built by running `make` (or `mingw32-make`) in the project root directory. After a successful build, an executable is created in the subfolder named **exe**. The executable filename is **bt_host_uart_dfu(.exe)**.

Before running the example, you need to check the COM port number or TCP/IP address associated with your NCP target. For more details, see [Using the Silicon Labs Bluetooth Stack v3.x and Higher in Network Co-Processor Mode](https://docs.silabs.com/bluetooth/latest/bluetooth-network-coprocessor-mode/).

The bt_host_uart_dfu program requires three command line arguments:

- Serial port (-u) or TCP/IP address (-t) – TCP port is not needed
- Baud rate (-b) – in case of Serial port
- Name of the (full) GBL file

Furthermore, the device must be flashed with the **BGAPI UART DFU Bootloader** and an NCP-application.

Example usage and expected output in v4.0 or higher:

```sh
./bt_host_uart_dfu -u /dev/tty.usbmodem0004402253201 -b 115200 ./full.gbl
[I] NCP host initialised.
[I] Reset NCP target in bootloader mode...
[I] DFU booted: v0x03000000
[I] Pressing Crtl+C aborts the update process.
[I] WARNING! If the update process is aborted, the device will stay in bootloader mode.

259648/259648 (100%)
[I] DFU finished successfully. Resetting the device.
```

The number of bytes uploaded in one DFU flash upload command is configurable. The UART DFU host example included in the SDK uses a 48-byte payload. The maximum usable payload length is 128 bytes. The maximum number of bytes sent in one command is specified using a C preprocessor directive named MAX_DFU_PACKET. The value of MAX_DFU_PACKET must be divisible by four.

##### Bluetooth OTA Upgrade

This is the firmware upgrade method used in SoC-mode Bluetooth applications. A GBL file containing new firmware is sent to a target device through a Bluetooth connection. The firmware upgrade image can be stored to an empty flash area and applied later by the user application, or immediately overwrite the original application using a component called AppLoader. The table below shows the differences between AppLoader-based and Application-based OTA.

|Feature|AppLoader-based OTA|Application-based OTA|
|---|---|---|
|**Implementation**|Integrated into the bootloader|Implemented in the user application|
|**Supported Devices**|Series 1 & 2|Series 2 & 3|
|**Storage slot required**|No, the old firmware is directly overwritten.|Yes, the new firmware must be stored in flash before overwriting.|
|**Supported PHY**|1M|1M, 2M, Coded|
|**Connection Encryption**|Not supported|Supported|

**Currently, it is recommended to use the Application-based OTA as it enables improved security and customizability.** (While GBL signing and encryption is supported for both, the AppLoader approach makes for a less secure connection.) Furthermore, AppLoader is not supported in Series 3 devices. The two available options are described in more detail in the sections, _Application-based OTA_ below and [AppLoader (Not recommended for new development)](#apploader-not-recommended-for-new-development). An example of creating the GBL files and using the Application-based OTA is shown in the [OTA DFU Example](#ota-dfu-example) section.

###### Application-based OTA

Application-based OTA is completely implemented in the user-application. This makes it possible to use a custom GATT service instead of the Silicon Labs OTA service used in the AppLoader. Furthermore, in case of UART DFU updates, the application can be designed to support other protocols and interfaces than BGAPI and UART. The user application can also be designed to support both OTA and UART DFU updates if needed.

To use this update mechanism, any application bootloader using internal or external storage may be used. At least one storage area must be defined, and the area must be large enough to fit the full GBL file, while not overlapping with the user application. These parameters can be controlled by configuring the **Bootloader Storage Slot Setup (bootloader_storage_slots)** component included in the bootloader project.

The basic steps for the update process are described below:

1. Application initializes the Gecko bootloader by calling `bootloader_init()`.
2. The download area for the new firmware is erased by calling `bootloader_eraseStorageSlot(0)`.
3. The update image (full GBL file) is received either over-the-air or through some physical interface like UART.
4. The application writes the received bytes to the download area by calling `bootloader_writeStorage()`.
5. (optional) Application can verify the integrity of the received GBL file by calling `bootloader_verifyImage()`.
6. Before rebooting, call `bootloader_setImageToBootload(0)` to specify the slot ID where new image is stored.
7. Reboot and instruct Gecko bootloader to perform the update by calling `bootloader_rebootAndInstall()`.

![Application-based OTA States](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image4.png)

It is assumed here that only one download area is configured and therefore the slot index in the above function calls is set to 0. The general firmware upgrade sequence is explained in [Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).

Note that the erase procedure in step 2 above takes several seconds to complete. If the new image is downloaded over a Bluetooth connection, the supervision timeout must be set long enough to avoid connection drops. Alternatively, the download area can be erased in advance, before the Bluetooth connection is opened. A third alternative is to erase the download area one flash page at a time during the writing progresses. This can be done using `bootloader_eraseRawStorage()`.

###### Enabling the Gecko Bootloader API (heading level 7)

To call the required Gecko Bootloader functions from the user application, the following interface sources must be included in the project:

**btl_interface.c** (common interface)

**btl_interface_storage.c** (interface to storage functionality)

These source files and their corresponding header files are copied to SDK sample projects by default and can be found in the SDK under:

```sh
<simplicity_sdk|gecko_sdk>\platform\bootloader\api\
```

When using the functions in the application, the correct header files can be included with:

```sh
#include "btl_interface.h"
#include "btl_interface_storage.h"
```

> **Note**: If UARTDRV (and DMADRV) is used inside the application (i.e. for logging via UART), that might cause LDMA channel conflict with the Bootloader storage access, thus preventing a successful OTA. To avoid this, both the bootloader and the application need to be configured appropriately by reducing the “Number of available channels” in the DMADRV Configuration UI of the application, allowing the Bootloader to utilize a DMA channel above it.

###### AppLoader (Not recommended for new development)

The AppLoader, introduced in Series 1, can be viewed as a small extension that manages everything related to OTA DFU. It contains a minimal version of the Bluetooth stack including only features that are necessary to perform OTA updates. Any Bluetooth features that are not necessary to support OTA updates are disabled in AppLoader to minimize the flash footprint.

The AppLoader features and limitations are summarized below:

- Enables OTA updating of user application.
- Only one Bluetooth connection is supported, GATT server role only.
- Bluetooth parameters used during firmware upgrade, such as advertisement and connection interval, can’t be changed.
- Encryption and other security features such as bonding are not supported.

The AppLoader is placed before the user application in flash. The default linker script provided in the SDK places the user application so that it starts at the flash sector following the AppLoader. The user application contains a full-featured version of the Bluetooth stack, and it can run independently of the AppLoader. If in-place OTA update is not needed, the AppLoader can be removed completely to free up flash for other use (code space or data storage).

###### Series 1 vs Series 2 (heading level 7)

From GSDK v4.1.0 and higher, there is a clear distinction between the integration of Apploader for Series 1 and Series 2 devices. For Series 1 devices, the Apploader is a separate application from both the main and the bootloader.

![Example flash layout for Series 1 devices using AppLoader](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image5.png)

For Series 2 devices, the AppLoader is added as a part of the bootloader. This results in the following for Series 2 devices:

- The AppLoader cannot be upgraded or flashed by itself.
- The AppLoader is upgraded by upgrading the bootloader.
- The OTA advertising data cannot be changed.
- The size of the combined bootloader and AppLoader is much larger than that of a regular bootloader, and it does not fit into the regular bootloader area.

![Example flash layout of a Series 2 device using the combined Bootloader and AppLoader](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image6.png)

###### AppLoader OTA Process (heading level 7)

Most of the OTA functionality is handled autonomously by the AppLoader. The minimum requirement for the user application is to trigger a reboot into DFU mode. After the upload is complete, AppLoader will reboot the device back into normal mode.

Reboot into DFU mode can be triggered in a variety of ways. It is up to the application developer to decide which is most applicable. Most of the example applications provided in the Bluetooth SDK already have OTA support built into the code. In these examples, the DFU mode is triggered through the Silicon Labs OTA service that is included as part of the application’s GATT database. An example of a user defined trigger can be found in [Triggering Reboot into DFU Mode from the User Application](#triggering-reboot-into-dfu-mode-from-the-user-application).

AppLoader supports two types of updates:

- Partial update: only the user application is updated
- Full update: both AppLoader and the user application are updated (1)  
  > **Note**: For Series 1 devices using older than v4.1.0 versions of GSDK, we recommend a combined upgrade of Bootloader and AppLoader to avoid 0x84 (NOT_SUPPORTED) parsing errors and a separate application upgrade step to avoid the 0x87 (APPLICATION_OVERLAP_APPLOADER) error. For detailed error explanations, see [OTA Error Codes](#ota-error-codes).  
  For Series 2 devices, the same steps can be followed, but the AppLoader is updated as part of the bootloader, after which the application must be updated. For this, the bootloader must be converted into .gbl format by using Simplicity Commander:  
  ```sh  
  commander gbl create bootloader-apploader.gbl --bootloader bootloader-apploader.s37  
  ```

The partial update process using AppLoader consists of the following steps:

1. OTA client connects to target device.
2. Client requests target device to reboot into DFU mode.
3. After reboot, client connects again.
4. During the 2nd connection, target device is running AppLoader (not the user application).
5. New firmware image is uploaded to the target.
6. AppLoader copies the new application on top of the existing application.
7. When upload is finished and connection closed, AppLoader reboots back to normal mode.
8. Update complete.

With partial update, it is possible to update the Bluetooth stack and user application. AppLoader is not modified during partial update.

Full update enables updating both the AppLoader and the user application. A full update is always recommended when moving from one SDK version to another. The size of AppLoader can vary depending on the SDK version, so this may prevent a partial OTA update if the new application image overlaps with the old AppLoader version.

Full update is done in two steps. Updating the AppLoader always erases the user application and therefore the AppLoader update must be followed by an application update.

The first phase of full update updates the AppLoader, and it consists of following steps for Series 1 devices:

1. OTA client connects to the target device.
2. The Client requests target device to reboot into DFU mode.
3. After reboot, the client reconnects.
4. During the 2nd connection, the target device is running AppLoader (not the user application).
5. New AppLoader image is uploaded to the target.
6. AppLoader copies the image into the download area (specified in Gecko bootloader configuration).
7. When the upload is finished and the connection closed, AppLoader reboots and requests Gecko Bootloader to install the downloaded image.
8. Gecko Bootloader updates AppLoader using the downloaded image and reboots.
9. After reboot, the new AppLoader is started.

At the end of the AppLoader update, the device does not contain a valid user application and therefore AppLoader will remain in DFU mode. To complete the update, a new user application is uploaded following the same sequence of operations that were described for the partial update.

###### Configuring the AppLoader (heading level 7)

In order to use OTA for firmware upgrades, the user must first configure the bootloader (only for Series 2) and the application to support the AppLoader. Once this is done, the user is ready to generate the .gbl file, as described in [Creating the GBL Files](#creating-the-gbl-files).

###### Bootloader (heading level 8)

This step is only required for Series 2. If you are using a Series 1 device, you can move on to [the application](#application).

Configuring the bootloader for OTA can be done in two ways. The most straightforward method is to include the sample Bootloader project, **SoC Bluetooth AppLoader OTA DFU**, where all necessary configurations are already set.

![Sample bootloader project containing the AppLoader](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image7.png)

Alternatively, you can add the **Bluetooth AppLoader OTA DFU (bootloader_apploader)** software component to your already existing bootloader. After this component is added, the **Base address of bootloader upgrade image** must be updated in the **Bootloader Core** component. This is done to prevent the new bootloader from overwriting itself during the OTA update. Any appropriate value can be used as long as the base address is larger than the size of the bootloader itself. The recommended value is 0x18000.

![The software component that adds AppLoader to the bootloader](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image8.png)

###### Application (heading level 8)

In your application project, only the **In-Place OTA DFU (in_place_ota_dfu)** component needs to be added. If you are using a sample project, this component might be included by default.

![The required software component for adding OTA support to the application](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image9.png)

The **In-Place OTA DFU (in_place_ota_dfu)** component requires the following components, which are automatically included:

- **AppLoader Support for Applications (apploader)** which on:
- Series 1 devices: includes the AppLoader binary as an additional prebuilt library.
- Series 2 devices: moves the application start address to give space for an AppLoader OTA DFU Bootloader. It also requires a Gecko Bootloader with an AppLoader OTA DFU plugin to be present on the device.
- **AppLoader Utility (apploader_util)**, which provides utility functions related to OTA DFU, such as a unified API for resetting the device to DFU mode.

![AppLoader components for applications](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image10.png)

###### Triggering Reboot into DFU Mode from the User Application (heading level 7)

The minimum functional requirement to enable OTA in the user application is to implement a ‘hook’ that allows the device to be rebooted into DFU mode.

1. The code checks if the OTA control characteristic was written, and if so, sets `boot_to_dfu` to true. After this, the connection is closed.
2. The device is rebooted into DFU mode with `sl_bt_system_reset(2)` or `sl_apploader_util_reset_to_ota_dfu()`. Parameter value 2 indicates that the device is to be rebooted into OTA DFU mode. The rest of the OTA upgrade is managed by AppLoader and no further actions are needed from the user application.
3. This code is now incorporated into the `sl_bt_in_place_ota_dfu.c` source file, part of the **In-Place OTA DFU (in_place_ota_dfu)** component.

![Handling the Write to OTA Control Characteristic in C Code](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image11.png)

![Handling the Write to OTA Control Characteristic in C Code](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image12.png)

###### OTA DFU Example

The Bluetooth SDK includes an OTA host reference implementation that can be used for testing OTA. The example is written in C and uses a WSTK in Network Co-Processor (NCP) mode. The OTA host application itself runs on the host computer. For more information on the NCP mode of operation, see [Using the Silicon Labs Bluetooth Stack v3.x and Higher in Network Co-Processor Mode](https://docs.silabs.com/bluetooth/latest/bluetooth-network-coprocessor-mode/).

The target device to be upgraded over-the-air is identified by its Bluetooth address.

![OTA host example setup](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image13.png)

In this example, we will use the application-based OTA, but AppLoader can also be used.

###### Preparing the SoC Application (heading level 7)

In this example, we use the **Bluetooth – SoC Empty** sample application, together with one of the internal-storage bootloaders.

![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image14.png)

As the **In-Place OTA DFU (in_place_ota_dfu)** is not used, it can be removed from the project. The source of **Application OTA DFU (app_ota_dfu)** can be found at:

```sh
<simplicity_sdk|gecko_sdk>\app\bluetooth\common\app_ota_dfu
```

###### Creating the GBL files (heading level 7)

Once the Application-based OTA has been added, the project can be compiled. After compiling, the GBL files must be created separately by using the [Post-Build Editor](06-post-build-editor) or by running one of the following scripts from the project root folder:

Three scripts are provided in the SDK examples:

- create_bl_files.bat (for Windows)
- create_bl_files.sh (for Linux / Mac)
- create_bl_files.py (multiplatform)

The GBL files can be generated by invoking the script from the project directory. As of now, all three are available in the latest releases, but in future releases the Python version will enjoy exclusive support with the others being deprecated. If they are not present in the project, the **BLE Post Build** component must be installed to make them available. On Unix platforms, the scripts might have to be resaved with "LF" end of line sequences, instead of "CRLF" to avoid interpretation issues.

Before running the scripts, two environment variables must be defined, `PATH_SCMD` and `PATH_GCCARM`, as seen in the table below:

<table>
    <thead>
        <tr>
            <th>Variable Name</th>
            <th>Example Variable Values</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>PATH_SCMD</td>
            <td>
                <p>C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander</p>
                <p>/Applications/Simplicity Studio 5.app/Contents/Eclipse/developer/adapter_packs/commander</p>
                <p>~/SimplicityStudio_v5/developer/adapter_packs/commander</p>
            </td>
        </tr>
        <tr>
            <td>PATH_GCCARM</td>
            <td>
                <p>C:\SiliconLabs\SimplicityStudio\v5\developer\toolchains\gnu_arm\12.2.rel1_2023.7</p>
                <p>/Applications/Simplicity Studio 5.app/Contents/Eclipse/developer/toolchains/gnu_arm/12.2.rel1_2023.7</p>
                <p>~/SimplicityStudio_v5/developer/toolchains/gnu_arm/12.2.rel1_2023.7</p>
            </td>
        </tr>
    </tbody>
</table>

Running the **create_bl_files** script creates GBL files in a subfolder named output_gbl. The **application.gbl** file is the relevant file for OTA.

If signing and/or encryption keys (named **app-sign-key.pem**, **app-encrypt-key.txt**) are present in the project directory then the script also creates secure variants of the GBL files. More information on creating secure firmware for DFU can be found in our training document: [Secure Firmware Upgrade using OTA](https://www.silabs.com/documents/public/training/wireless/bg22-thunderboard-workshop-secure-ota-ssv5.pdf).

If properly named bootloader binaries (such as bootloader-second-stage.s37 or bootloader-apploader.s37) are present in the application project folder, the **create_bl_files** script will incorporate those in the final GBL file.

###### Preparing the NCP Application (heading level 7)

The development kit that is used on the host side should be programmed with firmware that is suitable for NCP mode. The Bluetooth SDK includes an example project called “**Bluetooth NCP**” that can be used for this purpose.

The WSTK features an on-board USB-to-UART converter so that the board will be seen as a virtual Serial port by the host computer. The WSTK also has an Ethernet controller which can be used for the NCP connection.

###### Preparing the Host Application (heading level 7)

The OTA host example is found in the following directory under the SDK installation tree (the exact path depends on the installed SDK version), but for example:

{@Manual intervention TextBox Need consider what to do}

The project folder contains a makefile that allows the program to be built using for example MinGW. (It is recommended that you use the MSYS2 development toolchain, available at [https://www.msys2.org/](https://www.msys2.org/). Follow the instructions there on how to install GCC.) Alternatively, use make in any Unix environment. An executable file is created in subfolder named **exe**. The executable filename is **bt_host_ota_dfu(.exe)**.

###### Running OTA with the NCP Host Example (heading level 7)

The OTA host program expects the following command-line arguments:

- Serial port (-u) or TCP/IP address (-t) – TCP port is not needed
- Baud rate (-b) – in case of Serial port
- Name of the GBL file to be uploaded into target device (-g)
- Bluetooth address of the target device (-a)
- (optional) Force write without response (possible values 0 / 1, default is 0) (-w)

A full OTA upgrade is done in two parts and it requires two separate GBL files, one for the bootloader and another for the user application. If the bootloader and application has been combined into one image, as described in [Creating the GBL Files](#creating-the-gbl-files) or [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/), the upgrade can be done in one part.

For upgrading the bootloader and application separately, the host application must be invoked twice:

```sh
./bt_host_ota_dfu -u /dev/tty.usbmodem0004402253201 -b 115200 -g ./ bootloader-second_stage.gbl -a 00:0B:57:0B:49:23
./bt_host_ota_dfu -u /dev/tty.usbmodem0004402253201 -b 115200 -g ./application.gbl -a 00:0B:57:0B:49:23
```

> **Note: The GBL files can also be uploaded using the Simplicity Connect mobile application, as described in [Using Simplicity Connect for OTA DFU](https://docs.silabs.com/mobile-apps/latest/mobile-apps-using-connect-for-ota-dfu/).**

If the application alone is going to be upgraded, then the host program is run once, with the **application.gbl** file passed as parameter.

###### OTA Host Example Internal Operation (heading level 7)

The OTA host example is implemented as a state machine. The key steps in the OTA sequence are summarized below. Note that the program execution is independent of the type of upgrade image that is used. The program simply uploads one GBL file into the target device. It is up to the user to invoke the program either once or twice, depending on the upgrade type (partial OTA or full OTA).

The following diagram illustrates the state transitions in the OTA host example program in a slightly simplified form.

![OTA Host Application States](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image15.png)

**INIT**: The program checks the total size of the GBL file that is passed as a command-line parameter. The GBL file content is not parsed. It is enough to know the file size so that the entire content can be uploaded to target device.

**CONNECT**: The program tries to open a connection to the target device whose Bluetooth address is given as a command line parameter. The host program does not scan for devices. If the target device is not advertising, then the connection open attempt causes the program to be blocked.

**FIND SERVICES**: After a connection has been established, the program performs a service discovery. In this case only the OTA service is of interest, and therefore the program performs discovery of services with that specific UUID using the API call `sl_bt_gatt_discover_primary_services_by_uuid`. More information on the OTA service can be found in [Silicon Labs OTA GATT Service](#silicon-labs-ota-gatt-service).

**FIND CHARACTERISTICS**: After the service has been found, the characteristics of the OTA service are queried using API call `sl_bt_gatt_discover_characteristics`. The handle value for the **ota_control** needs to be discovered in order to proceed with the OTA procedure.

**RESET TO DFU**: If the target is not already in the DFU-mode, the host program requests reboot into DFU mode by writing value 0x00 to the ota_control characteristic. The execution then jumps back to the **CONNECT** state.

**OTA BEGIN**: If both ota_data and ota_control characteristic handles have been detected, the host program initiates OTA by writing value `0x00` to the `ota_control` characteristic. This does not cause reboot or any other side effects because the target device is already in DFU mode.

**OTA UPLOAD**: This is where the GBL file is uploaded to the target device. The whole content of the GBL file is uploaded to the target device, by performing multiple write operations into the ota_data characteristic. The host program uses the write-without-response transfer type to optimize throughput. Note that even if the write-without-response operations are not acknowledged at the application level, error checking (and retransmission when needed) at the lower protocol layers ensures that all packets are delivered reliably to the target device.

**OTA END**: Once the OTA upload is completed, the host program ends the OTA procedure by writing value `0x03` to the `ota_control` characteristic. Finally, the program terminates.

Some error cases have been omitted from the state diagram for simplicity. For example, the program exits with an error code if the OTA service is not found when performing service discovery or if the `ota_control` characteristic is not discovered in **FIND CHARACTERISTICS** state.

> **Note**: When the target device reboots into DFU mode, the host program must perform full service and characteristic discovery again. It is not possible to store the `ota_control` and `ota_data` characteristic handles in memory and use those cached values during the second connection. This is because the target device has two GATT databases that are independent of each other: one that is used by the application in normal mode and the other that is used by AppLoader in OTA DFU mode. While both of these GATT databases might include the Silicon Labs OTA service, the characteristic handles are likely to have different values. Therefore any kind of GATT caching cannot be used.

###### OTA GATT Database and Generic Attribute Service

When booted into DFU mode, the AppLoader uses a GATT database that is different than the normal GATT used by the application. The OTA DFU GATT database used by AppLoader contains following services:

- Generic Attribute (UUID 0x1801)
- Generic Access (UUID 0x1800)
- Silicon Labs OTA service (UUID 0x1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0)

The Bluetooth specification requires that, if GATT-based services can change in the lifetime of the device, then the **Generic Attribute Service** (UUID 0x1801) and the **Service Changed** characteristic (UUID 0x2A05) shall exist in the GATT database. For details, please see [Bluetooth Core specification](https://www.bluetooth.com/specifications/specs/), Version 6.0, Vol. 3, Part G, 7 DEFINED GENERIC ATTRIBUTE PROFILE SERVICE.

The Generic Attribute service is automatically included in the AppLoader GATT database used during OTA. To avoid any interoperability issues due to GATT caching, it is strongly recommended that the application GATT database used in normal mode also enables this service. Generic Attribute service is enabled by default in the SDK example applications.

> **Note**: AppLoader does not generate a service changed indication when rebooting to DFU mode or rebooting back to normal mode.

Automatic service changed indication requires that the client is bonded and has enabled the indication for this characteristic. AppLoader does not support bonding and therefore the service changed indication is not generated.

The Generic Attribute Service can also be explicitly defined in the application’s GATT database using the same XML notation that is used for other services. The Generic Attribute service must be the first service in the list, to ensure it is aligned with the Generic Attribute Service that is used during OTA. The Bluetooth specification requires that the attribute handle of the Service Changed characteristic shall not change and therefore this service must be first on the list (the same as in the OTA GATT database).

More details on the Generic Attribute Service can be found on the Bluetooth SIG website:

[https://www.bluetooth.com/specifications/specs/](https://www.bluetooth.com/specifications/specs/)

Note also that AppLoader does not support the GATT caching enhancements that were introduced in the Bluetooth Core Specification 5.1 and Silicon Labs Bluetooth SDK 2.11.1.

###### Silicon Labs OTA GATT Service

The following XML representation defines the Silicon Labs OTA service. It is a custom service using 128-bit UUID values. The service content and the UUID values are fixed and must not be changed.

The OTA service characteristics are described in the following table. The UUID value of the service itself is 1d14d6eefd63-4fa1-bfa4-8f47b42119f0.

|Characteristic|UUID|Type|Length|Support|Properties|
|---|---|---|---|---|---|
|OTA Control Attribute|F7BF3564-FB6D-4E53-88A4-5E37E0326063|Hex|1 byte|Mandatory|Write (4)|
|OTA Data Attribute (1)|984227F3-34FC-4045-A5D0-2C581F81A153|Hex|Variable; max 244 bytes|Mandatory|Write without response; Write|
|AppLoader version (2) (Bluetooth stack version 2,3)|4F4A2368-8CCA-451E-BFFF-CF0E2EE23E9F|Hex|8|Optional|Read|
|OTA version (2)|4CC07BCF-0868-4B32-9DAD-BA4CC41E5316|Hex|1|Optional|Read|
|Gecko Bootloader version (2)|25F05C0A-E917-46E9-B2A5-AA2BE1245AFE|Hex|4|Optional|Read|
|Application version|0D77CC11-4AC1-49F2-BFA9-CD96AC7A92F8|Hex|4|Optional|Read|

**Notes**:

1. This characteristic is excluded from the user application GATT database.
2. Version information is automatically added by AppLoader when running in DFU mode. These are optional in the application GATT database.
3. This characteristic exposes the AppLoader version.
4. Silicon Labs highly recommends that the default property (i.e, write) be used only over bonded connections to prevent uploading of new firmware by untrusted/unknown devices.

The table below provides possible control words written to the OTA control characteristic.

|Hex value|Description|
|---|---|
|0x00|OTA client initiates the upgrade procedure by writing value 0.|
|0x03|After the entire GBL file has been uploaded the client writes this value to indicate that upload is finished.|
|0x04|Request the target device to close connection. Typically the connection is closed by OTA client but using this control value it is possible to request that disconnection is initiated by the OTA target device.|
|Other values|Other values are reserved for future use and must not be used by application.|

In DFU mode, AppLoader uses the full OTA service described above. The GATT database of the user application includes only a subset of the full OTA service. The minimum application requirement is to include the OTA Control characteristic. The application must not include the OTA Data characteristic in its GATT database (unless the OTA update is implemented fully in application code, as described in [Application-Based OTA](#application-based-ota).)

From the user application viewpoint, only the OTA Control Attribute is relevant. In the OTA host example reference implementation included in the SDK, the OTA procedure is triggered when the client writes value 0 to the OTA Control Attribute. The user application does not handle data transfers related to OTA upgrades, so the OTA Data Attribute is excluded from the user applications GATT.

It is also possible to use an application-specific trigger to enter OTA mode, and therefore it is not necessary to include the OTA Control Attribute in the application’s GATT database. If reboot into DFU mode is handled using some other mechanism, then it is possible to exclude the whole OTA service from the application GATT. However, it should be noted that to be compatible with the OTA host example from the SDK or the Si Connect smartphone app the OTA trigger must be implemented as described above.

The presence of the OTA Data Attribute in the GATT database is used by the OTA host example application to check whether the target device is running in normal mode (user application) or DFU mode (AppLoader). Therefore, the OTA Data Attribute must not be included in the user application’s GATT. The OTA-enabled examples in the Bluetooth SDK only expose the OTA Control Attribute.

The four characteristics after the OTA Data Attribute are automatically added in the GATT database that is used by AppLoader. These include version information that can be read by the OTA client before starting the firmware update. For example, by checking the AppLoader version, the OTA client may check if a full or partial update is needed.

The AppLoader version is a 8-byte value that consists of four two-byte fields, indicating the AppLoader version in the form <major>.<minor>.<patch>-<build>. For example, value 010000000000170b can be interpreted as version “1.0.0-2839”.

The OTA version is a 1-byte value that indicates the OTA protocol version for compatibility checking. This version number is incremented only when needed, if there are some changes in the OTA implementation that may cause backward compatibility issues.

The Gecko Bootloader version is a 4-byte value that is configured in a Gecko Bootloader project in **config/btl_core_config.h**. The two most significant bytes are the major and minor numbers. The other two bytes are customer-specific, and they can be set to indicate certain Gecko Bootloader configuration options (for example, whether secure boot is required or not). As an example, value 00000401 indicates that the Gecko Bootloader version is “1.4” and the customer-specific part is 0x0000 (this is the default if no customer-specific version info has been configured in the Gecko Bootloader project).

The application version is a 4-byte value, and it is initialized to the same value that is defined in **config/app_properties_config.h**. The encoding of this value is application specific. The application properties file is discussed in more detail in [Application Properties in OTA Mode](#application-properties-in-ota-mode).

AppLoader does not include support for encryption or bonding and therefore there are no access restrictions on any of the characteristics listed in [Silicon Labs OTA GATT Service](#silicon-labs-ota-gatt-service). Because the user application has its own GATT database it is possible to include additional security requirements there as needed. For example, the user application can require that the OTA Control Attribute is writable only by a bonded client so that only bonded client can trigger reboot into DFU mode.

For additional security, it is recommended to configure the Gecko Bootloader to use secure boot and signed GBL images.

###### OTA Advertising Data

The default OTA advertising data includes the device name, TX power, advertising flags, and the Bluetooth device address. The following text snippet illustrates typical default raw OTA advertising data and how it is dissected into different advertising data elements.

![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image16.png)

For Series 1 devices, `sl_bt_ota_set_advertising_data(packet_type, adv_data_len, adv_data)` can be used to set custom OTA advertising data (only available in GSDK releases). The packet type identifies whether data is intended for advertising packets or scan response packets.

2: OTA advertising packets

4: OTA scan response packets

You can set a maximum of 31 bytes of data.

> **Note**: The OTA configuration commands must be called after NVM3 (PS) initialization has been done; that is, after `sl_bt_init()`.

The Bluetooth device address that is used in OTA mode is determined as follows:

- Use a static random address if it has been enabled in the OTA configuration flags.
- If the user application has overridden the default Bluetooth address (using command `sl_bt_system_set_identity_address(address, type)`), then use this address.
- The default Bluetooth address (programmed into the device in production) is used if neither a static random address nor custom address has been defined.

For Series 1 devices, in OTA mode, the TX power is hardcoded to 0 dBm. For Series 2 devices, the TX power level can be configured using the **Bluetooth AppLoader OTA DFU (bootloader_apploader)** component inside the bootloader-apploader project.

###### Application Properties in OTA Mode

The source file **app_properties.c** must be included in projects that use OTA and the Gecko Bootloader. This file is included in the SDK examples by default. Application properties are stored in a fixed location in code flash so that AppLoader can access the data when the device is running in OTA mode. The properties include a 32-bit version number that is application-specific. It is up to the application designer to decide how this value is encoded. This value is exposed in the GATT database used by AppLoader so that the OTA client can read it over the Bluetooth connection after the device has been rebooted into OTA mode.

The version information is set using following #define in **config/app_properties_config.h**:

![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image17.png)

The default value is set to 1, but it is strongly recommended that meaningful version number information is added here so that the OTA client can check the exact version that is installed on the target device. This allows better management of OTA updates of units that are deployed in the field, especially in cases where units are running different versions of the application. If AppLoader does not detect any valid application at all, then the application version in the GATT database is initialized to value zero.

###### OTA Error Codes

When a new GBL file is being uploaded, the AppLoader performs various checks. AppLoader can signal possible errors to the OTA client in two ways:

1. Response to the OTA termination code (0x03) that is written to the OTA Control characteristic.
2. Response to writes to the OTA Data characteristic.

Option 2 is not available if the client uses unacknowledged writes. In that case, the possible error code is not available until the entire file has been uploaded and client finishes the upload by writing to the OTA Control characteristic.

The OTA client must always check the response value to the last write to the OTA Control characteristic. Any non-zero value indicates that the update was not successful. In that case, the device is not able to boot into the main program but rather stays in OTA mode. This makes it possible to try the update again.

The following table summarizes the possible result codes returned by AppLoader.

<table>
    <thead>
        <tr>
            <th>Result Code</th>
            <th>Name</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>0x0000</td>
            <td>OK</td>
            <td>Success / No errors found.</td>
        </tr>
        <tr>
            <td>0x0480</td>
            <td>CRC_ERROR</td>
            <td>CRC check failed, or signature failure (if enabled).</td>
        </tr>
        <tr>
            <td>0x0481</td>
            <td>WRONG_STATE</td>
            <td>This error is returned if the OTA has not been started (by writing value 0x0 to the control endpoint) and the client tries to send data or terminate the update.</td>
        </tr>
        <tr>
            <td>0x0482</td>
            <td>BUFFERS_FULL</td>
            <td>AppLoader has run out of buffer space.</td>
        </tr>
        <tr>
            <td>0x0483</td>
            <td>IMAGE_TOO_BIG</td>
            <td>New firmware image is too large to fit into flash, or it overlaps with AppLoader.</td>
        </tr>
        <tr>
            <td>0x0484</td>
            <td>NOT_SUPPORTED</td>
            <td>
                <p>GBL file parsing failed. Potential causes are for example:
                </p>
                <ol>
                    <li>Attempting a partial update from one SDK version to another (such as 2.3.0 to 2.4.0).</li>
                    <li>The file is not a valid GBL file (for example, client is sending an EBL file).</li>
                </ol>
                <p></p>
            </td>
        </tr>
        <tr>
            <td>0x0485</td>
            <td>BOOTLOADER</td>
            <td>The Gecko bootloader cannot erase or write flash as requested by AppLoader, for example if the download area is too small to fit the entire GBL image.</td>
        </tr>
        <tr>
            <td>0x0486</td>
            <td>INCORRECT_BOOTLOADER</td>
            <td>Wrong type of bootloader. For example, target device has UART DFU bootloader instead of OTA bootloader installed.</td>
        </tr>
        <tr>
            <td>0x0487</td>
            <td>APPLICATION_OVERLAP_APPLOADER</td>
            <td>New application image is rejected because it would overlap with the AppLoader.</td>
        </tr>
        <tr>
            <td>0x0488</td>
            <td>INCOMPATIBLE_BOOTLOADER_VERSION</td>
            <td>AppLoader in requires Gecko Bootloader v1.11 or higher.</td>
        </tr>
        <tr>
            <td>0x0489</td>
            <td>ATT_ERROR_APPLICATION_VERSION_CHECK_FAIL</td>
            <td>AppLoader fails checking application version.</td>
        </tr>
    </tbody>
</table>

Note that the error codes listed above are applicable only when testing with the NCP host example. The upper half of the result code (0x04**) is generated by the BLE stack running on the NCP host device. The size of the ATT error code that is transmitted over the air is one octet. Values in the range 0x80-0x9F are reserved for application-specific errors in the Bluetooth specification.

###### Firmware Upgrade from PS Store to NVM3

If an application is already in the field using PS Store and should be upgraded to use NVM3, it can be upgraded using OTA DFU with new firmware that already uses NVM3.

However, in this case the data stored in the PS Store cannot be preserved. All bonding information and stored user data will be lost. Nevertheless, the new application can reinitialize the NVM area (at the end of the main flash) to use NVM3 instead of PS Store, and after the upgrade NVM3 will be functional.

Upgrading software from PS Store to NVM3 is challenging, mostly because the application provides information to the AppLoader through non-volatile memory (PS Store / NVM3), which gets upgraded as well. The following are the detailed steps to perform an OTA upgrade from PS Store to NVM3, where the device doing the upgrade is bonded with the device to be upgraded.

> **Note**: The procedure illustrates the situation where the upgrader and the device to be upgraded are bonded to highlight all the challenges. Bonding is not a condition for upgrading from PS Store to NVM3.

1. The device uses an application with PS Store.
2. The application sets `random address OTA flag` and `OTA device name` in PS Store 10.2_2020q4.
3. The Smartphone opens a connection to this device and gets bonded (if not bonded already).
4. The application stores bonding information in PS Store.
5. The Smartphone resets the device into OTA mode by writing 0x00 into the OTA control characteristic.
6. AppLoader (with PS Store support) starts.
7. AppLoader advertises with a random address and the OTA device name.
8. The Smartphone connects and uploads a new AppLoader (with NVM3 support).
9. The device resets and applies the new AppLoader image.
10. The new AppLoader (with NVM3 support) starts.
11. The AppLoader advertises with the public address and with the default name ("AppLoader"), because it cannot read the random address flag and the OTA device name from PS Store.
12. The Smartphone sees the device as bonded because bonding information is associated with the public address, but AppLoader does not support bonding.
13. The Smartphone removes bonding information for the device before re-connecting.
14. The Smartphone connects and uploads a new application (with NVM3 support).
15. The new application starts.
16. The application initializes NVM3 by reformatting the NVM area.
17. The application sets `random address OTA flag` and `OTA device name` in NVM3.
18. The Smartphone opens a connection and gets bonded (again).
19. The application stores bonding information in NVM3.

After this, NVM3 to NVM3 update will work normally:

1. The device uses an application with NVM3.
2. The application sets `random address OTA flag` and `OTA device name` in NVM3.
3. The Smartphone opens a connection to this device and gets bonded (if not bonded already).
4. The application stores bonding information in NVM3.
5. The Smartphone resets the device into OTA mode by writing 0x00 into the OTA control characteristic.
6. AppLoader (with NVM3 support) starts.
7. AppLoader advertises with a random address and the OTA device name.
8. The Smartphone connects and uploads a new AppLoader (with NVM3 support).
9. The device resets and applies the new AppLoader image.
10. The new AppLoader (with NVM3 support) starts.
11. AppLoader advertises with a random address and the OTA device name.
12. The Smartphone connects and uploads a new application (with NVM3 support).
13. The new application starts.
14. The Smartphone opens a connection and encrypts the connection with existing bonding information.
15. Bonding information is still stored in NVM3.

##### Working with AppLoader and Secure Boot

When employing secure boot, the AppLoader and application must be signed individually for the application to be allowed to run. This is because the AppLoader authenticates the application before allowing it to run, just as the bootloader authenticates the AppLoader before allowing it to run.

![diagram](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image18.png)

This section describes how to work with this capability in a production environment.

###### Creating a Single Signed Image with a Batch File

As described previously, a signed GBL file can be produced by executing `create_bl_files.bat/create_bl_files.sh/create_bl_files.py` with a private signing key file, `app-sign-key.pem` in the same folder or by using the [Post-Build Editor](06-post-build-editor). The resulting GBL file, `full.gbl`, can be flashed directly to the target device for a successful boot. This method is convenient for testing secure boot during the development process, but is not secure for production since it requires the private signing key to be available in plain PEM format, rather than isolating it in a Hardware Security Module (HSM) and does not support the use of bootloader certificates.

###### Signing Firmware Images for Production

For Series 1 Devices:

To sign a firmware image using an HSM, the image must first be separated into the AppLoader and application parts as follows.

1. Extract the AppLoader portion with the following command: `objcopy -O srec -j .text_apploader* apploader.s37`.
2. Sign the AppLoader for secure boot. For specific instructions on signing images with an HSM, see _Signing an Application for Secure Boot using a Hard Security Module_ in [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-commands/convert-and-modify-file-commands#signing-an-application-for-secure-boot-signing-using-a-signature-created-by-a-hardware-security-module). It is also possible to sign the AppLoader with a certificate although direct signing is sufficient for most use cases. For instructions on signing with a certificate with an HSM, see _Signing an Application for Secure Boot using an Intermediary Certificate_ in the Simplicity Commander Reference Guide.
3. Extract the application with the following command: `objcopy -O srec -R .text_apploader* -R .text_signature* application.s37`.
4. Sign the application for secure boot. The instructions for signing the AppLoader in step 2 above also apply to the application.
5. Combine the signed AppLoader and application into a single image as follows: `commander convert <signed apploader>.s37 <signed application>.s37 –outfile signed_fw_image.s37`.
6. Optionally, see _Creating a Partial Signed and Encrypted GBL Upgrade File for Use with a Hardware Security Module_ and _Creating a Signed GBL File Using a Hardware Security Module_ in the _Simplicity Commander Reference Guide_.

For Series 2 devices (EFR32xG2x), the AppLoader can be included in the bootloader project as a software component. This makes it possible to sign the application and bootloader binaries without any need to perform steps 1 – 6 above.

For more information on secure boot, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

##### OTA Delta DFU

SiSDK 2024.6.1 introduced a new feature called Delta DFU. This feature can be used to speedup OTA DFU and is especially useful in large wireless networks when upgrading large amounts of devices. Delta DFU is accomplished by:

1. Comparing the current and new application firmwares
2. Creating a patch file based on the comparison
3. Only uploading the patch file to the target device

Delta DFU is not supported when using AppLoader. Instead, OTA must be implemented in the application as described in Section [OTA DFU Example](03-bluetooth-ota-upgrade#ota-dfu-example), with an internal-storage bootloader. The storage space must be large enough to hold the patch file and the reconstructed firmware. We recommend the implementation of an additional handshake process to determine the current firmware version before the appropriate previously-generated Delta DFU image is being selected for upload.

###### Preparing the Bootloader

In Delta DFU, the bootloader takes care of applying the patch file to the current application firmware. For this, we need to prepare the bootloader:

1. Create an internal-storage bootloader project  
   ![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image19.png)
2. Add the **GBL Delta DFU (bootloader_gbl_delta_dfu)** software component  
   ![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image20.png)

###### Preparing the Application

Both the current and the new application must support application-based OTA. Sample applications include the **In-Place OTA DFU (in_place_ota_dfu)** software component by default. However, OTA Delta DFU does not use the in-place method for DFU. Therefore, **In-Place OTA DFU (in_place_ota_dfu)** must be replaced by the **Application OTA DFU (app_ota_dfu)** software component.

![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image21.png)

###### Creating a Patch File

The patch file can be created using Simplicity Commander. For this, we need both the current firmware file, and the new version.

```sh
commander gbl create patch.gbl --app app_v2.out --delta-app app_v1.out
```

For this to work, an ELF file with the same name must exist next to the application image. Once the patch file is created it can further be compressed using LZMA or LZ4. More information on creating a patch file can be found in [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

> **Note**: Patch-file creation with GBL4 is not supported.

###### Delta DFU process

Once a patch file has been created, it can be uploaded to the target device via OTA just as before in a partial update. When the patch file has been uploaded, the bootloader will reconstruct it into a full firmware image. This firmware image will then be written over the old image.

###### Delta DFU and Secure Boot

When using Delta DFU with Secure Boot, make sure both the current firmware and the new version (app_v1 and app_v2, respectively) are signed using the same private key before creating the patch file. When the patch file is created, as described in [Creating a patch file](#creating-a-patch-file), the signature of app_v2 will be included in the patch. Therefore, the reconstructed firmware will have the signature of app_v2, and the new application will boot as expected.

##### Post Build Editor

From SiSDK 2024.12.0 and after, there is a new way of generating the GBL files for OTA (GBL3 format only, as of now) via a convenient graphical user interface instead of by using the command line solutions introduced previously. The option is to be found among the CONFIGURATION TOOLS:

![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image22.png)

Every previously introduced configuration option is available here, including compression, signing, and encryption:

![screenshot](/using-gecko-bootloader-with-bluetooth-apps/0.2/images/sld650-image23.png)

#### Series 2 and Series 3 Secure Boot with RTSL

##### Series 2 and Series 3 Secure Boot with RTSL

**NOTE: This section replaces _AN1218: Series 2 and Series 3 Secure Boot with RTSL_. Further updates to this application note will be provided here.**

This application note describes the design of Secure Boot with RTSL (Root of Trust and Secure Loader) on Series 2 and Series 3 devices. It also provides examples of how to implement the Secure Boot process.

For more information on using the Gecko Bootloader with Series 2 and Series 3 devices, see the following:

- [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/)
- [UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)
- [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/)
- [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/)

###### Key Points

- Compares the Secure Boot process in Series 1, Series 2, and Series 3 devices
- Describes the Series 2 and Series 3 Secure Boot with RTSL components and process
- Provides examples of configuring Series 2 and Series 3 devices for the Secure Boot process
- Recovers secure boot failure devices

##### Series 2 and Series 3 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 and Series 3 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 and Series 3 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- Series 2 devices: EFR32xx2xx devices
- Series 3 devices: SiG3xxx devices
- HSE: Hardware Secure Engine
- VSE: Virtual Secure Engine
- SE: Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level (1)**|**SE Support**|
|---|---|
|Secure Vault High (SVH) and Series 3 Secure Vault|HSE only (HSE-SVH)|
|Secure Vault Mid (SVM)|HSE (HSE-SVM), VSE (VSE-SVM)|
|Secure Vault Base (SVB)|N/A|

**Notes**:

1. The features of different Secure Vault levels can be found in [Security](https://www.silabs.com/security).
2. Refer to [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/11-series-2-device-security-features) for details on supporting devices.

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High and Series 3 Secure Vault devices offer additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

> **Note**: Series 3 Secure Vault devices do not include a device certificate for the host MCU.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products, Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Series 2 and Series 3 Secure Boot with RTSL (this application note)</p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|
|AXiP Key|No|Used on Series 3 devices for encryption/ decryption and authentication of firmware placed in flash|
|EXiP Key|No|Used on Series 3 devices for encryption/ decryption of firmware placed in flash|

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 and Series 3 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 and Series 3 devices and modules.

##### Secure Boot Process

###### Introduction

Secure Boot is a foundational component of platform security, as the absence of it can allow malicious code to subvert protections like secure storage, secure data transport, secure identity, and data confidentiality.

Secure Boot works as a process by which each piece of firmware is validated for authenticity and integrity before it is allowed to run. Each authenticated module can also validate additional modules before executing them, forming a chain of trust. If any module fails its security check, it is not allowed to run, and program control will typically stall in the validating module. In most lightweight IoT systems, the behavior of a Secure Boot failure is to cause the device to stop working until an authentically signed image can be loaded onto it. Whereas this may seem extreme, it is a better outcome than a smart light bulb being repurposed to mine crypto-currency, or a smart speaker being repurposed as a surveillance device on the end user’s private conversations.

The first link in the chain of trust is the root of trust. This is often the weakest link in the Secure Boot chain because the root of trust itself is not checked for authenticity or integrity. The security strength of the root of trust lies in its immutability. The strongest roots of trust have their firmware origin in ROM and use a Public Sign Key that is also located in ROM.

Series 1, Series 2, and Series 3 devices use a two-stage boot design consisting of a non-upgradable first stage root of trust followed by an upgradable second stage. In Series 1 devices, the root of trust (also called the first-stage bootloader) is in flash rather than ROM, and the upgradable portion (the main bootloader) is checked for integrity using a CRC32 checksum but is not checked for authenticity using a Public Sign Key. In Series 2 and Series 3 devices, the root of trust is in ROM, and the upgradable portion is checked both for integrity and authenticity.

The Secure Boot with RTSL is implemented by Root code executed by the Hardware Secure Engine (HSE) or the Cortex-M33 operating in Root Mode (VSE). For more information about SE, see section _Secure Engine Subsystem_ in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

In Series 3 devices, once firmware is programmed to the device, the code regions must be closed. Closing a code region locks it to prevent writes, as well as further configuration, and indicates to the SE that it can now be accessed by the SE. After flashing the firmware image, commander automatically closes the code region. To open a closed code region, an erase must be performed. If a code region is not closed, the SE will return a fault when attempting to access the open code region during secure boot verification of the host firmware. Each time a code region is closed, the SE's MTP (Multiple Times Programmable) memory section is updated, which causes an SE OTP bit to be used. More details on SE OTP bits is covered in the following section.

Silicon Labs provides [Custom Part Manufacturing Service (CPMS)](https://www.silabs.com/developers/custom-part-manufacturing-service) to customize the users' security features and settings. This application note uses the following abbreviations:

- FSB: First Stage Bootloader
- SSB: Second Stage Bootloader
- GBL: Gecko Bootloader
- RTSL: Root of Trust and Secure Loader
- HSM: Hardware Security Module
- OTP: One-Time Programmable
- WSTK: Wireless Starter Kit
- GSDK: Gecko Software Development Kit. For more information, refer to [GSDK](https://github.com/SiliconLabs/gecko_sdk)
- SiSDK: Simplicity Software Development Kit. For more information, refer to [SiSDK](https://github.com/SiliconLabs/simplicity_sdk)
- ECDSA-P256-SHA256: Elliptic Curve Digital Signature Algorithm aka ECDSA using a P-256 curve and a SHA256 hash
- PEM (.pem): Privacy Enhanced Mail
- DER (.der): Distinguished Encoding Rules

###### ECDSA-P256-SHA256 Secure Boot in Series 1 Devices

The Secure Boot process for Series 1 (SVB) devices originates in flash, typically with the execution of the first stage of GBL. The first stage of GBL checks to see if an upgrade is pending for the second stage of GBL. If so, it processes the upgrade of the second stage and then executes it. Otherwise, it just executes the second stage. If Secure Boot is enabled, the second stage of GBL checks the integrity and authenticity of the application image before executing it. If the integrity check fails, program control remains in the SSB. The following figure illustrates the Secure Boot process on Series 1 devices.

![Series 1 ECDSA-P256-SHA256 Secure Boot Process](/series2-secure-boot-with-rtsl/0.2/images/sld794-image15.png)

See [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/) for more information to generate and download signed firmware images using Simplicity Commander.

###### ECDSA-P256-SHA256 Secure Boot in Series 2 and Series 3 Devices

For Series 2 and Series 3 devices, the Secure Engine (SE) implements the FSB to authenticate and upgrade the SSB. The GBL implements the SSB (aka Main Bootloader in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/)) to authenticate and upgrade the application firmware.

Refer to the _Gecko Bootloader Security Features_ section in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[UG489](https://www.silabs.com/documents/public/user-guides/ug489-gecko-bootloader-user-guide-gsdk-4.pdf) and [ECDSA-P256-SHA256 Secure Boot](03-examples#signing-for-ecdsa-p256-sha256-secure-boot) example for more information about the ECDSA-P256-SHA256 secure boot process in Series 2 devices and Series 3.

> **Note**: It is possible to have a 2-stage design to skip the SSB between FSB and application. However, the application cannot be upgraded if discarding the SSB, and this application note assumes the SSB is present.

###### HSE (heading level 7)

In HSE-SVM, HSE-SVH, and Series 3 Secure Vault devices, the Secure Boot process originates in ROM contained in the security co-processor (HSE). The following figures illustrate the Secure Boot process and flow on Series 2 HSE and Series 3 devices.

![Series 2 HSE and Series 3 ECDSA-P256-SHA256 Secure Boot Process](/series2-secure-boot-with-rtsl/0.2/images/sld794-image16.png)

![Series 2 HSE and Series 3 ECDSA-P256-SHA256 Secure Boot Flow](/series2-secure-boot-with-rtsl/0.2/images/sld794-image17.png)

###### VSE (heading level 7)

In VSE-SVM devices, the host MCU (Cortex-M33) assumes an elevated security state out of reset and securely boots itself from code that originates in ROM. The following figures illustrate the Secure Boot process and flow on Series 2 VSE devices.

![Series 2 VSE ECDSA-P256-SHA256 Secure Boot Process](/series2-secure-boot-with-rtsl/0.2/images/sld794-image18.png)

![Series 2 VSE ECDSA-P256-SHA256 Secure Boot Flow](/series2-secure-boot-with-rtsl/0.2/images/sld794-image19.png)

###### Certificate-based Secure Boot in Series 2 and Series 3 Devices

Refer to the _Gecko Bootloader Security Features_ section in [UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) and [Certificate-Based Secure Boot](03-examples#signing-for-certificate-based-secure-boot) example for details about the certificate-based Secure Boot process in Series 2 and Series 3 devices.

The certificate-based Secure Boot process uses key delegation to minimize the exposure of the Private Sign Key, thereby reducing the likelihood that the corresponding Public Sign Key would need to be revoked.

If the certificate’s private key is leaked, all devices that have been programmed with that certificate are at risk until they can be updated with an image containing a certificate with a [higher version](./03-examples.md#certificate-revocation(03-examples.md#certificate-revocation).

###### Secure Loader

In Series 2 and Series 3 devices, the Secure Loader is firmware pre-loaded into the chip. Silicon Labs maintains the Secure Loader and deploys through secure upgrade packages. It is the functional equivalent of the first-stage GBL on Series 1 devices (refer to [UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) for more information). The Secure Loader validates the authenticity and integrity of a staged image before performing an upgrade operation. The Secure Loader requires the staged image to reside on-chip and the staged image must not overlap with the target destination address range. Firmware images that originate from off-chip, either off-chip storage, external NCP/ RCP host interface, or through an OTA update procedure are expected to be staged either by the application or by SSB before calling the Secure Loader to perform the upgrade.

![Series 2 and Series 3 Secure Loader Example](/series2-secure-boot-with-rtsl/0.2/images/sld794-image20.png)

###### Secure Boot Time

Secure boot extends the recovery time from all sources of device reset. The duration of each authentication operation depends on the factors below:

- Computation of the SHA-256 digest (32 bytes) of the associated image, which is proportional to the size of the firmware image.
- Verification of the ECDSA-P256 signature of the SHA-256 digest above, which is independent of image size.
- The clock frequency of the Crypto Engine, which is the HSE or CRYPTOACC in VSE devices.

|**Authentication**|**Enable/Disable**|**Duration**|
|---|---|---|
|FSB code|Enable (cannot disable)|FSB code size dependent|
|SSB code|Disable (by default)|SSB code size and SE firmware version dependent|
|Application code|Disable (by default)|Application code size and SSB firmware (GBL) version dependent|

**Notes**:

- It will extend the boot time for certificates authentication if using [Certificate-Based Secure Boot](03-examples#signing-for-certificate-based-secure-boot).
- Refer to device-specific datasheets (like [EFR32MG21B](https://www.silabs.com/documents/public/data-sheets/efr32mg21b-datasheet.pdf)) for data about the boot timing of Series 2 devices.
- Refer to _Secure Boot Configuration_ below on how to enable the SSB and application code authentication.

###### Secure Boot Configuration

The following sections describe how to configure the Secure Boot of the SSB (GBL) and application firmware.

###### SSB (heading level 7)

In Series 2 and Series 3 devices, the immutable OTP memory stores the [Public Sign Key, Secure Boot Enable flag](03-examples#provision-public-sign-key-and-secure-boot-enabling), and Anti-rollback flag. The user cannot change its respective value once either is programmed. Once the Public Sign Key is provisioned, it remains provisioned to that key value for the life of the device. Once Secure Boot and Anti-rollback is enabled, it remains enabled for the life of the device. Both of these assignment operations are **IRREVOCABLE**.

The Public Sign Key used for Series 2 and Series 3 devices is the public portion of an ECDSA key pair over the NIST prime curve P-256. The Public Sign Key is a customer key and is typically provisioned during the initial product manufacturing and device programming phase. It is common for all products that share the same firmware image to be loaded with the same Public Sign Key. The key loaded into the device is a public key and has no confidentiality requirements. The private key associated with that public key, which will be used to sign firmware images or certificates, should be tightly held, ideally secured in the [HSM](03-examples#generate-key-and-signing) or equivalent key storage instrument.

You can use [Simplicity Commander](03-examples#simplicity-commander), [SE Manager](03-examples#se-manager-key-provisioning-platform-example), or [Simplicity Studio](03-examples#simplicity-studio) to program the Public Sign Key and configure the SSB Secure Boot with anti-rollback in SE OTP. The following figures show the Simplicity Studio and Simplicity Commander implementation, for detailed steps refer to the Example section:

![Configuration of SSB using Simplicity Studio](/series2-secure-boot-with-rtsl/0.2/images/sld794-image21.jpg)

![Configuration of SSB using Simplicity Commander](/series2-secure-boot-with-rtsl/0.2/images/sld794-image22.jpg)

###### Application Firmware (heading level 7)

You can use the AppBuilder or [Bootloader-core software component](03-examples#bootloader-core-software-component) in the [GBL](03-examples#generate-an-unsigned-gbl-image) project to configure the security options of the application firmware.

You can reconfigure the Secure Boot configuration of the application firmware by upgrading the GBL with the new custom settings.

![Using AppBuilder](/series2-secure-boot-with-rtsl/0.2/images/sld794-image23.png)

Using Bootloader core compoent

![Using Bootloader core component](/series2-secure-boot-with-rtsl/0.2/images/sld794-image24.jpg)

![Security Options of Application Firmware using AppBuilder and Bootloader Core Component](/series2-secure-boot-with-rtsl/0.2/images/sld794-image25.jpg)

> **Note**: Install "Bootloader Core (Series-3)" for series 3 devices.

##### Examples

###### Overview

The following table describes the examples for Series 2 and Series 3 Secure Boot.

> **Note**: Series 3 devices require SE firmware Version 3.1.0 or later to support Secure Boot. However, version 3.3.4 or newer is recommended for full feature support and latest security enhancements.

|**Example**|**Device (Radio Board)**|**Minimum SE Firmware**|**Tool**|
|---|---|---|---|
|Provision Public Sign Key and Secure Boot Enabling|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|"|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|SE Manager|
|"|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Studio 5|
|Provision GBL Decryption Key|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|"|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|SE Manager|
|Signing for ECDSA-P256-SHA256 Secure Boot|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|Signing for Certificate-Based Secure Boot|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|Generate a GBL Upgrade Image File|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|Upgrade to Certificate-Based Secure Boot|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|Certificate Revocation|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|
|Upgrade to Secure Boot with RTSL|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|SE Manager & Simplicity Commander|
|Recover Devices when Secure Boot Fails|EFR32MG21A010F1024IM32 (BRD4181A)|Version 1.2.9|Simplicity Commander|

> **Note**: Unless specified in the example, these examples can be applied to other Series 2 and Series 3 devices.

###### Using Simplicity Commander (heading level 7)

1. This application note uses Simplicity Commander v1.19.2. The procedures and console output may be different for the other versions of Simplicity Commander. The latest version of Simplicity Commander can be downloaded from [MCU Programming options](https://www.silabs.com/developer-tools/mcu-programming-options).  
   > **Note**: It is recommended to upgrade to the latest version of Simplicity Commander.  
   ```sh  
   commander --version  
   ```  
   ```sh  
   Simplicity Commander 1v19p2b1907  
     
   JLink DLL version: 7.52d  
   Qt 5.12.10 Copyright (C) 2017 The Qt Company Ltd.  
   EMDLL Version: 0v17p19b0  
   mbed TLS version: 2.16.6  
     
   Emulator found with SN=440048205 USBAddr=0  
     
   DONE  
   ```
2. The Simplicity Commander's Command Line Interface (CLI) is invoked by `commander.exe` in the Simplicity Commander folder. The location for Simplicity Studio 5 in Windows is `C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander`. For ease of use, it is highly recommended to add the path of commander.exe to the system PATH in Windows.
3. If more than one WSTK is connected via USB, the target WSTK must be specified using the `--serialno <J-Link serial number>` option.
4. If the WSTK is in debug mode OUT, the target device must be specified using the `--device <device name>` option. For more information about Simplicity Commander, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### Using an External Tool (heading level 7)

The [Secure Boot examples](#secure-boot) use the **OpenSSL** to sign the image files and certificates. The Windows version of OpenSSL can be downloaded from [https://slproweb.com/products/Win32OpenSSL.html](https://slproweb.com/products/Win32OpenSSL.html). This application note uses OpenSSL Version 3.5.0 (Win64).

```sh
openssl version
```

```sh
OpenSSL 3.5.0 8 Apr 2025 (Library: OpenSSL 3.5.0 8 Apr 2025)
```

The OpenSSL's Command Line Interface (CLI) is invoked by `openssl.exe` in the OpenSSL folder. The location in Windows (Win64) is `C:\Program Files\OpenSSL-Win64\bin`. For ease of use, it is highly recommended to add the path of `openssl.exe` to the system `PATH` in Windows.

###### Using a Platform Example (heading level 7)

Simplicity Studio 5 includes the [SE Manager platform example](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/start-a-project#examples) for key provisioning and Secure Boot enabling. This application note uses platform example of SiSDK v2025.6.1. The console output may be different on other versions.

Refer to the corresponding readme file for details about each SE Manager platform example. This file also includes the procedures to create the project and run the example.

###### Generate Key and Signing (heading level 7)

This section describes how to generate a key to sign an image file or certificate for Secure Boot using Simplicity Commander or using an HSM with Simplicity Commander (Openssl). For production environments, it is strongly recommended to generate keys with an HSM.

###### Using Simplicity Commander (heading level 8)

1. Run the `util genkey` command to generate the ECDSA-P256 Sign Key pair (`sign_key.pem` and `sign_pubkey.pem)` and Public Sign Key token file (`sign_pubkey.txt`). The Simplicity Commander can program the Public Sign Key in token file (`sign_pubkey.txt`) to the [top page of the main flash](#signing-for-ecdsa-p256-sha256-secure-boot).  
   ```sh  
   commander util genkey --type ecc-p256 --privkey sign_key.pem --pubkey sign_pubkey.pem  
   --tokenfile sign_pubkey.txt  
   ```  
   ```sh  
   Generating ECC P256 key pair...  
   Writing private key file in PEM format to sign_key.pem  
   Writing public key file in PEM format to sign_pubkey.pem  
   Writing EC tokens to sign_pubkey.txt...  
   DONE  
   ```  
   > **Note**: The same procedure can apply to generate the bootloader certificate and application certificate key pairs for [Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).
2. Use the convert command with the Private Key (like sign_key.pem) from step 1 to sign an image file or certificate. Refer to [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) and [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) for more information about the Simplicity Commander signing process.

###### Using an HSM and Simplicity Commander (heading level 8)

1. You can use HSM to generate the ECDSA-P256 Sign Key pair. The Private Sign Key is securely held in HSM and the Public Sign Key can be exported in a specific format (like `sign_pubkey.pem`).  
   > **Note**: The same procedure can apply to generate the bootloader certificate and application certificate key pairs for [Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).
2. Use the `util keytotoken` command to convert the Public Sign Key from step 1 to token format (`sign_pubkey.txt`). The Simplicity Commander can program the Public Sign Key in token file (`sign_pubkey.txt`) to the [top page of the main flash](#signing-for-ecdsa-p256-sha256-secure-boot).  
   ```sh  
   commander util keytotoken sign_pubkey.pem --outfile sign_pubkey.txt  
   ```  
   ```sh  
   Writing EC tokens to sign_pubkey.txt...  
   DONE  
   ```
3. Use the `convert` command with `--extsign` option to prepare an unsigned image or certificate for HSM.
4. Use the Private Key from step 1 to generate a signature for the unsigned image or certificate from step 3.
5. Use the `convert` command with the signature from step 4 to generate a signed image or certificate. Refer to [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) and [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) for more information about the HSM and Simplicity Commander signing process.

> **Note**: The Simplicity Commander v1.11.0 or above supports signature in DER format. The older version of Simplicity Commander can only handle signatures in Raw format.

###### Provision Public Sign Key and Secure Boot Enabling

The Public Sign Key in SE OTP is used to verify the host image signature or certificate during Secure Boot. You should provision this key before setting the Secure Boot enabled flag in SE OTP. On HSE-SVH devices, when anti-tamper functionality is needed, you need to provision the [anti-tamper protection configuration](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/) with Secure Boot settings.

If you set the [SECURE_BOOT_ANTI_ROLLBACK](#simplicity-commander) option with Secure Boot, the SE will store the version counter (4 bytes) for anti-rollback of GBL (SSB) to SE flash and check the bootloader version during an upgrade and on every boot. The version counter will not roll to 0 if it reaches the maximum value (bootloader cannot be upgraded anymore). The anti-rollback does not prevent flashing an older signed GBL hex image to the device.

The following table describes the anti-rollback protection on signed GBL when `SECURE_BOOT_ANTI_ROLLBACK` is enabled or disabled.

- The GBL handles the anti-rollback protection when upgrading the GBL through the [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) (`.gbl`).
- The SE handles the anti-rollback protection (if `SECURE_BOOT_ANTI_ROLLBACK` enabled) when booting the image.

|**Action**|**SECURE_BOOT_ANTI_ROLLBACK Disable**|**SECURE_BOOT_ANTI_ROLLBACK Enable**|
|---|---|---|
|Use a GBL upgrade image (`.gbl`) file (e.g., OTA)|Gecko Bootloader rejects upgrade if an equal or lower GBL version is detected.|Gecko Bootloader rejects upgrade if an equal or lower GBL version is detected.|
|Flash and boot a firmware image (`.s32`, `.hex`, `.bin`) directly (e.g., Simplicity Commander)|SE accepts the image to flash and boot regardless of the firmware image version.|The SE accepts and boots the firmware image if its version is equal to or higher than the stored version. A lower version will be blocked at boot.|

> **Note**: [Series 2 devices only] The device needs to execute a mass erase (`commander device masserase` or `commander security erasedevice` then reset) before flashing a GBL hex image (`.s37`) to the device if [SECURE_BOOT_PAGE_LOCK_NARROW](#simplicity-commander) or [SECURE_BOOT_PAGE_LOCK_FULL](#simplicity-commander) option in SE OTP is enabled.

For simplicity, the [Secure Boot examples](#secure-boot) in this application note do not enable the following options for Secure Boot.

- `SECURE_BOOT_PAGE_LOCK_NARROW`
- `SECURE_BOOT_PAGE_LOCK_FULL`

> **Note**: `SECURE_BOOT_PAGE_LOCK_NARROW` and `SECURE_BOOT_PAGE_LOCK_FULL` are only available on Series 2 devices.

###### Simplicity Commander (heading level 7)

The following procedures assume the required files are in the same folder.

1. Follow the procedures in [Generate Key and Signing](#generate-key-and-signing) to generate the ECDSA-P256 Sign Key pair (`sign_key.pem` and `sign_pubkey.pem`) and Public Sign Key token file (`sign_pubkey.txt`).
2. Run the `security writekey` command to provision the Public Sign Key (`sign_pubkey.pem`) to the SE OTP slot. The Public Sign Key cannot be changed once written.  
   ```sh  
   commander security writekey --sign sign_pubkey.pem --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   Device has serial number 000000000000000014b457fffe045b21  
     
   ================================================================================  
   Please look through any warnings before proceeding.  
   THIS IS A ONE-TIME command, all code to be run on the device must be signed by this key.  
   Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   DONE  
   ```
3. Run the `security readkey` command to verify the Public Sign Key with the Public Sign Key in the token file (`sign_pubkey.txt`).  
   ```sh  
   commander security readkey --sign --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   C4AF4AC69AAB9512DB50F7A26AE5B4801183D85417E729A56DA974F4E08A562C  
   DE6019DEA9411332DC1A743372D170B436238A34597C410EA177024DE20FC819  
   DONE  
   ```
4. For Series 2 VSE devices (like EFR32MG22C224F512IM40), run the `flash` command to program the Public Sign Key in the token file (`sign_pubkey.txt`) to the top page of the main flash for [ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot). It is optional on Series 2 HSE and Series 3 devices.  
   ```sh  
   commander flash --tokengroup znet --tokenfile sign_pubkey.txt --device EFR32MG22C224F512IM40 --serialno 440048205  
   ```  
   ```sh  
   Writing 8192 bytes starting at address 0x0007e000  
   Comparing range 0x0007E000 - 0x0007FFFF (8 KiB)  
   Programming range 0x0007E000 - 0x0007FFFF (8 KiB)  
   DONE  
   ```  
   > **Note**: The MCU Series 2 devices (like EFM32PG22C200F512IM40) require Simplicity Commander Version 1.12.2 or above to support the `flash --tokengroup znet` command.
5. Run the `security genconfig` command to generate the `user_configuration.json` file for secure boot.  
   ```sh  
   commander security genconfig --nostore --outfile user_configuration.json --device EFR32MG21A010F1024  
   --serialno 440048205  
   DONE  
   ```  
   |**Name**|**Description**|  
   |---|---|  
   |SECURE_BOOT_ENABLE|If set, verifies the host image on the Cortex-M33 before releasing the Cortex-M33 from reset.|  
   |SECURE_BOOT_VERIFY_CERTIFICATE|If set, requires certificate-based signing of the host image.|  
   |SECURE_BOOT_ANTI_ROLLBACK|If set, prevents secure upgrading to a host image with an equal or lower version than the image that is currently stored in flash.|  
   |SECURE_BOOT_PAGE_LOCK_NARROW|If set, locks flash pages that have been validated by the Secure Boot process to prevent re-flashing by other means than through the SE. Write/erase locks pages from 0 through the page where the Secure Boot host image signature is located, not including the last page if the signature is not on a page boundary.|  
   |SECURE_BOOT_PAGE_LOCK_FULL|If set, locks flash pages that have been validated by the Secure Boot process to prevent re-flashing by other means than through the SE. Write/erase locks pages from 0 through the page where the Secure Boot host image signature is located, including the last page if the signature is not on a page boundary.|  
   > **Notes**: The host image is the firmware in the device's flash starting address. It is usually the GBL.  
   >   
   > SECURE_BOOT_PAGE_LOCK_NARROW and SECURE_BOOT_PAGE_LOCK_FULL are not available in Series 3 devices.
6. Use a text editor to modify the default secure boot settings to the desired configurations used in this application note.  
   ![Secure boot settings](/series2-secure-boot-with-rtsl/0.2/images/sld794-image26.jpg)  
   > **Note**: For devices prior to EFR32xG23, if `SECURE_BOOT_ENABLE` is set to false, the SE ignores the other four options regardless of their values, whereas on EFR32xG23 and future Series 2 devices, this configuration cannot be programmed to the SE OTP.
7. Follow the procedure in [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) to flash a bootloader image for signature based secure boot.  
   OR  
   Follow the procedure in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to flash a bootloader image for certificate based secure boot.
8. Run the `security writeconfig` command to program the secure boot configuration to the SE OTP. You can execute this command once per device.  
   ```sh  
   commander security writeconfig --configfile user_configuration.json --device EFR32MG21A010F1024  
   --serialno 440048205  
   ```  
   ```sh  
   ================================================================================  
     
   THIS IS A ONE-TIME configuration: Please inspect file before confirming: user_configuration.json  
   Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   DONE  
   ```
9. Run the `security readconfig` command to check the secure boot configuration of the device.  
   ```sh  
   commander security readconfig --serialno 440048205  
   ```  
   ![Secure Boot configuration](/series2-secure-boot-with-rtsl/0.2/images/sld794-image27.jpg)  
   > **Note**: Enabling Anti-rollback during development involves updating the firmware version every time you decide to flash a new image, this adds complexity. Therefore, it is recommended to enable Anti-rollback during production.

###### SE Manager Key Provisioning Platform Example (heading level 7)

1. Click the **View Project Documentation** link to open the readme file.  
   ![Key Provisioning Sample Application](/series2-secure-boot-with-rtsl/0.2/images/sld794-image28.jpg)
2. Modify the default Public Sign Key in `public_sign_key[PUB_KEY_SIZE]` array in `app_process.c` to the desired values.  
   ```sh  
   /// Public sign key  
   SL_ALIGN(4) static const uint8_t public_sign_key[PUB_KEY_SIZE] = {   
     0xc4, 0xaf, 0x4a, 0xc6, 0x9a, 0xab, 0x95, 0x12,  
   0xdb, 0x50, 0xf7, 0xa2, 0x6a, 0xe5, 0xb4, 0x80,   
   0x11, 0x83, 0xd8, 0x54, 0x17, 0xe7, 0x29, 0xa5,  
   0x6d, 0xa9, 0x74, 0xf4, 0xe0, 0x8a, 0x56, 0x2c,  
   0xde, 0x60, 0x19, 0xde, 0xa9, 0x41, 0x13, 0x32,  
   0xdc, 0x1a, 0x74, 0x33, 0x72, 0xd1, 0x70, 0xb4,  
   0x36, 0x23, 0x8a, 0x34, 0x59, 0x7c, 0x41, 0x0e,  
   0xa1, 0x77, 0x02, 0x4d, 0xe2, 0x0f, 0xc8, 0x19  
   };  
   ```
3. Modify the default secure boot settings in `init_se_otp_conf()` function in `app_se_manager_key_provisioning.c` to the desired configuration.  
   ```sh  
   // Overwrite secure boot options in SL_SE_OTP_INIT_DEFAULT if necessary.  
   otp_init.enable_secure_boot = true;  
   otp_init.verify_secure_boot_certificate = false;  
   otp_init.enable_anti_rollback = true;  
   otp_init.secure_boot_page_lock_narrow = false;  
   otp_init.secure_boot_page_lock_full = false;  
   ```  
   > **Note**: If `enable_secure_boot` is false, the SE will ignore the other four options regardless of whether they are true or false. The EFR32xG23 and higher Series 2 devices do not allow this setting to program to the SE OTP.
4. Follow the procedures in [Generate an Unsigned Application Image](#generate-an-unsigned-application-image) to generate the unsigned application image if the GBL is present in the device.
5. Build the project and run the application. Follow the procedures in [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) if a signed application image is required.
6. Then press **SPACE** to skip the programming of the AES-128 key (HSE devices only). Optional to press **ENTER** to program the hard-coded [GBL Decryption Key](#se-manager-key-provisioning-platform-example-2) to HSE OTP.  
   ```sh  
   SE Manager Key Provisioning Example - Core running at 38000 kHz.  
   . SE manager initialization... SL_STATUS_OK (cycles: 9 time: 0 us)  
     
   . Get current SE firmware version... SL_STATUS_OK (cycles: 3578 time: 94 us)  
   + Current SE firmware version (MSB..LSB): 00010209  
     
   . Read SE OTP configuration... SL_STATUS_COMMAND_IS_INVALID (cycles: 3908 time: 102 us)  
     
   . Press ENTER to program 128-bit AES key in SE OTP or press SPACE to skip.  
     
   . Encrypt 16 bytes plaintext with 128-bit AES OTP key... SL_STATUS_FAIL (cycles: 4627 time: 121 us)  
     
   . Press ENTER to program public sign key in SE OTP or press SPACE to skip.  
   ```
7. Press **ENTER** to program the hard-coded Public Sign Key to SE OTP.  
   ```sh  
   + Warning: The public sign key in SE OTP cannot be changed once written!  
   + Press ENTER to confirm or press SPACE to skip if you are not sure.  
   ```
8. Press **ENTER** to confirm the operation. The SE returns `SL_STATUS_INVALID_PARAMETER` if the Public Sign Key is present in SE OTP.  
   ```sh  
   . Initialize public sign key... SL_STATUS_OK (cycles: 56052 time: 1475 us)  
     
   . Get public sign key... SL_STATUS_OK (cycles: 8450 time: 222 us)  
   + The public sign key (64 bytes):  
   C4 AF 4A C6 9A AB 95 12 DB 50 F7 A2 6A E5 B4 80  
   11 83 D8 54 17 E7 29 A5 6D A9 74 F4 E0 8A 56 2C  
   DE 60 19 DE A9 41 13 32 DC 1A 74 33 72 D1 70 B4  
   36 23 8A 34 59 7C 41 0E A1 77 02 4D E2 0F C8 19  
     
   . Press ENTER to program public command key in SE OTP or press SPACE to skip.  
   ```  
   ```sh  
   . Initialize public sign key... SL_STATUS_INVALID_PARAMETER (cycles: 4375 time: 115 us)  
     
   . Get public sign key... SL_STATUS_OK (cycles: 8435 time: 221 us)  
   + The public sign key (64 bytes):  
   C4 AF 4A C6 9A AB 95 12 DB 50 F7 A2 6A E5 B4 80  
   11 83 D8 54 17 E7 29 A5 6D A9 74 F4 E0 8A 56 2C  
   DE 60 19 DE A9 41 13 32 DC 1A 74 33 72 D1 70 B4  
   36 23 8A 34 59 7C 41 0E A1 77 02 4D E2 0F C8 19  
     
   . Press ENTER to program public command key in SE OTP or press SPACE to skip.  
   ```
9. Press **SPACE** to skip the programming of the Public Command Key. Optional to press **ENTER** to program the hard-coded Public Command Key to SE OTP.  
   ```sh  
   . Get public command key... SL_STATUS_FAIL (cycles: 4126 time: 108 us)  
     
   . Press ENTER to initialize SE OTP for secure boot configuration or press SPACE to skip.  
   ```
10. Press **ENTER** to program the secure boot configuration.  
    ```sh  
    + Warning: The SE OTP configuration cannot be changed once written!  
    + Press ENTER to confirm or press SPACE to skip if you are not sure.  
    ```
11. Press **ENTER** to confirm the operation. The SE returns `SL_STATUS_COMMAND_IS_INVALID` if an invalid setting from step 2 or the secure boot configuration has been programmed in SE OTP.  
    ```sh  
    . Initialize SE OTP... SL_STATUS_OK (cycles: 267256 time: 7033 us)  
    + Read SE OTP configuration... SL_STATUS_OK (cycles: 6865 time: 180 us)  
    + Secure boot	                 : Enabled  
    + Secure boot verify certificate : Disabled  
    + Secure boot anti-rollback	     : Enabled  
    + Secure boot page lock narrow	 : Disabled  
    + Secure boot page lock full	 : Disabled  
      
    . SE manager deinitialization... SL_STATUS_OK (cycles: 5 time: 0 us)  
    ```  
    ```sh  
    . Initialize SE OTP... SL_STATUS_COMMAND_IS_INVALID (cycles: 3989 time: 104 us)  
      
    . SE manager deinitialization... SL_STATUS_OK (cycles: 5 time: 0 us)  
    ```

###### Simplicity Studio (heading level 7)

The security operations are performed in the Security Settings of Simplicity Studio. This application note uses Simplicity Studio v5.2.3.1. The procedures and pictures may be different for the other versions of Simplicity Studio 5.

1. Right-click the selected debug adapter **RB (ID:J-Link serial number)** to display the context menu.  
   ![Debug Adapters Context Menu](/series2-secure-boot-with-rtsl/0.2/images/sld794-image29.jpg)
2. Click **Device configuration...** to open the **Configuration of device: J-Link Silicon Labs (serial number)** dialog box. Click the **Security Settings** tab to get the selected device configuration.  
   ![Configuration on Selected Device](/series2-secure-boot-with-rtsl/0.2/images/sld794-image30.png)
3. Click [**Start Provisioning Wizard…**] in the upper right corner to display the **Secure Initialization** dialog box. Checking the **Enable Version Rollback Prevention of Host Image** option is recommended. The **Verify intermediate certificate before secure boot** option is for [Certificate-based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ![Secure Initialization Dialog Box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image31.png)  
   > **Note**: The [SECURE_BOOT_PAGE_LOCK_NARROW and SECURE_BOOT_PAGE_LOCK_FULL](#simplicity-commander) options are not yet available in Simplicity Studio.
4. Click [**Next >**]. The **Security Keys** dialog box is displayed.  
   ![Security Keys Dialog Box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image32.png)
5. Checking the **Enable Writing Sign Key** checkbox will automatically enable Secure Boot. The following **Secure Boot Warning** is displayed. Click [**Yes**] to confirm.  
   ![Secure Boot Warning](/series2-secure-boot-with-rtsl/0.2/images/sld794-image33.png)
6. Open the [Public Sign Key](#generate-key-and-signing) token file (`sign_pubkey.txt`).  
   ```sh  
   MFG_SIGNED_BOOTLOADER_KEY_X : 997011ED1708580BD4A6B7F8AD6EE19B0B8722611FB76A3A5702D5141180E101  
   MFG_SIGNED_BOOTLOADER_KEY_Y : 0AC8673C8ACC26EE2B534C004F4A4B7EBBC23D04506DD66E3EF0DDC81E3CA55E  
   ```
7. Copy Public Sign Key (X-point `9970...` first, then Y-point `0AC8...`) to **Key:** box under **Sign Key:**.  
   ![Enter Public Sign Key](/series2-secure-boot-with-rtsl/0.2/images/sld794-image34.jpg)
8. Click [**Next >**]. The **Secure Locks** dialog box is displayed. When Secure Boot is enabled, the **Debug Locks** are not set by default. Refer to [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) for more information about these locks.  
   ![Security Locks Dialog Box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image35.png)
9. Click [**Next >**] to display the **Summary** dialog box.  
   ![Summary Dialog Box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image36.jpg)
10. If the information displayed is correct, click [**Provision**]. Click [**Yes**] to confirm. The Public Sign Key and Secure Boot configuration cannot be changed once written.

![One Time Device Provisioning Window](/series2-secure-boot-with-rtsl/0.2/images/sld794-image37.jpg)

1. The **Summary** dialog box displays the **Provisioning Status**.

![Provisioning Status](/series2-secure-boot-with-rtsl/0.2/images/sld794-image38.jpg)

1. Click [**Done**] to exit the provisioning process. The device configuration is updated.

###### Provision GBL Decryption Key

The GBL Decryption Key is used to decrypt the [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) payloads during firmware upgrade. You should provision this key before enabling the **Require encrypted firmware upgrade files** option in AppBuilder plugin and [3.4.1.2 Bootloader-core Software Component](#bootloader-core-software-component).

The following figures and table show the available options, two for VSE and three for HSE, for selecting the GBL Decryption Key used to decrypt the GBL upgrade image (bootloader, SE, or application).

![App Builder Options](/series2-secure-boot-with-rtsl/0.2/images/sld794-image39.jpg)

![Bootloader Software Component Options](/series2-secure-boot-with-rtsl/0.2/images/sld794-image40.jpg)

|**Option for GBL Decryption Key Selection**|**GBL Decryption Key Storage**|
|---|---|
|1. Use symmetric key stored in Secure Element storage (HSE devices only and GSDK ≥ v3.0).|The 128-bit symmetric key stored in HSE OTP is used for GBL upgrade image file decryption.|
|2. Use symmetric key stored in Application Properties Struct (GSDK ≥ v4.1).|The 128-bit symmetric key stored in the GBL Application Properties Struct is used for GBL upgrade image file decryption. The key is stored in the Secure flash if TrustZone is implemented.|
|3. Default storage if none of the above options are selected.|The 128-bit symmetric key stored on the top page of the main flash is used for GBL upgrade image file decryption. The key is stored in the Non-secure flash if TrustZone is implemented.|

**Note**:

- Option 2 requires `ApplicationProperties_t` struct v1.2 or higher (defined in `application_properties.h` in the Windows folder `C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\platform\bootloader\api`) in GSDK v4.1 or higher to store the GBL Decryption Key.

```c
/// Major version number of the ApplicationProperties_t struct #define APPLICATION_PROPERTIES_VERSION_MAJOR (1UL)
/// Minor version number of the ApplicationProperties_t struct #define APPLICATION_PROPERTIES_VERSION_MINOR (2UL)
```

```sh
/// Application Properties struct typedef struct {
/// @brief Magic value indicating this is an ApplicationProperties_t struct.
/// Must equal @ref APPLICATION_PROPERTIES_MAGIC uint8_t magic[16];
/// Version number of this struct uint32_t structVersion;
/// Type of signature this application is signed with uint32_t signatureType;
/// Location of the signature. Typically points to the end of the application uint32_t signatureLocation;
/// Information about the application ApplicationData_t app;
/// Pointer to information about the certificate ApplicationCertificate_t *cert;
/// Pointer to Long Token Data Section uint8_t *longTokenSectionAddress;
/// Parser Decryption Key const uint8_t decryptKey[16];
} ApplicationProperties_t;
```

- Option 2 must be implemented before signing the GBL image for [ECDSA-P256-SHA256](#signing-for-ecdsa-p256-sha256-secure-boot) or [certificate-based](#signing-for-certificate-based-secure-boot) Secure Boot.
- The options for the GBL Decryption Key are mutually exclusive. Either one of the two (VSE) or three (HSE) key storages will be selected for decryption.
- From a security point of view, it is highly recommended to use or upgrade to option 1 for HSE devices and option 2 for VSE devices.
- If the GBL Decryption Key in the selected option is compromised, the simple way is to upgrade the GBL to option 2 (if the existing option is 1 or 3) with the new GBL Decryption Key.

###### Simplicity Commander (heading level 7)

The following procedures describe how to program the GBL Decryption Key for the options below. All procedures assume the required files are in the same folder.

- Use symmetric key stored in Secure Element storage (HSE devices only and GSDK ≥ v3.0)
- Use symmetric key stored in Application Properties Struct (GSDK ≥ v4.1)
- Default Storage on the Top Page of the Main Flash

1. Generate a 128-bit Symmetric Key.  
   Run the `util genkey` command to generate the token file for the GBL Decryption Key.  
   ```sh  
   commander util genkey --type aes-ccm --outfile aes_key.txt  
   ```  
   ```sh  
   Using Windows' Cryptographic random number generator  
   DONE  
   ```
2. (**Use symmetric key stored in Secure Element storage**) Run the `security writekey` command to provision the GBL Decryption Key to the SE OTP slot. The GBL Decryption Key cannot be changed once written.  
   ```sh  
   commander security writekey --decrypt aes_key.txt --device EFR32MG21A010F1024 --serialno 440030580  
   ```  
   ```sh  
   Device has serial number 0000000000000000000d6ffffead3d94  
     
   ================================================================================  
   Please look through any warnings before proceeding.  
   THIS IS A ONE-TIME command, any encrypting of GBL files must be done with this key.  
   Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   DONE  
   ```  
   > **Note**: It cannot read back the GBL Decryption Key from the HSE OTP.
3. (**Use symmetric key stored in Application Properties Struct**) Run the `convert` command to program the GBL Decryption Key to the `Application Properties Struct` of the GBL.  
   ```sh  
   commander convert bootloader-uart-xmodem.s37 --aeskey aes_key.txt --outfile bootloader-uart-xmodem.s37  
   ```  
   ```sh  
   Parsing file bootloader-uart-xmodem.s37...  
   Writing to bootloader-uart-xmodem.s37...  
   Overwriting file: bootloader-uart-xmodem.s37...  
   DONE  
   ```  
   **Notes**:  
   - The `--aeskey` option in the `convert` command requires **Simplicity Commander v1.12.3 or above**.  
   - The GBL Decryption Key can only be added to the GBL with `Application Properties Struct` v1.2 or higher.
4. (**Default Storage on the Top Page of the Main Flash**) Run the `flash` command to program the GBL Decryption Key in the token file to the top page of the main flash.  
   ```sh  
   commander flash --tokengroup znet --tokenfile aes_key.txt --device EFR32MG21A010F1024 --serialno 440030580  
   ```  
   ```sh  
   Writing 8192 bytes starting at address 0x000fe000  
   Comparing range 0x000FE000 - 0x000FFFFF (8 KB)  
   Programming range 0x000FE000 - 0x000FFFFF (8 KB)  
   DONE  
   ```  
   > **Note**: The MCU Series 2 VSE devices (like EFM32PG22C200F512IM40) require Simplicity Commander Version 1.12.2 or above to support the flash --tokengroup znet command.

###### SE Manager Key Provisioning Platform Example (heading level 7)

This example only applies to [option 1](#provision-gbl-decryption-key) for Series 2 and Series 3 HSE devices. Click the **View Project Documentation** link to open the readme file.

![Key Provisioning Sample Application](/series2-secure-boot-with-rtsl/0.2/images/sld794-image28.jpg)

1. Modify the default GBL Decryption Key in the `aes_key[16]` array in `app_process.c` to the desired values.  
   ```sh  
   /// 128-bit AES key  
   SL_ALIGN(4) static const uint8_t aes_key[16] = {   
   0x81, 0xa5, 0xe2, 0x1f, 0xa1, 0x52, 0x86, 0xf1,   
   0xdf, 0x44, 0x5c, 0x2c, 0xc1, 0x20, 0xfa, 0x3f  
   };  
   ```
2. Modify the `ciphertext[16]` array in `app_process.c` to the expected ciphertext for AES ECB on 16 bytes zero plaintext to verify the GBL Decryption Key in step 1.  
   ```sh  
   /// Ciphertext to verify 128-bit AES key static const uint8_t ciphertext[16] = {  
   0x66, 0xd2, 0x0f, 0x99, 0x65, 0x3e, 0xa8, 0xd0, 0x83, 0x05, 0xa6, 0x39, 0xd4, 0x4e, 0x98, 0xa6  
   };  
   ```
3. Follow the procedures in [Generate an Unsigned Application Image](#generate-an-unsigned-application-image) to generate the unsigned application image if the GBL is present in the device.
4. Build the project and run the application. Follow the procedures in [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) if a signed application image is required.
5. Then press ENTER to program the hard-coded GBL Decryption Key to HSE OTP.  
   ```sh  
   SE Manager Key Provisioning Example - Core running at 38000 kHz.  
   . SE manager initialization... SL_STATUS_OK (cycles: 9 time: 0 us)  
     
   . Get current SE firmware version... SL_STATUS_OK (cycles: 3578 time: 94 us)  
   + Current SE firmware version (MSB..LSB): 00010209  
     
   . Read SE OTP configuration... SL_STATUS_COMMAND_IS_INVALID (cycles: 3908 time: 102 us)  
     
   . Press ENTER to program 128-bit AES key in SE OTP or press SPACE to skip.  
   + Warning: The 128-bit AES key in SE OTP cannot be changed once written!  
   + Press ENTER to confirm or press SPACE to skip if you are not sure.  
   ```
6. Press **ENTER** to confirm the operation. The program either returns `SL_STATUS_OK` or `SL_STATUS_INVALID_PARAMETER` (already present) and performs AES ECB encryption to verify the GBL Decryption Key in HSE OTP.  
   ```sh  
   . Initialize 128-bit AES key... SL_STATUS_OK (cycles: 39059 time: 1027 us)  
     
   . Encrypt 16 bytes plaintext with 128-bit AES OTP key... SL_STATUS_OK (cycles: 11013 time: 289 us)  
   + Compare encrypted message with expected ciphertext... OK  
     
   . Press ENTER to program public sign key in SE OTP or press SPACE to skip.  
   ```  
   ```sh  
   . Initialize 128-bit AES key... SL_STATUS_INVALID_PARAMETER (cycles: 4474 time: 117 us)  
     
   . Encrypt 16 bytes plaintext with 128-bit AES OTP key... SL_STATUS_OK (cycles: 11001 time: 289 us)  
   + Compare encrypted message with expected ciphertext... OK  
     
   . Press ENTER to program public sign key in SE OTP or press SPACE to skip.  
   ```
7. Press **SPACE** to skip the programming of the Public Sign Key.  
   ```sh  
   . Get public sign key... SL_STATUS_FAIL (cycles: 4126 time: 108 us)  
     
   . Press ENTER to program public command key in SE OTP or press SPACE to skip.  
   ```
8. Press **SPACE** to skip the programming of the Public Command Key.  
   ```sh  
   . Get public command key... SL_STATUS_FAIL (cycles: 4126 time: 108 us)  
     
   . Press ENTER to initialize SE OTP for secure boot configuration or press SPACE to skip.  
   ```
9. Press **SPACE** to skip the programming of the secure boot configuration.  
   ```sh  
   . SE manager deinitialization... SL_STATUS_OK (cycles: 10 time: 0 us)  
   ```

###### Secure Boot

You should usually not enable Secure Boot during the development phase to avoid a clash on [debugging](04-debugging-on-secure-boot-enabled-device#debugging-on-secure-boot-enabled-device). The Secure Boot feature is enabled near firmware release and uses the following sections to validate the configuration and system functionality.

###### Generate an Unsigned GBL Image (heading level 7)

There are two ways to configure the application firmware through a GBL project.

1. Use [AppBuilder](#appbuilder) (`.isc file`) in **GSDK v3.2 and lower**.
2. Use [Bootloader-core software component](#bootloader-core-software-component) (`.slcp` file) in **GSDK v4.0 and higher**, and **SiSDK v2024.6.0 and higher**.

The following notes apply to the AppBuilder and Bootloader-core software component.

- Enabling the **Allow use of public key from manufacturing token storage** option is mandatory on VSE devices (cannot be disabled in AppBuilder and is discarded in Bootloader-core software component) for [ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot).
- The HSE device ignores this default enabled option if the Public Sign Key has been provisioned in OTP.
- When the **Enable application rollback protection** option (GSDK ≥ v3.0) is enabled, the GBL stores an application version counter at the end of the bootloader space in flash. The GBL checks this version during upgrades and at every boot, but it does not prevent flashing an older image onto the device.
- The **Minimum application version allowed** option (GSDK ≥ v3.0) sets the lowest application version that can boot. This option maintains the version counter, which resets to 0 after upgrading the GBL.
- The **Enable application rollback protection** option is not applicable if the [SECURE_BOOT_PAGE_LOCK_FULL](#simplicity-commander) in SE OTP is enabled. See section "_Secure Boot with Application Rollback Protection_" in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf) (for GSDK v3.2 and lower), [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/), or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/) for details about the application rollback protection.
- The GBL size and starting address are device-dependent. For more information about the bootloader size and starting address on Series 2, see section "Memory Space For Bootloading" in [UG103.6: Bootloader Fundamentals](https://www.silabs.com/documents/public/user-guides/ug103-06-fundamentals-bootloading.pdf).

Refer to [Generate a GBL Upgrade Image File](#generate-a-gbl-upgrade-image-file) to create GBL upgrade image file for the **Require signed firmware upgrade files** and **Require encrypted firmware upgrade files** options. For simplicity, the Secure Boot examples in this application note do not enable these options. Refer to [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf), [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/), or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/) for information about these options.

The following sections describe how to build the unsigned GBL image from the **UART XMODEM Bootloader** (GSDK < v4.1) or **Bootloader - NCP UART XMODEM** (GSDK ≥ v4.1).

![Bootloader options](/series2-secure-boot-with-rtsl/0.2/images/sld794-image41.jpg)

###### AppBuilder (heading level 8)

This application note uses UART XMODEM Bootloader example v1.12.0 in GSDK v3.2.3. The procedures and pictures may be different for the other versions of this example.

1. Create a UART XMODEM Bootloader project.
2. The **Plugins** tab in AppBuilder (bootloader-uart-xmodem.isc) shows the default configurations for the UART XMODEM Bootloader example.
3. Use **Bootloader Core, provides API: core** in the **Plugins** tab to set up the application firmware configurations.  
   a. This application note uses the configuration below for [ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot).  
   ```c  
   ![ECDSA-P256-SHA256 Secure Boot configuration](./resources/sld794-image42.jpeg)  
   ```  
   b. This application note uses the configuration below for [Certificate-based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
   ![Certificate-based Secure Boot configuration](./resources/sld794-image43.jpeg)  
   ```
4. Enter a higher version number (default is 0) to the macro **BOOTLOADER_VERSION_MAIN_CUSTOMER** → **Value** in the **Additional Macros** field on the **Other** tab for [anti-rollback protection](#provision-public-sign-key-and-secure-boot-enabling) of GBL.  
   ![Bootloader version macro](/series2-secure-boot-with-rtsl/0.2/images/sld794-image44.png)
5. The default setting of GBL will overwrite the existing application image when upgrading the GBL or SE. It forces to update the application image even without changes on the firmware. Use the AppBuilder settings below to keep the existing application image when upgrading the GBL or SE.  
   a. Enter the required application image size to the macro **BTL_APP_SPACE_SIZE** → **Value** in the **Additional Macros** field on the **Other** tab. Check the **-D?** checkbox to add this definition to the project.  
   ```c  
    This application note uses 507904 (496 kB) to replace the default value of ((FLASH_BASE + FLASH_SIZE) - BTL_APPLICATION_BASE).  
     
    ![Bootloader application size macro](./resources/sld794-image45.jpeg)  
   ```  
   b. The **Base address of bootloader upgrade image** ≥ (**BTL_APP_SPACE_SIZE** + size of the GBL). The example in this application note uses EFR32MG21A010F1024:  
   ```c  
    Base address of bootloader upgrade image = 507904 (496 kB) + 16384 (16 kB for GBL) = 524288 (512 kB)  
     
    ![Base address of bootlader upgrade image](./resources/sld794-image46.png)  
     
    > **Note**: The default value of Base address of bootloader upgrade image is 32768 (32 kB).  
   ```  
   c. The (**Base address of bootloader upgrade image** + size of the GBL or SE + upgrade file overhead) ≤ the available size of the device main flash for application use (see project linker file for details).  
   ```c  
    The example in this application note uses EFR32MG21A010F1024:  
     
    512 kB (Base address of bootloader upgrade image) + 16 kB (GBL) or 48 kB (SE) + overhead bytes \< 1024 kB (size of main flash)  
     
    For more information about the size of the GBL and SE, see section *Storage Space Size Configuration* in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf).  
     
    > **Note**: It requires GBL v1.11.0 or above to support this feature.  
   ```
6. Click [**Generate**] in the right upper corner.
7. In the **Generation Successful** dialog, click [**OK**].
8. Build the project to generate the unsigned GBL image file (`bootloader-uart-xmodem.s37`).
9. **(Optional)** Run the `util appinfo` command to check all available information (application properties) in an unsigned GBL image. The `App version` is the GBL version for the [SECURE_BOOT_ANTI_ROLLBACK](#simplicity-commander) option.

```sh
commander util appinfo bootloader-uart-xmodem.s37
```

```sh
Parsing file bootloader-uart-xmodem.s37...
Found application properties in image.
Application properties info:
Application properties location : 0x00002b1c
Signature location	            : 0x00002d08
Signature type	                : No signature
Long token section address	    : Not set (0x00000000)

Application data info:
For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.
App type	                    : Bootloader (APPLICATION_TYPE_BOOTLOADER)
App version	                    : 0x010c0000
Product ID	                    : Not set (0x00000000000000000000000000000000)

No certificate found in image.
For Series 2 devices: If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.
DONE
```

###### Bootloader-core Software Component (heading level 8)

This application note uses UART XMODEM Bootloader example v2.0.0 in GSDK v4.0. The procedures and pictures may be different for the other versions of this example.

1. Create a UART XMODEM Bootloader project.
2. Checking the **Installed Components** under the **SOFTWARE COMPONENTS** tab shows the list of installed components (`bootloader-uart-xmodem.slcp`) in the UART XMODEM Bootloader example.
3. Click [**Configure**] in the **Bootloader-core** component to open the **Bootloader Core Configuration**.  
   ![Bootloader-core component](/series2-secure-boot-with-rtsl/0.2/images/sld794-image47.jpg)  
   > **Note:** Install "Bootloader Core (Series-3)" for series 3 devices.
4. Use **Bootloader Core Configuration** in **Bootloader-core** to set up the application firmware configurations.
5. This application note uses the configuration below for [ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot).  
   ![Bootloader Core configuration for ECDSA-P256-SHA256 Secure Boot](/series2-secure-boot-with-rtsl/0.2/images/sld794-image48.png)
6. This application note uses the configuration below for [Certificate-based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ![Bootloader Core configuration for Certificate-based Secure Boot](/series2-secure-boot-with-rtsl/0.2/images/sld794-image49.png)
7. [For series 2 devices only] Enter a higher version number (default is 0) to **BOOTLOADER VERSION MAIN CUSTOMER** for [anti-rollback protection](#provision-public-sign-key-and-secure-boot-enabling) of GBL.  
   ![screenshot](/series2-secure-boot-with-rtsl/0.2/images/sld794-image50.jpg)
8. [For series 2 devices only] The default setting of GBL will overwrite the existing application image when upgrading the GBL or SE. It forces to update the application image even without changes on the firmware. Use the Bootloader-core settings below to keep the existing application image when upgrading the GBL or SE.  
   a. Enter the required application image size to the **Enter Bootloader App Space Size** dialog box after enabling the **Use custom Bootloader Application Size** option.  
   ```c  
    This application note uses 507904 (496 kB) to replace the default value of 0.  
     
    ![screenshot](./resources/sld794-image51.jpeg)  
   ```  
   b. The **Base address of bootloader upgrade image** ≥ (**Enter Bootloader App Space Size** + size of the GBL). The example in this application note uses EFR32MG21A010F1024:  
   ```c  
    Base address of bootloader upgrade image = 507904 (496 kB) + 16384 (16 kB for GBL) = 524288 or 0x80000 (512 kB)  
     
    ![screenshot](./resources/sld794-image52.png)  
     
    > **Note**: The default value of Base address of bootloader upgrade image is 32768 or 0x8000 (32 kB).  
   ```  
   c. The (**Base address of bootloader upgrade image** + size of the GBL or SE + upgrade file overhead) ≤ the available size of the device main flash for application use (see project linker file for details).  
   ```c  
    The example in this application note uses EFR32MG21A010F1024:  
     
    512 kB (Base address of bootloader upgrade image) + 16 kB (GBL) or 48 kB (SE) + overhead bytes \< 1024 kB (size of main flash)  
     
    For more information about the size of the GBL and SE, see section *Storage Space Size Configuration* in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).  
   ```
9. Click [**X**] in the right upper corner to exit the **Bootloader Core Configuration**.
10. Build the project to generate the unsigned GBL image file (bootloader-uart-xmodem.s37).
11. **(Optional)** Run the `convert` command to program the GBL Decryption Key to the Application Properties Struct if this [GBL Decryption Key option](#provision-gbl-decryption-key) in GBL (GSDK ≥ v4.1) is selected.

```sh
commander convert bootloader-uart-xmodem.s37 --aeskey aes_key.txt --outfile bootloader-uart-xmodem.s37
```

```sh
Parsing file bootloader-uart-xmodem.s37...
Writing to bootloader-uart-xmodem.s37...
Overwriting file: bootloader-uart-xmodem.s37...
DONE
```

1. **(Optional)** Run the `util appinfo` command to check all available information (application properties) in an unsigned GBL image. The App version is the GBL version for the [SECURE_BOOT_ANTI_ROLLBACK](#simplicity-commander) option.

```sh
commander util appinfo bootloader-uart-xmodem.s37
```

```sh
Parsing file bootloader-uart-xmodem.s37...
Found application properties in image.
Application properties info:
Application properties location : 0x00002b30
Signature location	            : 0x00002c44
Signature type	                : No signature
Long token section address	    : Not set (0x00000000)

Application data info:
For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.
App type	                    : Bootloader (APPLICATION_TYPE_BOOTLOADER)
App version	                    : 0x02000000
Product ID	                    : Not set (0x00000000000000000000000000000000)

No certificate found in image.
For Series 2 devices: If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.
DONE
```

> **Note**: For TrustZone-aware bootloaders, the unsigned GBL image is the combined image of Secure and Non-secure bootloaders. The **Bootloader-core** component is installed in the Secure bootloader.

###### Generate an Unsigned Application Image (heading level 7)

This section describes how to generate an unsigned application image for the GBL.

1. For Series 2 devices, the application image should be placed on the main flash page after the GBL. For more information about the application starting address, see section _Memory Space For Bootloading_ in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).
2. For Series 3 devices, the application image should be placed in the code region 1 next to the bootloader which is in region 0, see section _External Flash Architecture in Series 3 Devices_ in [Platform Memory Model](https://docs.silabs.com/gecko-platform/latest/platform-memory-model/).
3. **(Simplicity Studio 5)** You can use the **Bootloader Application Interface** component to set up the start address of the application image. This application note uses **Platform - Blink Bare-metal** example in GSDK v3.2.3. The procedures and pictures may be different on other versions of the GSDK. The following steps can apply to other platform examples in GSDK and SiSDK.  
   a. Create a **Platform - Blink Bare-metal** project.  
   b. The **Software Components** tab shows the list of available components (`blink_baremetal.slcp`) that you can install in the project.  
   c. Select **Platform > Bootloader > Bootloader Application Interface**.  
   d. Click [**Install**].  
   ![Bootloader Application Interface](/series2-secure-boot-with-rtsl/0.2/images/sld794-image53.jpg)  
   > **Note**: For the wireless protocol stack example, the Bootloader Application Interface component is already present in the project.
4. The application image should contain an `ApplicationProperties_t` struct (defined in `application_properties.h` in the Windows folder below) declaring the application version, capabilities, and other metadata.  
   For GSDK v3.2 and lower: `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION>\platform\bootloader\api`  
   For SiSDK v2024.6.0 and higher, or GSDK v4.0 and higher: `C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\platform\bootloader\api`  
   Below is an example source file `app_properties.c` with `ApplicationProperties_t` struct for Secure Boot on GSDK v3.2 and lower.  
   ```sh  
   #include <stddef.h>  
   #include "application_properties.h"  
     
   const ApplicationProperties_t sl_app_properties = {  
   .magic = APPLICATION_PROPERTIES_MAGIC,  
   .structVersion = APPLICATION_PROPERTIES_VERSION,  
   .signatureType = APPLICATION_SIGNATURE_NONE,  
   .signatureLocation = 0,  
   .app = {  
       .type = APPLICATION_TYPE_MCU,  
       .version = 1UL,  
       .capabilities = 0UL,  
       .productId = {0U},  
   },  
   };  
   ```  
   The `signatureType` and `signatureLocation` are filled by Simplicity Commander when signing the application image using the `convert` command.
5. The following table describes how to add the `app_properties.c` file in step 4 to **Platform - Blink Bare-metal** project. For the wireless protocol stack example, the `app_properties.c` file with `ApplicationProperties_t` struct is already present in the project.  
   **App properties for older Simplicity Studio and GSDK versions**  
   |**Simplicity Studio 4 & Simplicity Studio 5 with GSDK v3.2 and lower**|**Simplicity Studio 5 with GSDK v4.0 and higher**|  
   |---|---|  
   |Manually added|Automatically added after installing the Bootloader Application Interface component in step 3 to the project.|  
   > **Note**: Refer to the [Knowledge Article](https://community.silabs.com/s/article/what-are-the-steps-to-add-application-properties-to-a-application-project-x?language=en_US) in Silicon Labs Community to add `app_properties.c` to the project in Simplicity Studio 4.
6. **(Simplicity Studio 4 & Simplicity Studio 5 with GSDK v3.2 and lower)** Enter a higher version number to `.version` in `app_properties.c` for [anti-rollback protection](#generate-an-unsigned-gbl-image) (if enabled) of the application.
7. **(Simplicity Studio 5 with GSDK v4.0 and higher)** Click [**Configure**] in the **App Properties** component under **Platform** > **Bootloader** to open the **App Properties** configuration. The example below uses GSDK v4.0. The procedures and pictures may be different on other versions of the GSDK.  
   ![App Properties component](/series2-secure-boot-with-rtsl/0.2/images/sld794-image54.jpg)
8. Enter a higher version number to **Version number for this application** dialog box in **App Properties settings** for [anti-rollback protection](#generate-an-unsigned-gbl-image) (if enabled) of the application.  
   ![App properties version number dialog box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image55.png)  
   > **Note**: The `app_properties.c` is in the Windows folder below.  
   >   
   > `C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\platform\bootloader\app_properties`
9. Build the project to generate the unsigned application image file (`blink_baremetal.s37`).
10. **(Optional)** Run the `util appinfo` command to check all available information about `ApplicationProperties_t` struct in an un-signed application image. The App version is for the **Enable application rollback protection** option in the [AppBuilder](#appbuilder or [Bootloader-core software component](#bootloader-core-software-component).

```sh
commander util appinfo blink_baremetal.s37
```

```sh
Parsing file blink_baremetal.s37...
Found application properties in image. Application properties info:
Application properties location : 0x00006198
Signature location	            : Not set (0x00000000)
Signature type	                : No signature
Long token section address	    : Not set (0x00000000)

Application data info:
For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.
App type	                    : MCU application (APPLICATION_TYPE_MCU)
App version	                    : 0x00000001
Product ID	                    : Not set (0x00000000000000000000000000000000)

No certificate found in image.
For Series 2 devices: If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.
DONE
```

**Note:** For the TrustZone-aware applications, the unsigned application image is the combined image of Secure and Non-secure applications. The `ApplicationProperties_t` struct is located in the Secure application.

###### Signing for ECDSA-P256-SHA256 Secure Boot (heading level 7)

The following figure describes the signing and verification for ECDSA-P256-SHA256 Secure Boot.

![ECDSA-P256-SHA256 Sign and Verify](/series2-secure-boot-with-rtsl/0.2/images/sld794-ecdsa-p256-sha256-sign-verify.png)

> **Note**: The bootloader cannot access the Public Sign Key in VSE OTP to verify the application image. Therefore VSE devices need to store a [Public Sign Key copy](#simplicity-commander) on the top page of the main flash (see section _Key Storage_ in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/)).

**Public Sign Key usage for VSE and HSE Devices**

|**Device**|**FSB to Verify the Bootloader Image**|**SSB to Verify the Application Image**|
|---|---|---|
|HSE|Use the Public Sign Key in HSE OTP|Use the Public Sign Key in HSE OTP|
|VSE|Use the Public Sign Key in VSE OTP|Use the Public Sign Key on the top page of the main flash|

The HSE device ignores the default enabled [Allow use of public key from manufacturing token storage option](02-secure-boot-process#application-firmware) once the Public Sign Key has been provisioned.

To have better protection on the Public Sign Key, the [certificate-based](#signing-for-certificate-based-secure-boot) Secure Boot is strongly recommended on VSE devices since the SSB does not require accessing the Public Sign Key to verify the application signature.

The following sections provide two methods to sign the bootloader image and application image files. All procedures assume the required files are in the same folder.

1. Using Simplicity Commander
2. Using an HSM and Simplicity Commander

###### Bootloader Image File (heading level 8)

1. If Secure Boot flag is not enabled in SE OTP, follow the procedures in [Simplicity Commander](#simplicity-commander) to set up the ECDSA-P256-SHA256 Secure Boot configuration for the bootloader.
2. Follow the procedures in [AppBuilder](#appbuilder) or [Bootloader-core Software Component](#bootloader-core-software-component) to set up the ECDSA-P256-SHA256 Secure Boot configuration for the user application to generate an unsigned bootloader image.
3. The following steps show two methods to generate a signed bootloader image—either directly with Simplicity Commander (3a) or using an HSM with Commander (3b).  
   a. **(Using Simplicity Commander)** Run the `convert` command with **Private Sign Key** to overwrite the unsigned bootloader image file with the signed bootloader image file (`bootloader-uart-xmodem.s37`).  
   ```c  
    ```sh  
    commander	convert	bootloader-uart-xmodem.s37	--secureboot	--keyfile	sign_key.pem	--verify sign_pubkey.pem  
    --outfile bootloader-uart-xmodem.s37  
    ```  
     
    ```sh  
    Parsing file bootloader-uart-xmodem.s37... Found Application Properties at 0x00002b1c  
    Writing Application Properties signature pointer to point to 0x00002d08  
    Setting signature type in Application Properties: 0x00000001  
    Image SHA256: c53bb8a3fd88a5071bfb71444324bb136b276160318488ff89011bbd269e114e  
    R = AB62F3A52B13D137FBCC6A2176D4D1852E06B6E4E6B2673DC251FC491450CBDA  
    S = 9C7C7AF2624165FD90FB3B114E3FA6FE4F4C5625B15C9F3D50DCB04DD06A7B19  
     
    Verifying signed image...  
    Writing to bootloader-uart-xmodem.s37...  
    Overwriting file: bootloader-uart-xmodem.s37...  
    DONE  
    ```  
   ```  
   b. **(Using an HSM and Simplicity Commander)** Run the `convert` command with `--extsign` option to generate an external signing bootloader image file (`bootloader-uart-xmodem.extsign`).  
   ```c  
    ```sh  
    commander convert bootloader-uart-xmodem.s37 --secureboot --extsign --outfile bootloader-uart-xmodem  
    ```  
     
    ```sh  
    Parsing file bootloader-uart-xmodem.s37... Found Application Properties at 0x00002b1c  
    Writing Application Properties signature pointer to point to 0x00002d08  
    Setting signature type in Application Properties: 0x00000001  
    Writing to bootloader-uart-xmodem.extsign...  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key to generate the signature for the external signing bootloader image. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** to simulate this process. The signature is in the `bl_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out bl_signature.der bootloader-uart-xmodem.extsign  
    ```  
     
    Run the `convert` command with the **bootloader image signature** to overwrite the unsigned bootloader image file with the signed bootloader image file (`bootloader-uart-xmodem.s37`).  
     
    ```sh  
    commander convert bootloader-uart-xmodem.s37 --secureboot --signature bl_signature.der  
    --verify sign_pubkey.pem --outfile bootloader-uart-xmodem.s37  
    ```  
     
    ```sh  
    Parsing file bootloader-uart-xmodem.s37... Parsing signature file bl_signature.der...  
    R = 0E9FC64F41B55367894908D3ADAC40E8D145E33224C4BAA8151EC3EFD107A154  
    S = F56230AA6484E55270F22A4D164377CA918F66A367656AB6E10CB3F58641CE84  
    Found Application Properties at 0x00002b1c  
    Writing Application Properties signature pointer to point to 0x00002d08  
    Setting signature type in Application Properties: 0x00000001  
     
    Verifying signed image...  
    Writing to bootloader-uart-xmodem.s37...  
    Overwriting file: bootloader-uart-xmodem.s37...  
    DONE  
    ```  
   ```
4. **(Optional)** Run the `util appinfo` command to check all available information about `ApplicationProperties_t` struct in a signed GBL image.  
   ```sh  
   commander util appinfo bootloader-uart-xmodem.s37  
   ```  
   ```sh  
   Parsing file bootloader-uart-xmodem.s37...  
   Found application properties in image.  
   Application properties info:  
   Application properties location : 0x00002b30  
   Signature location	            : 0x00002c44  
   Signature type	                : ECDSA-P256  
   Long token section address	    : Not set (0x00000000)  
     
   Application data info:  
   For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.  
   App type	                    : Bootloader (APPLICATION_TYPE_BOOTLOADER)  
   App version	                    : 0x02000000  
   Product ID	                    : Not set (0x00000000000000000000000000000000)  
     
   No certificate found in image.  
   For Series 2 devices: If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.  
   DONE  
   ```
5. The signed bootloader image file (`.s37`) can be used for [production programming](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) or for generating a [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) for bootloader upgrade.
6. Run the `flash` command to program the signed bootloader image (`bootloader-uart-xmodem.s37`) to the device if the device does not have a bootloader.  
   ```sh  
   commander flash bootloader-uart-xmodem.s37 --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   Parsing file bootloader-uart-xmodem.s37...  
   Writing 16384 bytes starting at address 0x00000000  
   Comparing range 0x00000000 - 0x00003FFF (16 KiB)  
   Programming range 0x00000000 - 0x00001FFF (8 KiB)  
   Programming range 0x00002000 - 0x00003FFF (8 KiB)  
   DONE  
   ```  
   Simplicity Commander output for Series 3 devices will look as follows:  
   ```sh  
   WARNING: Failed secure boot detected. Issuing a mass erase before flashing to recover the device...  
   Parsing file bootloader-uart-xmodem.s37...  
   Writing 14280 bytes starting at address 0x01000000  
   Erasing range 0x01000000 - 0x01007FFF (1 sector, 32 KB)  
   Programming range 0x01000000 - 0x01000FFF (4 KB)  
   Programming range 0x01001000 - 0x01001FFF (4 KB)  
   Programming range 0x01002000 - 0x01002FFF (4 KB)  
   Programming range 0x01003000 - 0x01003FFF (4 KB)  
   Programming range 0x01004000 - 0x01004FFF (4 KB)  
   Programming range 0x01005000 - 0x01005FFF (4 KB)  
   Programming range 0x01006000 - 0x01006FFF (4 KB)  
   Programming range 0x01007000 - 0x01007FFF (4 KB)  
   JLinkError: Failed to halt CPU.  
   Closing region 0 (this consumes one OTP bit, consider --noclose on development/testing devices)  
   Flashing completed successfully!  
   DONE  
   ```

###### Application Image File (heading level 8)

1. Follow the procedures in [Generate an Unsigned Application Image](#generate-an-unsigned-application-image) to generate an unsigned application image for the bootloader.
2. The following steps show two methods to generate a signed application image, either directly with Simplicity Commander (2a) or using an HSM with Commander and OpenSSL (2b).  
   a. **(Using Simplicity Commander)** Run the `convert` command with **Private Sign Key** to overwrite the unsigned application image file with the signed application image file (`blink_baremetal.s37`).  
   ```c  
    ```sh  
    commander convert blink_baremetal.s37 --secureboot --keyfile sign_key.pem --verify sign_pubkey.pem  
    --outfile blink_baremetal.s37  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Found Application Properties at 0x000061bc  
    Writing Application Properties signature pointer to point to 0x000064d8  
    Setting signature type in Application Properties: 0x00000001  
    Image SHA256: 8b58ec567126aa1f6baa88afc916581477745aca6f47697ec093512fc30dcc6f  
    R = 056E3AA36BD882B5467D44A56DB7CC1AEE44D45BC9B98FAB05BE2C032573A1F7  
    S = BE1D27CE7877D0BC761C0F02690CC74251EBE3A458474C573C21B3A738A03577  
     
    Verifying signed image...  
    Writing to blink_baremetal.s37... Overwriting file: blink_baremetal.s37...  
    DONE  
    ```  
   ```  
   b. **(Using an HSM and Simplicity Commander)** Run the `convert` command with `--extsign` option to generate an external signing application image file (`blink_baremetal.extsign`).  
   ```c  
    ```sh  
    commander convert blink_baremetal.s37 --secureboot --extsign --outfile blink_baremetal  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Found Application Properties at 0x00006198  
    Writing Application Properties signature pointer to point to 0x0000643c  
    Setting signature type in Application Properties: 0x00000001  
    Writing to blink_baremetal.extsign...  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key to generate the signature for the external signing application image. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** to simulate this process. The signature is in the `app_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out app_signature.der blink_baremetal.extsign  
    ```  
     
    Run the `convert` command with the **application image signature** to overwrite the unsigned application image file with the signed application image file. (`blink_baremetal.s37`).  
     
    ```sh  
    commander	convert	blink_baremetal.s37	--secureboot	--signature	app_signature.der	--verify sign_pubkey.pem  
    --outfile blink_baremetal.s37  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Parsing signature file app_signature.der...  
    R = BD5BDC866CE67DA104B1E7B686C45B7BF96F2643154D37ACC63DACDF69C27E89  
    S = 2DD3BFFAC857A5B0BD8C9B4DDB23D21944D062F8E431D36541B84EF411C1CC92  
    Found Application Properties at 0x000061bc  
    Writing Application Properties signature pointer to point to 0x000064d8  
    Setting signature type in Application Properties: 0x00000001  
     
    Verifying signed image...  
    Writing to blink_baremetal.s37... Overwriting file: blink_baremetal.s37...  
    DONE  
    ```  
   ```
3. **(Optional)** Run the `util appinfo` command to check all available information about `ApplicationProperties_t` struct in a signed application image.  
   ```sh  
   commander util appinfo blink_baremetal.s37  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Found application properties in image. Application properties info:  
   Application properties location : 0x000061bc  
   Signature location	            : 0x000064d8  
   Signature type	                : ECDSA-P256  
   Long token section address	    : Not set (0x00000000)  
     
   Application data info:  
   For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.  
   App type	                    : MCU application (APPLICATION_TYPE_MCU)  
   App version	                    : 0x00000001  
   Product ID	                    : Not set (0x00000000000000000000000000000000)  
     
   No certificate found in image.  
   For Series 2 devices: If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.  
   DONE  
   ```
4. The signed application image file (`.s37`) can be used for [production programming](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) or for generating a [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) for application upgrade.

###### Signing for Certificate-Based Secure Boot (heading level 7)

The following figure describes the signing and verification for certificate-based Secure Boot. You can freely switch between standard and advanced certificate-based Secure Boot by upgrading the application firmware without and with the application certificate.

![Certificate-Based Sign and Verify](/series2-secure-boot-with-rtsl/0.2/images/certificate-based-sign-verify-standard.png)

![Certificate-Based Sign and Verify](/series2-secure-boot-with-rtsl/0.2/images/certificate-based-sign-verify-advanced.png)

###### Certificate (heading level 8)

The following table describes the elements of a certificate.

|**Element**|**Description**|
|---|---|
|Certificate structure version|The version of the certificate structure.|
|Reserved flags|Reserved in the current certificate structure version.|
|Certificate public key|ECDSA-P256 public key, X and Y coordinates concatenated, used to validate the image.|
|Certificate version|The version of the running certificate.|
|Certificate signature|ECDSA-P256 signature, used for the authentication of the public key and the certificate version.|

**Notes**:

- The `application_properties.h` file in the Windows folder below defines the parameters of the certificate structure (`ApplicationCertificate_t`).  
  For GSDK v3.2 and lower: `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION>\platform\bootloader\api`  
  For GSDK v4.0 and higher: `C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\platform\bootloader\api`
- The certificate is not in X.509 format.

###### Private/Public Key Pair (heading level 8)

The following table describes two Private/Public Key pairs used in certificates for certificate-based Secure Boot. You can use [Simplicity Commander or HSM](#generate-key-and-signing) to generate these key pairs.

|**Certificate**|**Private Key**|**Public Key**|**Description**|
|---|---|---|---|
|Bootloader (bl_cert.bin) (1)|bl_cert_key.pem (Private Bootloader Key)|bl_cert_pubkey.pem (Public Bootloader Key)|The bootloader certificate is signed by the Private Sign Key corresponding to the Public Sign Key in SE OTP.|
|Application (app_cert.bin) (2)|app_cert_key.pem (Private Application Key)|app_cert_pubkey.pem (Public Application Key)|The application certificate is signed by the Private Bootloader Key corresponding to the Public Bootloader Key in the bootloader certificate.|

**Notes**:

1. a. Certificate version in the bootloader certificate < certificate version in SE flash - the certificate is rejected.  
   b. Certificate version in the bootloader certificate = certificate version in SE flash - the certificate is accepted.  
   c. Certificate version in the bootloader certificate > certificate version in SE flash - the certificate is accepted. The certificate version in SE flash is updated to match ([revocation mechanism](#certificate-revocation)).
2. The certificate version in the application certificate is compared with the certificate version in the bootloader certificate. The application certificate is accepted if its version is equal to or higher than the certificate version in the bootloader certificate.

The following sections provide two methods to sign the bootloader image and application image files. All procedures assume the required files are in the same folder.

1. Using Simplicity Commander
2. Using an HSM and Simplicity Commander

###### Bootloader Image File (heading level 8)

1. If Certificated based Secure Boot flag is not enabled in SE OTP, follow the procedures in [Simplicity Commander](#simplicity-commander) to set up the certificate-based Secure Boot configuration for the bootloader.
2. Follow the procedures in [AppBuilder](#appbuilder) or [Bootloader-core Software Component](#bootloader-core-software-component) to set up the certificate-based Secure Boot configuration for the user application to generate an unsigned bootloader image.
3. The following steps show two methods to generate a bootloader certificate, either directly with Simplicity Commander (3a) or using an HSM with Commander (3b).  
   a. **(Using Simplicity Commander)** Run the `util gencert` command with **Public Bootloader Key** and **Private Sign Key** to generate the bootloader certificate (`bl_cert.bin`). Refer to the table abovefor details about the `--cert-version` for bootloader certificate.  
   ```c  
    ```sh  
    commander util gencert --cert-type secureboot --cert-version 1 --cert-pubkey bl_cert_pubkey.pem  
    --sign sign_key.pem --outfile bl_cert.bin  
    ```  
     
    ```sh  
    Successfully signed certificate  
    DONE  
    ```  
     
    Run the `convert` command with **Bootloader Certificate** and **Private Bootloader Key** to overwrite the unsigned bootloader image file with the signed bootloader image file (`bootloader-uart-xmodem.s37`).  
     
    ```sh  
    commander convert bootloader-uart-xmodem.s37 --secureboot --certificate bl_cert.bin  
    --keyfile bl_cert_key.pem --outfile bootloader-uart-xmodem.s37  
    ```  
     
    ```sh  
    Parsing file bootloader-uart-xmodem.s37...  
    Writing certificate to location 0x00002cf0  
    Private key matches public key in certificate.  
    Found Application Properties at 0x00002d78  
    Writing Application Properties signature pointer to point to 0x00002f64  
    Setting signature type in Application Properties: 0x00000001  
    Image SHA256: 3cf574b688853a801e8dc98687414db27f886c60c55dbf7fea2d47633df94e8d  
    R = C866592B4CB7BAD9EFC35985F1B9D52C65C26453D4808597EEEFFB16DC4AA962  
    S = 94CAA21ED5D7772F96BBF4D24A0711A94DCCB6D4D38DFA45182876B9BE2A8DE3  
     
    Verifying signed image...  
    Writing to bootloader-uart-xmodem.s37... Overwriting file: bootloader-uart-xmodem.s37...  
    DONE  
    ```  
   ```  
   b. **(Using an HSM and Simplicity Commander)** Run the `util gencert` command with **Public Bootloader Key** and `--extsign` option to generate an external signing bootloader certificate (`bl_cert.extsign`). Refer to the table above for details about the `--cert-version` for bootloader certificate.  
   ```c  
    ```sh  
    commander util gencert --cert-type secureboot --cert-version 1 --cert-pubkey bl_cert_pubkey.pem  
    --extsign --outfile bl_cert  
    ```  
     
    ```sh  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key to generate the signature for the external signing bootloader certificate. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** to simulate this process. The signature is in the `bl_cert_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out bl_cert_signature.der bl_cert.extsign  
    ```  
     
    Run the `util signcert` command with the **bootloader certificate signature** to generate the bootloader certificate (`bl_cert.bin`).  
     
    ```sh  
    commander util signcert bl_cert.extsign --cert-type secureboot --signature bl_cert_signature.der  
    --verify sign_pubkey.pem --outfile bl_cert.bin  
    ```  
     
    ```sh  
    R = 065A58EA6CE6BBA44F3C59C6D255A901DBBC55FA97F261658B2026ABC8CD9680  
    S = 8A0011AA6393BC284B13C8313EE6772030DE07E213E74CA0FEA740F3D33E6518  
    Successfully verified signature Successfully signed certificate  
    DONE  
    ```  
     
    Run the `convert` command with **Bootloader Certificate** and `--extsign` option to generate an external signing bootloader image file (`bootloader-uart-xmodem.extsign`).  
     
    ```sh  
    commander convert bootloader-uart-xmodem.s37 --secureboot --certificate bl_cert.bin --extsign  
    --outfile bootloader-uart-xmodem  
    ```  
   ```
4. **(Optional)** Run the `util verifysign` command with **Public Sign Key** to verify that the **Bootloader Certificate and image** were correctly signed.  
   ```sh  
   commander util verifysign bootloader-uart-xmodem.s37 --verify sign_pubkey.pem  
   ```  
   ```sh  
   Parsing file bootloader-uart-xmodem.s37... Found application properties at 0x00002d78 Found certificate at 0x00002cf0  
   Successfully verified certificate signature with verification key.  
   Using certificate key to verify application signature.  
   Successfully verified application signature.  
   DONE  
   ```
5. **(Optional)** Run the `util appinfo` command to check all available information about `ApplicationProperties_t` struct in a signed GBL image.  
   ```sh  
   commander util appinfo bootloader-uart-xmodem.s37  
   ```  
   ```sh  
   Parsing file bootloader-uart-xmodem.s37...  
   Found application properties in image.  
   Application properties info:  
   Application properties location : 0x00002d00  
   Signature location	            : 0x00002e14  
   Signature type	                : ECDSA-P256  
   Long token section address	    : Not set (0x00000000)  
     
   Application data info:  
   For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.  
   App type	                    : Bootloader (APPLICATION_TYPE_BOOTLOADER)  
   App version	                    : 0x02000000  
   Product ID	                    : Not set (0x00000000000000000000000000000000)  
     
   Found certificate at 0x00002c78  
   Application certificate info:  
   Certificate located at	        : 0x00002c78  
   Certificate version	            : 0x00000001  
   Certificate key	                : 0xb1bc6f6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc08440f0a4e1dca4  
                                   7c04119ed6a1be31b7707e5f9d001a659a051003e95e1b936f05c37ea793ad63  
   Certificate signature	        : 0xef3b53368d4cd7821eb30a96140bbde8840378cfea30687a8c10642e1c7728fd  
                                   309f976adf46e4eac62a2233f0c1f08f4e58344bdec61775b5282ceb351bb3d0  
   DONE  
   ```
6. The signed bootloader image file (`.s37`) can be used for [production programming](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) or for generating a [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) for bootloader upgrade.
7. Run the `flash` command to program the signed bootloader image (`bootloader-uart-xmodem.s37`) to the device if the device does not have a bootloader.

```sh
commander flash bootloader-uart-xmodem.s37 --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Parsing file bootloader-uart-xmodem.s37...
Writing 16384 bytes starting at address 0x00000000
Comparing range 0x00000000 - 0x00003FFF (16 KiB)
Programming range 0x00000000 - 0x00001FFF (8 KiB)
Programming range 0x00002000 - 0x00003FFF (8 KiB)
DONE
```

Simplicity Commander output for Series 3 devices will look as follows:

```sh
WARNING: Failed secure boot detected. Issuing a mass erase before flashing to recover the device...
Parsing file bootloader-uart-xmodem.s37...
Writing 14280 bytes starting at address 0x01000000
Erasing range 0x01000000 - 0x01007FFF (1 sector, 32 KB)
Programming range 0x01000000 - 0x01000FFF (4 KB)
Programming range 0x01001000 - 0x01001FFF (4 KB)
Programming range 0x01002000 - 0x01002FFF (4 KB)
Programming range 0x01003000 - 0x01003FFF (4 KB)
Programming range 0x01004000 - 0x01004FFF (4 KB)
Programming range 0x01005000 - 0x01005FFF (4 KB)
Programming range 0x01006000 - 0x01006FFF (4 KB)
Programming range 0x01007000 - 0x01007FFF (4 KB)
JLinkError: Failed to halt CPU.
Closing region 0 (this consumes one OTP bit, consider --noclose on development/testing devices)
Flashing completed successfully!
DONE
```

###### Application Image File (Standard Certificate-Based) (heading level 8)

1. Follow the procedures in [Generate an Unsigned Application Image](#generate-an-unsigned-application-image) to generate an unsigned application image for the bootloader.
2. a. **(Using Simplicity Commander)** Run the convert command with **Private Bootloader Key** to overwrite the unsigned application image file with the signed application image file (`blink_baremetal.s37`).  
   ```sh  
   commander	convert	blink_baremetal.s37	--secureboot	--keyfile	bl_cert_key.pem	--verify bl_cert_pubkey.pem  
   --outfile blink_baremetal.s37  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Found Application Properties at 0x000061bc  
   Writing Application Properties signature pointer to point to 0x000064d8  
   Setting signature type in Application Properties: 0x00000001  
   Image SHA256: 8b58ec567126aa1f6baa88afc916581477745aca6f47697ec093512fc30dcc6f  
   R = 994739A26AB520A88A5550F1643AE263D88A952F185F96EE7021FA43DEA6138C  
   S = 65B7112715E2F999A6B216C32D3331AB63B2D31A0A1311DF36EEE62269F8D6AA  
     
   Verifying signed image...  
   Writing to blink_baremetal.s37...  
   Overwriting file: blink_baremetal.s37...  
   DONE  
   ```  
   b. **(Using an HSM and Simplicity Commander)** Run the `convert` command with `--extsign` option to generate an external signing application image file (`blink_baremetal.extsign`).  
   ```c  
    ```sh  
    commander convert blink_baremetal.s37 --secureboot --extsign --outfile blink_baremetal  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Found Application Properties at 0x000061bc  
    Writing Application Properties signature pointer to point to 0x000064d8  
    Setting signature type in Application Properties: 0x00000001  
    Writing to blink_baremetal.extsign...  
    DONE  
    ```  
     
    Use an HSM containing the Private Bootloader Key to generate the signature for the external signing application image. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Bootloader Key** to simulate this process. The signature is in the `app_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out app_signature.der blink_baremetal.extsign  
    ```  
     
    Run the `convert` command with the **application image signature** to overwrite the unsigned application image file with the signed application image file. (`blink_baremetal.s37`).  
     
    ```sh  
    commander convert blink_baremetal.s37 --secureboot --signature app_signature.der  
    --verify bl_cert_pubkey.pem --outfile blink_baremetal.s37  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Parsing signature file app_signature.der...  
    R = 8DA79B020E954D24C23423D80627E046E44052736F6546902F016D64464E82DE  
    S = 9D5A1CC424E97A5AD0352A4EEA6BBF565FED5FC61FF99E63AA73DFFEAD9EE399  
    Found Application Properties at 0x000061bc  
    Writing Application Properties signature pointer to point to 0x000064d8  
    Setting signature type in Application Properties: 0x00000001  
     
    Verifying signed image...  
    Writing to blink_baremetal.s37...  
    Overwriting file: blink_baremetal.s37...  
    DONE  
    ```  
   ```
3. **(Optional)** Run the `util verifysign` command with **Public Bootloader Key** to verify that the application image file was correctly signed.  
   ```sh  
   commander util verifysign blink_baremetal.s37 --verify bl_cert_pubkey.pem  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Found application properties at 0x000061bc  
   Did not find application certificate in file  
   If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.  
   Successfully verified application signature.  
   DONE  
   ```
4. **(Optional)** Run the `util appinfo` command to check all available information about `ApplicationProperties_t` struct in a signed application image.  
   ```sh  
   commander util appinfo blink_baremetal.s37  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Found application properties in image.  
   Application properties info:  
   Application properties location : 0x000061bc  
   Signature location	            : 0x000064d8  
   Signature type	                : ECDSA-P256  
   Long token section address	    : Not set (0x00000000)  
     
   Application data info:  
   For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.  
   App type	                    : MCU application (APPLICATION_TYPE_MCU)  
   App version	                    : 0x00000001  
   Product ID	                    : Not set (0x00000000000000000000000000000000)  
     
   No certificate found in image.  
   For Series 2 devices: If the configuration flag SECURE_BOOT_VERIFY_CERTIFICATE is set or a device has previously seen certificate based signing, it will not accept direct signing.  
   DONE  
   ```
5. The signed application image file (`.s37`) can be used for [production programming](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) or for generating a [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) for application upgrade.

###### Application Image File (Advanced Certificate-Based) (heading level 8)

1. Follow the procedures in [Generate an Unsigned Application Image](#generate-an-unsigned-application-image) to generate an unsigned application image for the bootloader.
2. a. **(Using Simplicity Commander)** Run the `util gencert` command with **Public Application Key** and **Private Bootloader Key** to generate the application certificate (`app_cert.bin`). Refer to [Private/Public Key Pair](#privatepublic-key-pair) for details about the `--cert-version` for application certificate.  
   ```sh  
   commander util gencert --cert-type secureboot --cert-version 1 --cert-pubkey app_cert_pubkey.pem  
   --sign bl_cert_key.pem --outfile app_cert.bin  
   ```  
   ```sh  
   Successfully signed certificate  
   DONE  
   ```  
   Run the `convert` command with **Application Certificate** and **Private Application Key** to overwrite the unsigned application image file with the signed application image file (`blink_baremetal.s37`). This command will inject the application certificate into the application image before signing.  
   ```sh  
   commander	convert	blink_baremetal.s37	--secureboot	--certificate	app_cert.bin	--keyfile  
   app_cert_key.pem  
   --outfile blink_baremetal.s37  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Writing certificate to location 0x000064d8  
   Private key matches public key in certificate.  
   Found Application Properties at 0x000061bc  
   Writing Application Properties signature pointer to point to 0x00006560  
   Setting signature type in Application Properties: 0x00000001  
   Image SHA256: 38fd11214c36abf3bb4c4eeda8cfdd2ca2ac2ff1e07072d555a06c74700a23f5  
   R = 6B4E3BB454513CAA4569415AE8F79453973AAC7FD1FC4914284B65010F3790A6  
   S = 1657CAAABED579880187261038358C83B1780A67CC41475370D94ED4445A5557  
     
   Verifying signed image...  
   Writing to blink_baremetal.s37...  
   Overwriting file: blink_baremetal.s37...  
   DONE  
   ```  
   b. **(Using an HSM and Simplicity Commander)** Run the `util gencert` command with **Public Application Key** and `--extsign` option to generate an external signing application certificate (`app_cert.extsign`). Refer to [Private/Public Key Pair](#privatepublic-key-pair) for details about the `--cert-version` for application certificate.  
   ```c  
    ```sh  
    commander util gencert --cert-type secureboot --cert-version 1 --cert-pubkey app_cert_pubkey.pem  
    --extsign --outfile app_cert  
    DONE  
    ```  
     
    Use an HSM containing the Private Bootloader Key to generate the signature for the external signing application certificate. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Bootloader Key** to simulate this process. The signature is in the `app_cert_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out app_cert_signature.der app_cert.extsign  
    ```  
     
    Run the `util signcert` command with the **application certificate signature** to generate the application certificate (`app_cert.bin`).  
     
    ```sh  
    commander util signcert app_cert.extsign --cert-type secureboot --signature app_cert_signature.der  
    --verify bl_cert_pubkey.pem --outfile app_cert.bin  
    ```  
     
    ```sh  
    R = 279D4FA1B801D108F82E30B0CF1164BF597549287290BD3883C5847B91095CCE  
    S = 567F0E219D2089EF4D79C3D94E43D2FADFE1899B71492ED358E6A1B46AE8162F  
    Successfully verified signature Successfully signed certificate  
    DONE  
    ```  
     
    Run the `convert` command with the **Application Certificate** and `--extsign` option to generate an external signing application image file (`blink_baremetal.extsign`).  
     
    ```sh  
    commander convert blink_baremetal.s37 --secureboot --certificate app_cert.bin --extsign --outfile blink_baremetal  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Writing certificate to location 0x000064d8  
    ```  
   ```
3. **(Optional)** Run the `util verifysign` command with **Public Bootloader Key** to verify that the **Application Certificate and image** were correctly signed.  
   ```sh  
   commander util verifysign blink_baremetal.s37 --verify bl_cert_pubkey.pem  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Found application properties at 0x000061bc Found certificate at 0x000064d8  
   Successfully verified certificate signature with verification key.  
   Using certificate key to verify application signature.  
   Successfully verified application signature.  
   DONE  
   ```
4. **(Optional)** Run the `util appinfo` command to check all available information about `ApplicationProperties_t` struct in a signed application image.  
   ```sh  
   commander util appinfo blink_baremetal.s37  
   ```  
   ```sh  
   Parsing file blink_baremetal.s37...  
   Found application properties in image.  
   Application properties info:  
   Application properties location : 0x000061bc  
   Signature location	            : 0x00006560  
   Signature type	                : ECDSA-P256  
   Long token section address	    : Not set (0x00000000)  
     
   Application data info:  
   For Series 2 devices: If rollback prevention is enabled in the OTP configuration, the device will not boot if the device has seen an application with a higher version number.  
   App type	                    : MCU application (APPLICATION_TYPE_MCU)  
   App version	                    : 0x00000001  
   Product ID	                    : Not set (0x00000000000000000000000000000000)  
     
   Found certificate at 0x000064d8  
   Application certificate info:  
   Certificate located at	        : 0x000064d8  
   Certificate version	            : 0x00000001  
   Certificate key	                : 0xe562003cd86e225decfd35712e431a19ecd5031a079b06c1d473620a6be9f57a  
                                   879820100fee074f28b5885fd6759f480b62aaa0717f96e245aab6635cfb1e11  
   Certificate signature	        : 0x039aaba62b5258e68d16e167c3a611c719c542bb3483f5d4b522472b06adf30f  
                                   8cfcc484bf8551a208256e3d2d8c9194a7d2ac551e2cac659a99822308a40aa6  
   DONE  
   ```
5. The signed application image file (`.s37`) can be used for [production programming](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) or for generating a [GBL upgrade image file](#generate-a-gbl-upgrade-image-file) for application upgrade.

###### Generate a GBL Upgrade Image File (heading level 7)

This section provides steps to create GBL files used to upgrade bootloader, application and/or SE firmware on Series 2 and Series 3 devices.

> **Note**: Series 3 devices support only GBLv4 files for firmware upgrade process.

- Follow the procedures in [AppBuilder](#appbuilder) or [Bootloader-core Software Component](#bootloader-core-software-component) to avoid overwriting the existing application image (if necessary) when upgrading the bootloader or SE.
- For a standalone bootloader with communication interface, you can only generate three separate GBL upgrade image files containing bootloader, SE, and application images.
- (Series 2 devices) For an application bootloader with storage, you can generate a single GBL upgrade image file (see example below) with a combination of bootloader, SE, and application images.

```sh
commander gbl create all.gbl --app app.s37 --bootloader bl.s37 --seupgrade se.seu
```

- A signed GBL upgrade image file is required if you enable the **Require signed firmware upgrade files** option in [AppBuilder](#appbuilder) or [Bootloader-core Software Component](#bootloader-core-software-component). The following table shows which private key(s) can be used to sign the GBL upgrade image file (bootloader, SE, or application) on VSE, HSE and Series 3 devices. The VSE devices store a [Public Sign Key](#signing-for-ecdsa-p256-sha256-secure-boot) copy on the top page of the main flash to verify the GBL upgrade image file for ECDSA-P256-SHA256 Secure Boot.

**Private Key(s) usage to sign GBL upgrade image file**

|**Secure Boot**|**HSE and Series 3**|**VSE**|
|---|---|---|
|ECDSA-P256-SHA256|Private Sign Key|Private Sign Key (Public Sign Key in main flash)|
|Certificate-Based|Private Sign Key or Private Bootloader Key|Private Bootloader Key|

- An encrypted GBL upgrade image file is required if you enable the **Require encrypted firmware upgrade files** option in [AppBuilder](#appbuilder) or [Bootloader-core Software Component](#bootloader-core-software-component). Refer to [Provision GBL Decryption Key](#provision-gbl-decryption-key) on how to provision the GBL Decryption Key for this option.
- [Only applicable for Series 2 devices] For an application bootloader with storage, you can enable the **Upgrade SE without using the staging area** option in **GSDK v4.1.1 or higher** to directly fetch the SE image from the GBL upgrade image file in storage instead of copying the image to the pre-configured upgrade location.

![Upgrade SE without using the staging area option](/series2-secure-boot-with-rtsl/0.2/images/sld794-image56.jpg)

To use the above option, the SE image cannot be in the encrypted part of the GBL upgrade image file if the **Require encrypted firmware upgrade files** option is enabled. Use the `--seunencrypted` option in **Simplicity Commander v1.13.0 or higher** (see example below) to generate an encrypted GBL upgrade image file with a SE image outside the encrypted part of the file.

```sh
commander gbl create se-upgrade.gbl --seupgrade secure-element.seu --seunencrypted --app myapp.s37
--encrypt aes_key.txt
```

- In Series 3 devices, the storage bootloader supports direct SE upgrades from the GBL file without the need for staging.

The following sections provide two methods to sign the bootloader, Secure Engine, and application upgrade image files if the **Require signed firmware upgrade files** option is enabled.

1. Using Simplicity Commander
2. Using an HSM and Simplicity Commander

The sections also include encryption examples with an AES-128 key (like `aes_key.txt`) for the **Require encrypted firmware upgrade files** option. All procedures assume the required files are in the same folder.

Series 3 devices require GBLv4. GBLv4 is a new format that supports more command line options than the upgrade file for series 2 devices which do not support GBLv4.

- To compress an upgrade file, append `--compress <compression algorithm>` to the command, supported algorithms are `lz4` and `lzma`.
- To add the product id, append `--productid <16-byte long identifier>` to the command.
- To add the bundle version and minimum version, append `--bundleversion <version number> --minversion <version number>` to the command.

Read more about GBLv4 files and the configurations supported in **Gecko Bootloader File Format v4** section of [Gecko Bootloader User's Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/02-gecko-bootloader-file-format-v4).

- All `gbl create` and `gbl4 create` commands support both encrypted and unencrypted images. To create an unencrypted image, omit the `--encrypt` option. To create an encrypted image, append `--encrypt aes_key.txt` to the command.

###### Bootloader Upgrade (heading level 8)

1. Create an unsigned GBL upgrade image:  
   a. Series 2 devices: Run the `gbl create` command with `--bootloader` option to generate the bootloader GBL upgrade image file (`bootloader-uart-xmodem.gbl`) with the signed bootloader image file (`bootloader-uart-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl create bootloader-uart-xmodem.gbl --bootloader bootloader-uart-xmodem.s37  
    ```  
     
    ```sh  
    Initializing GBL file...  
    Adding bootloader to GBL...  
    Writing GBL file bootloader-uart-xmodem.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--data` option to generate the bootloader GBL upgrade image file (`bootloader.gbl`) with the signed bootloader image file (`bootloader-uart-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl4 create bootloader.gbl --data bootloader-uart-xmodem.s37 --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Parsing file bootloader.s37...  
    Writing GBL file bootloader.gbl...  
    DONE  
    ```  
   ```
2. Create a signed GBL upgrade image using Simplicity Commander:  
   a. Series 2 devices: Run the `gbl create` command with `--bootloader` option to generate the signed bootloader GBL upgrade image file (`bootloader-uart-xmodem.gbl`) with **Private Sign Key** or **Private Bootloader Key** and the signed bootloader image file (`bootloader-uart-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl create bootloader-uart-xmodem.gbl --bootloader bootloader-uart-xmodem.s37 --sign  
    sign_key.pem  
    ```  
     
    ```sh  
    commander gbl create bootloader-uart-xmodem.gbl --bootloader bootloader-uart-xmodem.s37  
    --sign bl_cert_key.pem  
    ```  
     
    ```sh  
    Initializing GBL file...  
    Adding bootloader to GBL...  
    Signing GBL...  
    Image SHA256: 3eb09993ffca5f9b34df3f38b65ab9d2f6619b828b014a186516016d4bbd80f7  
    R = C21E0C19254AC4F62374BBCA65DEBB42C7349384F5527330CD030A51DC2170F7  
    S = E1680C3670DE68D731086845E2726EF3BF07B96EB54AA2DB2F390F60BDB6DAB2  
    Writing GBL file bootloader-uart-xmodem.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--data` option to generate the signed bootloader GBL upgrade image file (`bootloader.gbl`) with **Private Sign Key** or **Private Bootloader Key** and the signed bootloader image file (`bootloader-u art-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl4 create bootloader.gbl --data bootloader-uart-xmodem.s37 --sign sign_key.pem  
    --device SIMG301LIL  
    ```  
     
    ```sh  
    commander gbl4 create bootloader.gbl --data bootloader-uart-xmodem.s37 --sign bl_cert_key.pem  
    --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Parsing file bootloader.s37...  
    Writing GBL file bootloader.gbl...  
    Image SHA256: 5ba67b656103a3539f0f3802a4398f0babb3ff182fe9890962e678052571d42b  
    R = 6845219257E660918B7BAE26FFF3DC7BBE8150DA3281CE8881B7088E9E9736EC  
    S = B8C5B58987FA3C7E44444B7C43096A41F48D245ED148C4E0863F0F910133811E  
    DONE  
    ```  
   ```
3. Creating a signed GBL upgrade image using an HSM and Simplicity Commander:  
   a. Series 2 devices: Run the `gbl create` command with `--bootloader` and `--extsign` options to generate an external signing bootloader GBL upgrade image file (`bootloader-uart-xmodem.extsign`) with the signed bootloader image file (`bootloader-uart-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl create bootloader-uart-xmodem --bootloader bootloader-uart-xmodem.s37 --extsign  
    ```  
     
    ```sh  
    Initializing GBL file...  
    Adding bootloader to GBL...  
    Preparing GBL for external signing...  
    Writing GBL file bootloader-uart-xmodem.extsign...  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key or Private Bootloader Key to generate the signature for the external signing bootloader GBL upgrade image file. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** or **Private Bootloader Key** to simulate this process. The signature is in the gbl_signature.der.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out gbl_signature.der bootloader-uart-xmodem.extsign  
    ```  
     
    ```sh  
    openssl	dgst	-sha256	-binary	-sign	bl_cert_key.pem	-out	gbl_signature.der	bootloader-uart- xmodem.extsign  
    ```  
     
    Run the `gbl sign` command with the **signature** above to generate a signed bootloader GBL upgrade image file (`bootloader-uart-xmodem.gbl`).  
     
    ```sh  
    commander	gbl	sign	bootloader-uart-xmodem.extsign	--signature	gbl_signature.der	--verify  
    sign_pubkey.pem  
    --outfile bootloader-uart-xmodem.gbl  
    ```  
     
    ```sh  
    commander gbl sign bootloader-uart-xmodem.extsign --signature gbl_signature.der  
    --verify bl_cert_pubkey.pem --outfile bootloader-uart-xmodem.gbl  
    ```  
     
    ```sh  
    Reading GBL data from bootloader-uart-xmodem.extsign...  
    Parsing signature file gbl_signature.der...  
    R = 90F0A3C0D5D9ED2DC10EB3F55595FF21AB31307DC6283E3F3B7494A30FB741D4  
    S = 2765041F515A960F048CA250BFAB92031D4D1E569FB3F917C9329E7362C17B51  
    Writing signature to GBL... Verifying GBL...  
    Successfully verified GBL signature  
    Writing GBL file bootloader-uart-xmodem.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--data` and `--extsign` options to generate an unsigned and manifest files (`bootloader.unsigned` and `bootloader.manifest`) with the signed bootloader image file (`bootloader-uart-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl4 create bootloader --data bootloader-uart-xmodem.s37 --extsign --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Parsing file bootloader-uart-xmodem.s37...  
    Writing manifest data (for external signing) to bootloader.manifest  
    Writing unsigned GBL file (for later use in 'gbl4 sign') to bootloader.unsigned...  
    After computing the signature of bootloader.manifest, assemble the GBL4 using:  
    commander gbl4 sign bootloader.unsigned --outfile bootloader --signature <signature.der>  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key or Private Bootloader Key to generate the signature for the manifest file. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** or **Private Bootloader Key** to simulate this process. The signature is in the `gbl_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out gbl_signature.der bootloader.manifest  
    ```  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out gbl_signature.der bootloader.manifest  
    ```  
   ```
4. Follow the procedures in [Upload a GBL Upgrade Image File](#upload-a-gbl-upgrade-image-file) to upgrade the bootloader with the bootloader GBL upgrade image file.

###### Secure Engine Upgrade

1. Creating an unsigned GBL upgrade image:  
   a. Series 2 devices: Run the `gbl create` command with `--seupgrade` option to generate the SE GBL upgrade image file (`s2c1_se_fw_upgrade_1v2p9.gbl`) with the [SE image file](01-series-2-and-series-3-device-security-features#se-firmware) (`s2c1_se_fw_upgrade_1v2p9.seu`).  
   ```c  
    ```sh  
    commander gbl create s2c1_se_fw_upgrade_1v2p9.gbl --seupgrade s2c1_se_fw_upgrade_1v2p9.seu  
    ```  
     
    ```sh  
    Initializing GBL file...  
    Adding Secure Element upgrade image to GBL...  
    Writing GBL file s2c1_se_fw_upgrade_1v2p9.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--seupgrade` option to generate the SE GBL upgrade image file (`se-upgrade.gbl`) with the [SE image file](01-series-2-and-series-3-device-security-features#se-firmware) (`x301_se_fw_upgrade_3v3p2.seuv2`).  
   ```c  
    ```sh  
    commander gbl4 create se-upgrade.gbl --seupgrade x301_se_fw_upgrade_3v3p2.seuv2 --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Reading SE upgrade file from x301_se_fw_upgrade_3v3p2.seuv2  
    Writing GBL file se-upgrade...  
    DONE  
    ```  
   ```
2. Creating a signed GBL upgrade image using Simplicity Commander:  
   a. Series 2 devices: Run the `gbl create` command with `--seupgrade` option to generate the signed SE GBL upgrade image file (`s2c1_se_fw_upgrade_1v2p9.gbl`) with **Private Sign Key** or **Private Bootloader Key** and the [SE image file](01-series-2-and-series-3-device-security-features#se-firmware) (`s2c1_se_fw_upgrade_1v2p9.seu`).  
   ```c  
    ```sh  
    commander gbl create s2c1_se_fw_upgrade_1v2p9.gbl --seupgrade s2c1_se_fw_upgrade_1v2p9.seu  
    --sign sign_key.pem  
    ```  
     
    ```sh  
    commander gbl create s2c1_se_fw_upgrade_1v2p9.gbl --seupgrade s2c1_se_fw_upgrade_1v2p9.seu  
    --sign bl_cert_key.pem  
    ```  
     
    ```sh  
    Initializing GBL file...  
    Adding Secure Element upgrade image to GBL...  
    Signing GBL...  
    Image SHA256: 599d7fc35996b4715441b642709ed262525d09d811d4726e423c0d605ec0f0bf  
    R = EF8EC2DDEDDF44DF88FEAD4ED0A9FDC6351B4D745D5A05BFB87204791871A525  
    S = FCB26EF005D97E8C5341153A210AE9927E1CF646A3E473FFB90DA8C857E6421F  
    Writing GBL file s2c1_se_fw_upgrade_1v2p9.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--seupgrade` option to generate the signed SE GBL upgrade image file (`se-upgrade.gbl`) with **Private Sign Key** or **Private Bootloader Key** and the [SE image file](01-series-2-and-series-3-device-security-features#se-firmware) (`x301_se_fw_upgrade_3v3p2.seuv2`).  
   ```c  
    ```sh  
    commander gbl4 create se-upgrade.gbl --seupgrade x301_se_fw_upgrade_3v3p2.seuv2  
    --sign sign_key.pem --device SIMG301LIL  
    ```  
     
    ```sh  
    commander gbl4 create se-upgrade.gbl --seupgrade x301_se_fw_upgrade_3v3p2.seuv2  
    --sign bl_cert_key.pem --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Reading SE upgrade file from x301_se_fw_upgrade_3v3p2.seuv2  
    Writing GBL file se-upgrade.gbl...  
    Image SHA256: e6462d8810f9afee36974b82b3790af55c94f559c532ee0e264617d705a1fd6b  
    R = 095A9D64BD490FCA444D49DADC53C666B717006D9E7C91C196B259F6E27E5C9C  
    S = 0BFC9B86BA5B3C2A4C98AE5EC8264D905659AE8528433832FAD225D51E9899FD  
    DONE  
    ```  
   ```
3. Creating a signed GBL upgrade image using an HSM and Simplicity Commander:  
   a. Series 2 devices: Run the `gbl create` command with `--seupgrade` and `--extsign` options to generate an external signing SE GBL upgrade image file (`s2c1_se_fw_upgrade_1v2p9.extsign`) with the [SE image file](01-series-2-and-series-3-device-security-features#se-firmware) (`s2c1_se_fw_upgrade_1v2p9.seu`).  
   ```c  
    ```sh  
    commander gbl create s2c1_se_fw_upgrade_1v2p9 --seupgrade s2c1_se_fw_upgrade_1v2p9.seu --extsign  
    ```  
     
    ```sh  
    Initializing GBL file...  
    Adding Secure Element upgrade image to GBL...  
    Preparing GBL for external signing...  
    Writing GBL file s2c1_se_fw_upgrade_1v2p9.extsign...  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key or Private Bootloader Key to generate the signature for the external signing SE GBL upgrade image file. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** or **Private Bootloader Key** to simulate this process. The signature is in the `gbl_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out gbl_signature.der s2c1_se_fw_upgrade_1v2p9.extsign  
    ```  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out gbl_signature.der s2c1_se_fw_upgrade_1v2p9.extsign  
    ```  
     
    Run the `gbl sign` command with the **signature** above to generate a signed SE GBL upgrade image file (`s2c1_se_fw_upgrade_1v2p9.gbl`).  
     
    ```sh  
    commander	gbl	sign	s2c1_se_fw_upgrade_1v2p9.extsign	--signature	gbl_signature.der	--verify  
    sign_pubkey.pem  
    --outfile s2c1_se_fw_upgrade_1v2p9.gbl  
    ```  
     
    ```sh  
    commander gbl sign s2c1_se_fw_upgrade_1v2p9.extsign --signature gbl_signature.der  
    --verify bl_cert_pubkey.pem --outfile s2c1_se_fw_upgrade_1v2p9.gbl  
    ```  
     
    ```sh  
    Reading GBL data from s2c1_se_fw_upgrade_1v2p9.extsign...  
    Parsing signature file gbl_signature.der...  
    R = 2798B98194EE02717C738B5866ABD8D234D0F0E096E90495D371D2507D8E1C67  
    S = 19F2586E2C6177D6B4EEC708E006F67334C989D0398D4233C686C98ECB6992FB  
    Writing signature to GBL... Verifying GBL...  
    Successfully verified GBL signature  
    Writing GBL file s2c1_se_fw_upgrade_1v2p9.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--seupgrade` and `--extsign` options to generate unsigned and manifest files (`se-upgrade.unsigned` and `se-upgrade.manifest`) with the [SE image file](01-series-2-and-series-3-device-security-features#se-firmware) (`x301_se_fw_upgrade_3v3p2.seuv2`).  
   ```c  
    ```sh  
    commander gbl4 create se-upgrade --seupgrade x301_se_fw_upgrade_3v3p2.seuv2 --extsign  
    --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Reading SE upgrade file from x301_se_fw_upgrade_3v3p2.seuv2  
    Writing manifest data (for external signing) to se-upgrade.manifest  
    Writing unsigned GBL file (for later use in 'gbl4 sign') to se-upgrade.unsigned...  
    After computing the signature of se-upgrade.manifest, assemble the GBL4 using:  
    commander gbl4 sign se-upgrade.unsigned --outfile se-upgrade --signature <signature.der>  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key or Private Bootloader Key to generate the signature for the manifest file. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** or **Private Bootloader Key** to simulate this process. The signature is in the `gbl_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out gbl_signature.der se-upgrade.manifest  
    ```  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out gbl_signature.der se-upgrade.manifest  
    ```  
     
    Run the `gbl4 sign` command with the **signature** above to generate a signed SE GBL upgrade image file (`se-upgrade.gbl`).  
   ```
4. Follow the procedures in [Upload a GBL Upgrade Image File](#upload-a-gbl-upgrade-image-file) to upgrade the SE with the SE GBL upgrade image file.

**Notes**:

- The `sign_key.pem`/`sign_pubkey.pem` key pair is for [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot), and the `bl_cert_key.pem`/`bl_cert_pubkey.pem` key pair is for [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).
- Trying to apply a lower version of the SE image file (`.seu`) to the device will be ignored.

###### Application Upgrade

1. Creating an unsigned GBL upgrade image:  
   a. Series 2 devices: Run the `gbl create` command with `--app` option to generate the application GBL upgrade image file (`blink_baremetal.gbl`) with the signed application image file (`blink_baremetal.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl create blink_baremetal.gbl --app blink_baremetal.s37  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Initializing GBL file...  
    Adding application to GBL...  
    Writing GBL file blink_baremetal.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--data` option to generate the bootloader GBL upgrade image file (`app-upgrade.gbl`) with the signed bootloader image file (`bt_soc_blinky_freertos.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl4 create app-upgrade.gbl --data bt_soc_blinky_freertos.s37 --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Parsing file bt_soc_blinky_freertos.s37...  
    Writing GBL file app-upgrade.gbl...  
    DONE  
    ```  
   ```
2. Creating a signed GBL upgrade image using Simplicity Commander:  
   a. Series 2 devices: Run the `gbl create` command with `--app` option to generate the signed application GBL upgrade image file (`blink_baremetal.gbl`) with **Private Sign Key** or **Private Bootloader Key** and the signed application image file (`blink_baremetal.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl create blink_baremetal.gbl --app blink_baremetal.s37 --sign sign_key.pem  
    ```  
     
    ```sh  
    commander gbl create blink_baremetal.gbl --app blink_baremetal.s37 --sign bl_cert_key.pem  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Initializing GBL file...  
    Adding application to GBL...  
    Signing GBL...  
    Image SHA256: 116c1be47d799ab75afc7b3f4c9a8023e5cd031103b1d28c578eebfaf1ad73d2  
    R = CE4D85C058301A2437440E00385D97E496F1D8B5CAFFB8C184F8A88B5266E3E9  
    S = 90BBF754EBC0AB343CC32AA06ADED85F9D12D1A67CA6608F9085137142000A40  
    Writing GBL file blink_baremetal.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--data` option to generate the signed bootloader GBL upgrade image file (`app-upgrade-signed.gbl`) with **Private Sign Key** or **Private Bootloader Key** and the signed bootloader image file (`bt_soc_blinky_freertos.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl4 create app-upgrade-signed.gbl --data bt_soc_blinky_freertos.s37  
    --sign sign_key.pem --device SIMG301LIL  
    ```  
     
    ```sh  
    commander gbl4 create app-upgrade-signed.gbl --data bt_soc_blinky_freertos.s37  
    --sign bl_cert_key.pem --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Parsing file bt_soc_blinky_freertos.s37...  
    Writing GBL file app-upgrade-signed.gbl...  
    Image SHA256: 665ee8c703bc57ee59078d48183d39087e6a52e564ee3bd73971f33acbd0b009  
    R = 5C72EDFA23B947BAB1827A566C14BDF4542C24CE62F30DE928216AC10FE8AA5B  
    S = 22A4912CA192274681FB000F882D0CE500FC3D29C54CB354430553EC4A61B11A  
    DONE  
    ```  
   ```
3. Creating a signed GBL upgrade image using an HSM and Simplicity Commander:  
   a. Series 2 devices: Run the `gbl create` command with `--app` and `--extsign` options to generate an external signing application GBL upgrade image file (`blink_baremetal.extsign`) with the signed application image file (`blink_baremetal.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl create blink_baremetal --app blink_baremetal.s37 --extsign  
    ```  
     
    ```sh  
    Parsing file blink_baremetal.s37...  
    Initializing GBL file...  
    Adding application to GBL...  
    Preparing GBL for external signing...  
    Writing GBL file blink_baremetal.extsign...  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key or Private Bootloader Key to generate the signature for the external signing application GBL upgrade image file. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** or **Private Bootloader Key** to simulate this process. The signature is in the `gbl_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out gbl_signature.der blink_baremetal.extsign  
    ```  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out gbl_signature.der blink_baremetal.extsign  
    ```  
     
    Run the `gbl sign` command with the **signature** above to generate a signed application GBL upgrade image file (`blink_baremetal.gbl`).  
     
    ```sh  
    commander gbl sign blink_baremetal.extsign --signature gbl_signature.der --verify sign_pubkey.pem  
    --outfile blink_baremetal.gbl  
    ```  
     
    ```sh  
    commander gbl sign blink_baremetal.extsign --signature gbl_signature.der --verify bl_cert_pubkey.pem  
    --outfile blink_baremetal.gbl  
    ```  
     
    ```sh  
    Reading GBL data from blink_baremetal.extsign...  
    Parsing signature file gbl_signature.der...  
    R = 533499660E24F1620EF25D862FB607F46E9E4ECC41CBDECBE77C64EF1970D96A  
    S = FA8901878218F5F1DB0FAF8B074CE98A27C63FFDE63730CD49EE47E847B9811D  
    Writing signature to GBL...  
    Verifying GBL...  
    Successfully verified GBL signature  
    Writing GBL file blink_baremetal.gbl...  
    DONE  
    ```  
   ```  
   b. Series 3 devices: Run the `gbl4 create` command with `--data` and `--extsign` options to generate an unsigned and manifest files (`app-upgrade.unsigned` and `app-upgrade.manifest`) with the signed bootloader image file (`bootloader-uart-xmodem.s37`) from [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).  
   ```c  
    ```sh  
    commander gbl4 create app-upgrade --data bt_soc_blinky_freertos.s37 --extsign --device SIMG301LIL  
    ```  
     
    ```sh  
    Initializing GBLV4 file...  
    Parsing file bt_soc_blinky_freertos.s37...  
    Writing manifest data (for external signing) to app-upgrade.manifest  
    Writing unsigned GBL file (for later use in 'gbl4 sign') to app-upgrade.unsigned...  
    After computing the signature of app-upgrade.manifest, assemble the GBL4 using:  
    commander gbl4 sign app-upgrade.unsigned --outfile app-upgrade --signature <signature.der>  
    DONE  
    ```  
     
    Use an HSM containing the Private Sign Key or Private Bootloader Key to generate the signature for the manifest file. This example uses the [OpenSSL](#using-an-external-tool) with the **Private Sign Key** or **Private Bootloader Key** to simulate this process. The signature is in the `gbl_signature.der`.  
     
    ```sh  
    openssl dgst -sha256 -binary -sign sign_key.pem -out gbl_signature.der app-upgrade.manifest  
    ```  
     
    ```sh  
    openssl dgst -sha256 -binary -sign bl_cert_key.pem -out gbl_signature.der app-upgrade.manifest  
    ```  
     
    Run the `gbl4 sign` command with the **signature** above to generate a signed bootloader GBL upgrade image file (`bootloader.gbl`).  
   ```
4. Follow the procedures in [Upload a GBL Upgrade Image File](#upload-a-gbl-upgrade-image-file) to upgrade the application with the application GBL upgrade image file.

**Notes**:

- [Series 2 devices] The Simplicity Commander v1.11.0 or above supports GBL upgrade image file in `util verifysign` command.  
  ```sh  
  commander util verifysign blink_baremetal.gbl --verify sign_pubkey.pem  
  ```  
  ```sh  
  Successfully verified GBL signature  
  DONE  
  ```
- [Series 2 devices] The Simplicity Commander v1.12.0 or above fixes a bug introduced in v1.11.0 when using the `--extsign` option on the GBL upgrade image file.

###### Upload a GBL Upgrade Image File (heading level 7)

This section describes how to use UART XMODEM Bootloader v2.0.0 in GSDK v4.0 and higher to upload a GBL upgrade image file (`.gbl`) to the device. The procedures and pictures may be different for the other versions of this example.

The GBL upgrade image file uses a proprietary format to store the upgrade image for a firmware upgrade. Use the gbl create command to generate the GBL upgrade image file for bootloader, application, and Secure Engine. Refer to [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) and [Generate a GBL Upgrade Image File](#generate-a-gbl-upgrade-image-file) for more information about GBL upgrade image file creation.

You can use any terminal software that supports the XMODEM-CRC protocol for file transfer. This application note uses [Tera Term](https://ttssh2.osdn.jp/index.html.en) as terminal software. The default serial port setting is 115200 bps 8-N-1.

1. Assume the [UART XMODEM Bootloader](#generate-an-unsigned-gbl-image) and application firmware had already flashed to the radio board on WSTK.
2. Press the **RESET** and **PB0** push buttons on the WSTK.
3. Release the **RESET** push button to run the UART XMODEM Bootloader.  
   ![Options in UART XMODEM Bootloader](/series2-secure-boot-with-rtsl/0.2/images/sld794-image57.png)
4. Release the **PB0** push button. Press 1 (`upload gbl`) in Tera Term to upload a GBL upgrade image file.  
   ![Upload GBL option](/series2-secure-boot-with-rtsl/0.2/images/sld794-image58.png)
5. Transfer a file through XMODEM-CRC in Tera Term, navigate to **File** > **Transfer** > **XMODEM** > **Send...**.  
   ![XMODEM Transfer in Tera Term](/series2-secure-boot-with-rtsl/0.2/images/sld794-image59.png)
6. Select the target GBL upgrade image file. Click [**Open**] to upload.  
   ![Target GBL file location](/series2-secure-boot-with-rtsl/0.2/images/sld794-image60.png)
7. If no error occurs, press 2 (`run`) to start a firmware upgrade.  
   ![Run option](/series2-secure-boot-with-rtsl/0.2/images/sld794-image61.png)

###### Upgrade to Certificate-Based Secure Boot

You can upgrade the Series 2 and Series 3 devices deployed in the field from [ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) to [certificate-based Secure Boot](#signing-for-certificate-based-secure-boot) even if the [SECURE_BOOT_VERIFY_CERTIFICATE](#simplicity-commander) option in SE OTP is disabled.

```sh
commander security readconfig --serialno 440048205
```

```sh
MCU Flags
Secure Boot                    : Enabled
Secure Boot Verify Certificate : Disabled
Secure Boot Anti Rollback      : Enabled
Secure Boot Page Lock Narrow   : Disabled
Secure Boot Page Lock Full     : Disabled
```

The following procedures for the upgrade to certificate-based Secure Boot is an **IRREVERSIBLE** process.

1. Follow the procedures in [Generate Key and Signing](#generate-key-and-signing) to generate an ECDSA-P256 bootloader certificate key pair.
2. Follow the procedures in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate the signed GBL image file with the bootloader certificate key pair in step 1. The bootloader certificate version `(--cert-version` in the `util gencert` command) in this signed GBL image file must be **equal to or higher than one (≥ 1)**.
3. Follow the procedures in [Generate a GBL Upgrade Image File](#generate-a-gbl-upgrade-image-file) to upgrade the bootloader to certificate-based Secure Boot. Use the [Private Sign Key](#generate-a-gbl-upgrade-image-file) for ECDSA-P256-SHA256 Secure Boot to sign the bootloader GBL upgrade image file if required.  
   SE will use the Public Bootloader Key to [validate](#signing-for-certificate-based-secure-boot) the bootloader image once SE identifies a bootloader certificate in the bootloader image. If the bootloader certificate version from step 2 is **higher than zero (> 0) and gets verified once**, SE will never again accept the [ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) signed bootloader image. Refer to the "_Secure Boot Procedure_" section in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) for more information.  
   ```sh  
   commander security status --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   SE Firmware version : 1.2.9  
   Serial number	    : 000000000000000014b457fffe045a2d  
   Debug lock	        : Disabled  
   Device erase	    : Enabled  
   Secure debug unlock : Disabled  
   Tamper status	    : Not OK  
   Secure boot	        : Enabled  
   Boot status	        : 0x18 - Failed: Secure Boot requires cert, but none found  
   DONE  
   ```
4. **(Standard Certificate-Based)** Follow the procedures in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate the signed application image file with the Private Bootloader Key in step 1.
5. **(Advanced Certificate-Based)** Follow the procedures in [Generate Key and Signing](#generate-key-and-signing) to generate an ECDSA-P256 application certificate key pair.  
   Follow the procedures in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate the signed application image file with the application certificate key pair in this step and the Private Bootloader Key in step 1. The application certificate version (`--cert-version` in the `util gencert` command) in this signed application image file must be **equal to or higher** than the bootloader certificate version in step 2 ([Private/Public Key Pair](#privatepublic-key-pair)).
6. Follow the procedures in [Generate a GBL Upgrade Image File](#generate-a-gbl-upgrade-image-file) to upgrade application with the signed image from step 4 or 5 for certificate-based Secure Boot. Use the [Private Sign Key](#generate-a-gbl-upgrade-image-file) or [Private Bootloader key](#generate-a-gbl-upgrade-image-file) in **step 1** for certificate-based Secure Boot to sign the application GBL upgrade image file if required.

###### Certificate Revocation

The certificate revocation is the act of invalidating a certificate when its private key shows signs of being compromised. The following procedures describe how to revoke the Series 2 and Series 3 devices' bootloader certificates deployed in the field.

1. Follow the procedures in [Generate Key and Signing](#generate-key-and-signing) to generate a new ECDSA-P256 bootloader certificate key pair.
2. Follow the procedures in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate the signed GBL image file with the bootloader certificate key pair in step 1. The bootloader certificate version (`--cert-version` in the `util gencert` command) in this signed GBL image file must be **higher than** the certificate version in SE flash (see [Private/Public Key Pair](#privatepublic-key-pair)).
3. Follow the procedures in [Generate a GBL Upgrade Image File](#generate-a-gbl-upgrade-image-file) to upgrade the bootloader with the signed image from step 2. Use the [Private Sign Key](#generate-a-gbl-upgrade-image-file) or **existing** [Private Bootloader Key](#generate-a-gbl-upgrade-image-file) for certificate-based Secure Boot to sign the bootloader GBL upgrade image file if required.
4. **(Standard Certificate-Based)** Follow the procedures in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate the signed application image file with the Private Bootloader Key in step 1.
5. **(Advanced Certificate-Based)** Follow the procedures in [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate the signed application image file with the Private Bootloader Key in step 1. The application certificate version (--cert-version in the util gencert command) in this signed application image file must be **equal to or higher** than the bootloader certificate version in step 2 (see [Private/Public Key Pair](#privatepublic-key-pair)).  
   You should generate a new [ECDSA-P256 application certificate key pair](#generate-key-and-signing) if the Private Application Key for the application certificate is compromised.
6. Follow the procedures in [Generate a GBL Upgrade Image File](#generate-a-gbl-upgrade-image-file) to upgrade the application with the signed image from step 4 or 5. Use the [Private Sign Key](#generate-a-gbl-upgrade-image-file) or [Private Bootloader key](#generate-a-gbl-upgrade-image-file) in **step 1** for certificate-based Secure Boot to sign the application GBL upgrade image file if required.

###### Upgrade to Secure Boot with RTSL

The following procedures describe upgrading Series 2 and Series 3 devices deployed in the field without Secure Boot to Secure Boot with RTSL.

1. **(Recommended)** Upgrade SE firmware to the latest version if available. See the _Gecko Bootloader Operation - Secure Engine Upgrade_ section in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).
2. Follow the procedures in [AppBuilder](#) or [3.4.1.2 Bootloader-core Software Component](#bootloader-core-software-component) to prepare an unsigned GBL image with the required [Secure Boot configuration](02-secure-boot-process#application-firmware) for the application firmware.
3. Follow the procedures in [Generate Key and Signing](#generate-key-and-signing) to generate the ECDSA-P256 Sign Key pair for Secure Boot. The key pairs for the bootloader certificate and application certificate (advanced) are required if using [Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot).
4. Follow steps 1 to 2 in [SE Manager Key Provisioning Platform Example](#se-manager-key-provisioning-platform-example-2) if this HSE [GBL Decryption Key option](#provision-gbl-decryption-key) is selected. Use the Public Sign Key in step 3 and follow steps 1 to 3 in [SE Manager Key Provisioning Platform Example](#se-manager-key-provisioning-platform-example) to generate an **unsigned** image. Use this image to create an [application GBL upgrade image file](#generate-a-gbl-upgrade-image-file).
5. The original GBL (application Secure Boot is disabled) boots into the **unsigned** SE Manager Key Provisioning Platform Example after upgrading the application with the image file in step 4.
6. Follow steps 5 to 8 in [SE Manager Key Provisioning Platform Example](#se-manager-key-provisioning-platform-example) to install the Public Sign Key to SE OTP and GBL Decryption Key (optional) to HSE OTP. Press **SPACE** instead of **ENTER** in step 9 to **BYPASS** the programming of the [Secure Boot configuration](02-secure-boot-process#ssb) in SE OTP.  
   ```sh  
   . Press ENTER to initialize SE OTP for secure boot configuration or press SPACE to skip.  
     
   . SE manager deinitialization... SL_STATUS_OK (cycles: 5 time: 0 us)  
   ```  
   **Notes**:  
   - Programming the [Public Sign Key](#signing-for-ecdsa-p256-sha256-secure-boot) to the top page of the main flash (not included in this example) is required for the VSE device ECDSA-P256-SHA256 Secure Boot.  
   - Programming the GBL Decryption Key to the top page of the main flash (not included in this example) is required if the [default storage option](#provision-gbl-decryption-key) for GBL Decryption Key is selected and the **Require encrypted firmware upgrade files** option is enabled in step 2.
7. Follow the signing procedures in [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) (Bootloader Image File section, skip the Secure Boot configuration for the bootloader) with the required key(s) generated in step 3 to sign the unsigned GBL image generated from step 2. Use this signed image to create a [bootloader GBL upgrade image file](#generate-a-gbl-upgrade-image-file).
8. Follow the signing procedures in [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) (Application Image File section) with the required key(s) generated in step 3 to sign the unsigned application image generated from step 4. Use this signed image to create an [application GBL upgrade image file](#generate-a-gbl-upgrade-image-file).  
   > **Note**: For the application bootloader with storage, you can generate a [single GBL upgrade image file](#generate-a-gbl-upgrade-image-file) for signed images from steps 7 and 8.
9. The Secure Boot in SE OTP is not yet enabled, so FSB does not verify the signature when upgrading to the signed GBL in step 7. The updated GBL (application Secure Boot enabled) verifies the signature when upgrading or booting to the signed SE Manager Key Provisioning Platform Example in step 8.
10. Follow steps 9 to 10 (use **SPACE** to skip previous steps for OTP key programming) in [SE Manager Key Provisioning Platform Example](#se-manager-key-provisioning-platform-example) to program the required [Secure Boot configuration](02-secure-boot-process#ssb) in SE OTP for signed GBL.
11. Update a **signed** custom application firmware to replace the signed SE Manager Key Provisioning Platform Example used for Secure Boot with RTSL upgrade.

**Notes**:

- Refer to the "_Enabling Secure Boot RTSL on Series 2 and Series 3 Devices_" section (either Standalone Bootloaders or Application Bootloaders with Storage) in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[UG489](https://www.silabs.com/documents/public/user-guides/ug489-gecko-bootloader-user-guide-gsdk-4.pdf) and [Bootloader User Guide Series3 and higher](https://docs.silabs.com/wisun/latest/bootloader-user-guide-series3-and-higher/) for details.
- The SE Manager Key Provisioning Platform Example used here is just for reference. You can modify or write a new application to automate the processes for the Secure Boot with RTSL upgrade.
- If the [Require signed firmware upgrade files](#generate-a-gbl-upgrade-image-file) option is enabled in step 2, the GBL upgrade image files from steps 8 and 11 must be signed.
- If the [Require encrypted firmware upgrade files](#generate-a-gbl-upgrade-image-file) option is enabled in step 2, the GBL upgrade image files from steps 8 and 11 must be encrypted. And the GBL Decryption Key for the corresponding [option](#provision-gbl-decryption-key) in GBL must be in place.

###### Recover Devices when Secure Boot Fails

If a Secure Boot process fails (meaning firmware image at device starting address validation fails), the only way to recover is to flash a correctly signed image.

There are two scenarios to recover the device from a Secure Boot failure:

1. Debug Lock
2. BUSLOCK

###### DEBUG LOCK (heading level 7)

The following table describes the different debug lock scenarios on recovering the Secure Boot failure device.

|**Secure Debug**|**Device Erase**|**Debug Lock**|**State**|**Recover from Secure Boot Failure**|
|---|---|---|---|---|
|Disabled|Enabled|Disabled|Unlock|Flash a correctly signed image.|
|Disabled|Enabled|Enabled|Standard debug lock|Flash a correctly signed image after standard debug unlocking the device.|
|Disabled|Disabled|Enabled|Permanent debug lock|There is no way to recover the device. Make sure the programmed image is correctly signed before locking the device.|
|Enabled|Disabled|Enabled|Secure debug lock|Flash a correctly signed image after secure debug unlocking the device.|

> **Note**: The error code in the **Boot status** of examples below depends on boot failure caused by the host image (GBL).

The following procedures describe how to recover the Secure Boot failure device from the lock states below.

- Unlocked
- Standard debug locked
- Secure debug locked

1. Follow the procedure in [Signing for ECDSA-P256-SHA256 Secure Boot](#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](#signing-for-certificate-based-secure-boot) to generate a correctly signed GBL.
2. **(Unlocked)** Run the `security status` command to get the boot status.  
   ```sh  
   commander security status --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   SE Firmware version : 1.2.9  
   Serial number	    : 000000000000000014b457fffe045afd  
   Debug lock	        : Disabled  
   Device erase	    : Enabled  
   Secure debug unlock : Disabled  
   Tamper status	    : Not OK  
   Secure boot	        : Enabled  
   Boot status	        : 0x12 - Failed: Error while checking signature of host firmware  
   DONE  
   ```  
   Run the `flash` command to flash the correctly signed image (like `bootloader-uart-xmodem.s37`). If a failed Secure Boot is detected, the device will be erased before flashing the new image.  
   ```sh  
   commander flash bootloader-uart-xmodem.s37 --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   WARNING: Failed secure boot detected. Issuing a mass erase before flashing to recover the device...  
   Parsing file bootloader-uart-xmodem.s37...  
   Writing 16384 bytes starting at address 0x00000000  
   Comparing range 0x00000000 - 0x00003FFF (16 KiB)  
   Programming range 0x00000000 - 0x00001FFF (8 KiB)  
   Programming range 0x00002000 - 0x00003FFF (8 KiB)  
   DONE  
   ```
3. **(Standard debug locked)** Run the `security status` command to get the boot status.  
   ```sh  
   commander security status --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   SE Firmware version : 1.2.9  
   Serial number	    : 000000000000000014b457fffe045afd  
   Debug lock	        : Enabled  
   Device erase	    : Enabled  
   Secure debug unlock : Disabled  
   Tamper status	    : Not OK  
   Secure boot	        : Enabled  
   Boot status	        : 0x12 - Failed: Error while checking signature of host firmware  
   DONE  
   ```  
   Run the `security erasedevice` command to unlock the device.  
   ```sh  
   commander security erasedevice --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   Successfully erased device  
   DONE  
   ```  
   > **Note**: Issue a power-on or pin reset to complete the unlock process.  
   Run the `flash` command to flash the correctly signed image (like `bootloader-uart-xmodem.s37`). If a failed Secure Boot is detected, the device will be erased before flashing the new image.  
   ```sh  
   commander flash bootloader-uart-xmodem.s37 --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   WARNING: Failed secure boot detected. Issuing a mass erase before flashing to recover the device...  
   Parsing file bootloader-uart-xmodem.s37...  
   Writing 16384 bytes starting at address 0x00000000  
   Comparing range 0x00000000 - 0x00003FFF (16 KiB)  
   Programming range 0x00000000 - 0x00001FFF (8 KiB)  
   Programming range 0x00002000 - 0x00003FFF (8 KiB)  
   DONE  
   ```
4. **(Secure debug locked)** Run the `security status` command to get the boot status.  
   ```sh  
   commander security status --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   SE Firmware version : 1.2.9  
   Serial number	    : 0000000000000000000d6ffffe0a3a5f  
   Debug lock	        : Enabled  
   Device erase	    : Disabled  
   Secure debug unlock : Enabled  
   Tamper status	    : Not OK  
   Secure boot	        : Enabled  
   Boot status	        : 0x12 - Failed: Error while checking signature of host firmware  
   DONE  
   ```  
   Run the `security unlock` command to unlock the device with the debug unlock token.  
   ```sh  
   commander security unlock --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   Unlocking with unlock payload:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000000d6ffffe0a3a5f/challenge_020fc3cc9e492088d06d75d71b7aabfe/unlock_payload_0000000000111110.bin  
   Secure debug successfully unlocked  
   DONE  
   ```  
   Run the `flash` command with the `--noreset` option to flash the correctly signed image (like `bootloader-uart-xmodem.s37`).  
   ```sh  
   commander flash --noreset bootloader-uart-xmodem.s37 --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   Parsing file bootloader-uart-xmodem.s37...  
   Writing 16384 bytes starting at address 0x00000000  
   Comparing range 0x00000000 - 0x00003FFF (16 KiB)  
   Erasing range 0x00000000 - 0x00003FFF (2 sectors, 16 KiB)  
   Programming range 0x00000000 - 0x00001FFF (8 KiB)  
   Programming range 0x00002000 - 0x00003FFF (8 KiB)  
   DONE  
   ```  
   > **Note**: The `--noreset` option prevents the device from returning to the secure debug lock state before flashing.
5. Run the `security status` command to check the boot status. The example below is an unlocked device.  
   ```sh  
   commander security status --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   SE Firmware version : 1.2.9  
   Serial number       : 000000000000000014b457fffe045afd  
   Debug lock          : Disabled  
   Device erase        : Enabled  
   Secure debug unlock : Disabled  
   Tamper status       : OK  
   Secure boot         : Enabled  
   Boot status         : 0x20 - OK  
   DONE  
   ```

###### BUSLOCK (heading level 7)

When secure boot is enabled, the SE enforces the secure boot process through a hardware mechanism called BUSLOCK. This BUS-LOCK will halt the host-side (M33) bus so that it will not start the executing code. The BUSLOCK is enabled out of reset when secure boot is enabled.

- **BUSLOCK status for secure boot success**: BUSLOCK is enabled out of reset and is released only when the Secure boot process is successful and returns 0x20 - OK status code.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.9
Serial number       : 000000000000000014b457fffe045afd
Debug lock          : Disabled
Device erase        : Enabled
Secure debug unlock : Disabled
Tamper status       : OK
Secure boot         : Enabled
Boot status         : 0x20 - OK
DONE
```

- **BUSLOCK status for secure boot failure**: BUSLOCK remains applied when the Secure Boot process fails and returns anything but 0x20 - OK status code. This keeps the BUSLOCK intact, and the host CPU is frozen, resulting in halting firmware execution on the M33 core. The device can be recovered from the BUSLOCK state by following these steps:

1. Issue a `security erase` command to the SE:  
   ```sh  
   commander security erasedevice  
   ```  
   ```sh  
   Successfully erased device  
   DONE  
   ```
2. After issuing the `security erase` command to the SE, flash the correctly signed image to recover from a secure boot failure.

##### Debugging on Secure Boot Enabled Device

Assume a correctly signed GBL image has been programmed to the device. Follow the procedures in [Generate an Unsigned Ap- plication Image](03-examples#generate-an-unsigned-application-image) to generate an unsigned application image for the GBL.

The Windows environment variable PATH should include the folder (`C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander`) that locates the `commander.exe` of Simplicity Commander.

The following sections describe how to debug an application firmware with Simplicity IDE, or IAR on a Secure Boot enabled device.

###### Simplicity IDE

This application note uses Simplicity Studio v5.2.3.1. The procedures and pictures may be different for the other versions of Simplicity Studio 5.

1. The Simplicity IDE creates a folder below (`<NAME>` is the Windows User Name on PC) in Windows when building the unsigned application image.  
   `C:\Users\<NAME>\SimplicityStudio\v5_workspace\blink_baremetal\GNU ARM v10.2.1 - Default`
2. Follow the procedures in [Signing for ECDSA-P256-SHA256 Secure Boot](03-examples#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](03-examples#signing-for-certificate-based-secure-boot) to create a batch file (Windows) to sign the unsigned application image and then flash it to the device. This application note uses ECDSA-P256-SHA256 Secure Boot (Using Simplicity Commander) as an example to create a `secure_boot_debug.bat` file below.  
   ```sh  
   commander convert blink_baremetal.s37 --secureboot --keyfile sign_key.pem --verify sign_pubkey.pem  
   --outfile blink_baremetal.s37  
   commander flash blink_baremetal.s37  
   ```
3. Copy the batch file in step 2 and files (`sign_key.pem` and `sign_pubkey.pem` in this example) specified in `secure_boot_debug.bat` to the folder in step 1.
4. Right-click the project in the **Project Explorer** window, and then click **Properties** to open the properties dialog.  
   ![Project Explorer window](/series2-secure-boot-with-rtsl/0.2/images/sld794-image62.png)
5. Select **C/C++ Build > Settings > Build Steps**. Enter the phrase below to the **Command:** box under the **Post-build steps** (enter text to **Description:** box is optional) to run the batch file as a post-build action. Click [**Apply and Close**] to exit.  
   ```sh  
   cmd //c 'secure_boot_debug.bat'  
   ```  
   ![Properties dialog box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image63.jpg)
6. After building the project, the batch file in the **Post-build steps** overwrites the unsigned application image with the signed application image.  
   ![Overwriting in Post-build steps](/series2-secure-boot-with-rtsl/0.2/images/sld794-image64.jpg)  
   > **Note**: If the project is already up-to-date, it will not invoke the **Post-build steps** in step 5 to run the batch file. Use a dummy edit (add space or newline) on one of the source files in the project to trigger the build action.  
   ![Console window](/series2-secure-boot-with-rtsl/0.2/images/sld794-image65.jpg)  
   The application starts to run if no error in step 6.
7. Select the project in the **Project Explorer** window, click **Run→Attach to→1 Silicon Labs ARM Program** to attach to the running target for debugging on the signed application image.  
   ![Run window](/series2-secure-boot-with-rtsl/0.2/images/sld794-image66.jpg)

###### IAR

This section uses Simplicity Studio v5.4.2.0 and IAR v9.20.4. The procedures and pictures may be different for the other versions of Simplicity Studio 5 and IAR.

1. The **Overview** tab shows the **Target and Tool Settings** card on the left side. Scroll down if necessary and click [**Change Target/SDK/Generators**].  
   ![Overview tab in SCLP file](/series2-secure-boot-with-rtsl/0.2/images/sld794-image67.jpg)
2. Drop down the **CHANGE PROJECT GENERATORS** list and select **IAR Embedded Workbench Project**. Click [**Save**] to generate an IAR project.  
   ![Target and tool settings dialog box](/series2-secure-boot-with-rtsl/0.2/images/sld794-image68.png)
3. Double click the IAR workspace file (`blink_baremetal.eww`) in the **Project Explorer** window to open the IAR project. The IAR creates a folder below (`<NAME>` is the Windows User Name on PC) in Windows to store the compiled image.  
   `C:\Users\<NAME>\SimplicityStudio\v5_workspace\blink_baremetal\ewarm-iar\exe`  
   ![Project Explorer window](/series2-secure-boot-with-rtsl/0.2/images/sld794-image69.png)
4. Follow the procedures in [Signing for ECDSA-P256-SHA256 Secure Boot](03-examples#signing-for-ecdsa-p256-sha256-secure-boot) or [Signing for Certificate-Based Secure Boot](03-examples#signing-for-certificate-based-secure-boot) to create a batch file (Windows) to sign the unsigned application image. This application note uses ECDSA-P256-SHA256 Secure Boot (Using Simplicity Commander) as an example to create a `secure_boot_debug.bat` file below.  
   ```sh  
   cd C:\Users\<NAME>\SimplicityStudio\v5_workspace\blink_baremetal\ewarm-iar\exe  
   commander convert blink_baremetal.s37 --secureboot --keyfile sign_key.pem --verify sign_pubkey.pem  
   --outfile blink_baremetal.s37  
   ```
5. Copy the batch file in step 4 and files (`sign_key.pem` and `sign_pubkey.pem` in this example) specified in `secure_boot_debug.bat` to the folder in step 3.
6. Right-click the project in the workspace, and then click **Options...**.  
   ![Workspace window](/series2-secure-boot-with-rtsl/0.2/images/sld794-image70.jpg)  
   > **Note**: For GSDK v3.2 and lower, the `app_properties.c` is manually added to the IAR project.
7. Click **Build Actions** to open the **Build Actions Configuration** dialog box. Enter the phrase below to the **Post-build command line:** box to run the batch file as a post-build action. Click [**OK**] to exit.  
   ```sh  
   cmd /c "$PROJ_DIR$\ewarm-iar\exe\secure_boot_debug.bat > $PROJ_DIR$\log.txt 2>&1"  
   ```
8. After building the project, the batch file in the **Post-build command** overwrites the unsigned application image with the signed application image.  
   ![Build messages](/series2-secure-boot-with-rtsl/0.2/images/sld794-image72.png)  
   > **Note**: If the project is already up-to-date, it will not invoke the **Post-build command** in step 7 to run the batch file. Use a dummy edit (add space or newline) on one of the source files in the project to trigger the build action.  
   ![Build messages](/series2-secure-boot-with-rtsl/0.2/images/sld794-image73.png)
9. The `> $PROJ_DIR$\log.txt 2>&1` redirects the batch file output to the `log.txt` file in the IAR project folder.  
   ![Log.txt file](/series2-secure-boot-with-rtsl/0.2/images/sld794-image74.jpg)
10. If no error in step 8, click the ![start](/series2-secure-boot-with-rtsl/0.2/images/sld794-image75.jpg) icon to start debugging on the signed application image.

##### Failure Analysis

The following table describes the different scenarios when returning a Series 2 or Series 3 device to Silicon Labs for failure analysis.

|**State**|**Secure Boot Disabled**|**Secure Boot Enabled (2)**|
|---|---|---|
|Standard debug unlock|Device erase is not necessary for failure analysis.|Device erase is not necessary, but a correctly signed image is required to perform failure analysis.|
|Standard debug lock|Device erase is required to perform failure analysis.|Require device erase and correctly signed image to perform failure analysis.|
|Permanent debug lock|Cannot perform failure analysis.|Cannot perform failure analysis.|
|Secure debug lock (1)|Require debug unlock token to perform failure analysis.|Require debug unlock token and correctly signed image to perform failure analysis.|

**Notes**:

1. Follow the procedures in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) section _Secure Debug Unlock and Roll Challenge - Simplicity Commander_ to generate a valid debug unlock token for each device returned to Silicon Labs for failure analysis.
2. Secure boot enabled devices, especially with secure boot failure, may limit Silicon Labs' ability to determine the root cause of failure.

##### Secure Boot Status Codes

Boot status codes can be used to know the status of the boot mechanism. The `security status` command can be used to get the boot status.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.9
Serial number : 000000000000000014b457fffe045afd
Debug lock : Disabled
Device erase : Enabled
Secure debug unlock : Disabled
Tamper status : OK
Secure boot : Enabled
Boot status : 0x20 - OK
DONE
```

The following table shows Status codes in Secure Boot mechanism and their description:

|**STATUS CODE**|**DESCRIPTION**|
|---|---|
|0x00|Start PUF|
|0x01|Fetch OTP for bootloader|
|0x02|Tamper test|
|0x03|Self-tests|
|0x04|TRNG Initialization failed|
|0x05|NVM Initialization failed|
|0x0B|Jump to main loop|
|0x0C|Fetch OTP for host boot|
|0x0D|Fetch pointers host firmware|
|0x0E|Fetch header host firmware|
|0x0F|Fetch host firmware|
|0x10|Check version host firmware|
|0x11|Check signature on certificate for host firmware|
|0x12|Check signature host firmware|
|0x13|Failed to get data from internal NVM|
|0x14|Finding host application properties pointer|
|0x15|Validating host application properties structure|
|0x16|Validating host application signature pointer|
|0x17|Getting SecureBoot key|
|0x18|SecureBoot requires cert, but none found|
|0x19|Updating required certificate version failed|
|0x1A|Certificate is of an older version as the last cert we validated|
|0x1B|Certificate structure version is not supported by this firmware|
|0x1C|Certificate pointer is out of range|
|0x1D|Region 0 is not closed|
|0x20|Main loop entered|
|0x80|PUF AC was somehow cleared|
|0x81|PUF failed to reconstruct after the longest delay|
|0x90|ESEC aborted booting due to catching too many successive tamper resets|
|0xFF|Finished verifying host app|

#### Transitioning to the Updated Gecko Bootloader in GSDK 4.0 and Higher

##### Transitioning to the Updated Gecko Bootloader in GSDK 4.0 and Higher

> **Note: This section replaces _AN1326: Transitioning to the Updated Gecko Bootloader in GSDK 4.0 and Higher_. Further updates to this application note will be provided here**.

Gecko Bootloader v2.x, introduced in GSDK 4.0, contains a number of changes compared to Gecko Bootloader v1.x. Many of these changes are due to an underlying framework redesign that results in an improved developer experience in Simplicity Studio 5 as well as enhanced compatibility within the GSDK. This document describes the differences between the versions, including how to configure the new Gecko Bootloader within Simplicity Studio 5.

##### Introduction

Gecko Software Development Kit suite (GSDK) version 3 (GSDK v3.0) introduced a new underlying Gecko Platform architecture based on components. Beginning with GSDK 4.0, the Gecko Bootloader now uses this underlying architecture. With Simplicity Studio 5 (SSv5) and GSDK 4.0, developers working with Gecko Bootloader will benefit from the following component-based project configuration features:

- Search and filter to find and discover software components that work with the target device
- Automatically pull in all component dependencies and initialization code
- Configurable software components including peripheral inits, drivers, middleware, and stacks
- All configuration settings are in C header files for usage outside of Simplicity Studio
- Configuration validation to alert developers to errors or issues
- Easily manage all project source via git or other SCM tools
- Managed migration to future component and SDK versions
- Simplified transitions from Silicon Labs development kits to custom hardware

Other features of the SSv5/GSDK 4.x development environment include:

- Project source management options (link to SDK sources or copy all contents to user folder)
- Graphical pin configuration through the Pin Tool
- Redesigned Radio Configurator with a fresh UI that’s more intuitive for single- and multi-PHY customization
- Iterative development (configure components, edit sources, compile, debug) using SSv5 configuration tools and third-party IDEs
- GNU makefiles as a build option

This document summarizes the differences between the Gecko Bootloader v2.x in GSDK 4.0 and earlier AppBuilder-based versions. These differences include:

- Differences between AppBuilder and the new component-based Project Configurator
- Comparison of the new Project Configurator components with AppBuilder plugins
- Features of the Pin Tool, now used instead of Hardware Configurator
- Other differences including:  
  - Linker file  
  - Additional Macros  
  - Postbuild steps  
  - Main bootloader in main flash  
  - Callbacks  
  - Storage Slots  
  - App Properties

##### About Projects

###### Creating a Project

If you have used earlier versions of SSv5, initial project creation is unchanged. If you are unfamiliar with project creation in SSv5, see the [Simplicity Studio 5 User's Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/). This section highlights the differences with AppBuilder project creation and configuration.

Once you have selected an example project, an initial configuration dialog opens. Note that the Project Location, which in AppBuilder is shown on the General tab, is defined here.

![image1](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image1.png)

In SSv5, the compiler to use is specified when you create a project and, after that, is difficult to change (see [Simplicity Studio 5 User’s Guide Tips & Tricks](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tips-and-tricks/) for a procedure to convert an existing project from GCC to IAR). If you do not want to use the default compiler (GCC unless otherwise specified), click **BACK**, and change it on the first Project Configuration dialog.

![image2](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image2.png)

Click **FINISH** and the project will be generated.

![image3](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image3.png)

###### Project File Structure

On project generation, the required project files and folders are created.

![image4](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image4.png)

Projects always include the following parts:

- **autogen** folder: Only the autogen folder includes generated code. It includes configuration (mbedtls_config_autogen.h), init code, the linker script, and other generated code used by components, like the command descriptors for the CLI interface.
- **config** folder: Component configuration headers are located in this folder. These can be edited with the Simplicity IDE Component Editor, but directly editing the header file is also possible. The Component Editor is available through the Project Configurator’s **Configure** control, available only for configurable components.
- **gecko_sdk** folder (with version number): Contains source and binary files added by components.
- **files in the root folder**: Only the application specific files should be in the root folder, including source files, the project configurator (_.slcp_) file and the Pin Tool _(.pintool_) file. For more details, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).

![image5](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image5.png)

The first stage bootloader binary file is copied to the **autogen** folder at the time of project generation. The correct first stage binary file is located in accordance with the target hardware and placed in the **autogen,** which is later used by the postbuild script to generate a combined bootloader binary. The **autogen** folder is shown below with the first stage bootloader binary.

![image6](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image6.png)

###### Configuring a Project

Most project configuration can be done through tools in Simplicity Studio. These tools provide the functionality previously provided by AppBuilder.

- **Project Configurator**: the top-level project configuration tool through which you install and uninstall components and change other project parameters. It also provides access to other configuration tools.
- **Component Editor**: provides access to the configurable parameters of an individual component.
- **Pin Tool**: configures peripherals.

Once you create the project, the Project Configurator tabbed interface is presented, including:

- Overview
- Software Components
- Configuration Tools

You can always re-open the Project Configurator by double-clicking the <projectname>.slcp file. For details on using the Project Configurator and Component Editor, see the [Simplicity Studio 5 User's Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/).

###### OVERVIEW Tab (heading level 7)

The OVERVIEW tab, like AppBuilder’s General tab, shows the target part information, and a description of the project.

![image7](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image7.png)

Note that there is no **Generate** control. Changes made through Project Configurator are auto-saved and the project files are auto-generated. The Force Generation control on the Project Details card is provided for use only in the event of a system problem, where auto-generation fails.

The Project Generators interface controls generation of additional files for import into other IDEs. It does not change the compiler used to build the application image.

###### SOFTWARE COMPONENTS Tab (heading level 7)

The SOFTWARE COMPONENTS tab shows the available components and those that are already installed in the example code.

![image8](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image8.png)

Component groupings are subject to change in SDK releases, as new components are added and organization is updated. The most reliable way to find a specific component is to search for it. You can also filter the displayed components using the checkboxes at the top.

Installed components have a circled checkmark to the left. Configurable components have a gear icon to the right.

Select a component to see details about it. Click **Install** to install the component or **Uninstall** to remove it. If it is configurable, a **Configure** control is shown in the upper right.

![image9](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image9.png)

Click that control or the gear icon next to an installed component name to open the Component Editor in a new tab.

![image10](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image10.png)

Save any changes to trigger file generation.

###### CONFIGURATION TOOLS Tab (heading level 7)

The CONFIGURATION TOOLS tab is a quick way of opening useful tools for project development.

![image11](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image11.png)

##### Components

This section maps the various Gecko Bootloader components to the previously available plugins (in the AppBuilder workflow). Although the basic subgroups might remain the same, specific component locations are subject to change across various GSDK versions. Therefore, it is good practice to search for individual components by their names rather than the specific subgroups that they belong to.

|AppBuilder Plugin|Simplicity Studio v5 Component|Additional Comments|
|---|---|---|
|Communication| | |
|BGAPI UART DFU|BGAPI UART DFU| |
|EZSP-SPI|EZSP-SPI| |
|UART XMODEM|UART XMODEM| |
|XMODEM Parser|XMODEM Parser| |
|Core| | |
|Application Upgrade Version Check|Application Upgrade Version Check| |
|Bootloader Core|Bootloader Core| |
|GBL Compression (LZ4)|GBL Compression (LZ4)| |
|GBL Compression (LZMA)|GBL Compression (LZMA)| |
|Image Parser|Image Parser| |
|Image Parser with legacy EBL support|Image Parser with legacy EBL support| |
|Image Parser without encryption support|Image Parser without encryption support| |
|“|Bootloader Include Parser|New component that includes common Image Parser header files|
|“|Bootloader in Main Flash|New component that enables the user to place bootloader in main flash for xG13 and xG14 devices|
|Drivers| | |
|Delay|Bootloader Delay Driver| |
|SPI Master|Bootloader SPI Controller USART Driver| |
|SPI Slave|Bootloader SPI Peripheral USART Driver| |
|UART|Bootloader UART Driver| |
|EUART|Bootloader EUART Driver| |
|“|Bootloader SPI Controller EUSART Driver|New component supporting SPI EUSART driver. This component can be used with devices supporting EUSART interface.|
|“|Bootloader SPI Peripheral EUSART Driver|New component supporting SPI EUSART driver. This component can be used with devices supporting EUSART interface.|
|Storage| | |
|Common Storage|Common Storage| |
|Common Storage (single storage slot only)|Common Storage (single storage slot only)| |
|Internal Storage|Internal Storage| |
|SPI Flash Storage|SPI Flash Storage| |
|“|Bootloader Storage Slot Setup|New component that facilitates configuring storage slots for Internal and SPI Flash based bootloaders|
|Utils| | |
|Crypto|Crypto| |
|Cyclic Redundancy Check|Cyclic Redundancy Check| |
|Debug|Debug| |
|EMLIB|EMLIB Peripheral HAL|This component is no longer part of the Bootloader module. EMLIB component(s) can be found under Platform > Peripheral|
|EZSP GPIO Activation|EZSP GPIO Activation| |
|GPIO Activation|GPIO Activation| |
|SE Manager|SE Manager|This component is now available under Platform > Security. This component is only applicable for Series 2 devices.|
|Token Management|Token Management| |
|mbed TLS|Mbed TLS …|These components are available under Platform > Security|
|Bootloader Interface| | |
| |App Properties|A new component to configure application properties (version), which is used during creation of a GBL file using Simplicity Commander.|
|Bootloader-interface|Bootloader Application Interface| |

##### Pin Tool

In contrast to the AppBuilder workflow, Simplicity Studio v5 offers the **Pin Tool** configuration tool, which can be used to configure the various pins of the MCU used in the project. Pin Tool can be used in standalone mode through the tile on the **Configuration Tools** tab.

![image12](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image12.png)

Pin Tool-related configuration is also available through the Component Editor of all applicable configurable components, making it a one-stop solution for configuring pin details and setting user configuration details. Following is the list of configurable components that also include Pin Tool configuration (wherever applicable) in their configuration wizard.

|Configurable Component|Configuration Options|
|---|---|
|UART XMODEM|Menu Idle Timeout|
|Bootloader Core|All options that were available for the bootloader plugin are now available in the Bootloader Core component. Options include: Enable Secure Boot, Enable certificate support, Prevent bootloader write/erase, etc|
|Bootloader UART/EUART Driver|Configuration options include: USART settings, USART peripheral, Serial VCOM Enable/Disable|
|Bootloader SPI Controller USART/EUSART Driver|Configuration options include: Frequency, Peripheral and SPI Port Settings|
|Bootloader SPI Peripheral USART/EUSART Driver|Configuration options include: Tx Buffer Size, Rx Buffer Size, Peripheral and Port Settings|
|Bootloader Storage Slot Setup|Supports configuration of storage slot (start addresses and slot lengths) up to a maximum of 3 slots|
|Common Storage/Common Storage (single storage slot only)|Configuration options include: Start address of bootload info|
|Internal Storage|Configuration options include: Enable DMA based MSC Write, DMA channel to reserve|
|SPI Flash Storage|Enables configuration of the list of SPI flash devices that must be enabled in the bootloader image|
|Debug|Enable/disable Debug prints/asserts|
|EZSP GPIO Activation|Configuration options include: Properties of SPI NCP, WAKE INT Pin, HOST INT Pin|
|GPIO Activation|Configuration options include: Properties of Bootloader entry, Button Pin configuration|

The configuration options of any installed configurable component can be accessed by clicking **Configure**. Refer to section [2 Project Creation](_Ref88045121) for more details on the Component Editor.

As an example, in the following procedure the Bootloader SPI Controller USART Driver is configured using the Component Editor and the pin configuration is verified using the Pin Tool.

1. Pin Tool configuration before installing the SPI Controller component. The device used for this example is the EFM32GG11 Giant Gecko Starter Kit board (BRD2204A Rev B00).  
   ![image13](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image13.png)
2. Install the Bootloader SPI Controller USART driver component.  
   ![image14](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image14.png)
3. Click **Configure** to open the Component Editor and configure the USART peripheral as shown.  
   ![image15](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image15.png)
4. Open the Pin Tool.  
   ![image16](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image16.png)
5. The pin configurations are shown. Notice that pins PA12, PA13, PB6, PB7, and PB8 are reserved for USART0.  
   ![image17](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image17.png)

##### Linker File

The linker files for GCC and IAR are now generated during the project generation step. The linker files for the bootloader are generated from template files using the Jinja template engine. The template files are included with theGecko SDK Suite (GSDK), which is installed through Simplicity Studio. The jinja template files are located at **<path-to-simplicity-studio-installation>|v5|developer|sdks|gecko_sdk_suite|<gecko_sdk_version>|platform|common|toolchain|**.This path contains folders for both **gcc** and **iar**.

##### Additional Macros

In the AppBuilder workflow, the user could define additional compiler macros used during compilation of the bootloader application. In Gecko Bootloader v2.x, these additional macros are now part of the various components. These components have these macros defined internally, and those macros which require user intervention are available to the user as configuration options through the Component Editor.

##### Postbuild Steps

For Series 1 devices, the main stage bootloader needs to be combined with the first stage bootloader, which results in a combined bootloader binary. To accomplish this, a postbuild script is made available with the GSDK, which combines the appropriate first stage bootloader with the main stage bootloader to produce a combined bootloader binary. A postbuild step must be explicitly added through the Project’s settings so that the postbuild script can be run after the bootloader build is complete. For more details, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).

> **Note**: Adding the postbuild steps is mandatory when building bootloader binaries for Series 1 devices. If the postbuild step is not configured correctly, Simplicity Studio cannot build a combined bootloader binary image.

##### Main Bootloader in Main Flash

For xG13 and xG14 devices, the entire main stage bootloader might not fit into the bootloader flash if the user installs some extra components. In such scenarios, the main stage bootloader can be placed in the main flash by installing the **Bootloader in Main Flash** core component in the bootloader project.

![image18](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image18.png)

For more information on this component, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).

##### Callbacks

In contrast to the AppBuilder workflow, callbacks are now part of **btl_callbacks_stub.c**. This file is added to the project when the **SPI Flash Storage** component is installed. This file contains dummy implementation of callbacks that the bootloader relies on. This file can be found in **gecko_sdk_<version> > platform > bootloader > storage > btl_callbacks_stub.c** as shown.

![image19](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image19.png)

##### Storage Slots

Gecko Bootloader supports the Application Bootloader mode. This mode supports single/multiple storage slots that can be configured at compile time. In Gecko Bootloader v2.x, the storage slots can now be configured in the **Bootloader Storage Slot Setup** component using the Component Editor. A maximum of 3 storage slots can be configured.

![image20](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image20.png)

##### App Properties

Previously, in the AppBuilder workflow, a variable of type **AppProperties_t** had to be configured to add application properties to the application. This was then later used by Simplicity Commander during gbl file creation. Beginning with Gecko Bootloader version 2.x, a new configurable component named **App Properties** can be used to configure the application properties. This component can be installed using the Component editor which is available as part of Simplicity Studio. It is also installed automatically as a dependency on installing the **Bootloader Application Interface** component in the project. The component allows the user to configure the application version using Simplicity Studio’s Component Editor as shown below.

![image21](/bootloader-transitioning-guide-gsdk-v40-and-higher/0.1/images/sld795-image21.png)

For more details on how to configure this component, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).

### Firmware Update

#### Firmware Update Security Best Practices

Implementing a firmware update in a secure manner is critical to the
continued secure operation of a Mesh network. There is hardly a more
powerful security threat than an attacker that has the ability to
execute program code they control inside of a network.

Fortunately, there are multiple defense mechanisms that can be used to
help defend against such attacks. This document describes multiple
security best practices that can be used to protect the firmware
update process from attackers.

For Mesh Device Firmware Update implementation on Silicon Labs devices,
refer to [Bluetooth Mesh Device Firmware Update](/btmesh/11.0.0/btmesh-device-firmware-update).

For details on Silicon Labs Secure Boot, refer to [Gecko Bootloader
Security documentation](https://docs.silabs.com/mcu-bootloader/latest/gecko-bootloader-security).

The Mesh Device Firmware Update specification can be found at the
[Bluetooth SIG
website](https://www.bluetooth.com/specifications/specs/mesh-device-firmware-update-model/).

This guide makes use of terms defined in the above documentation
without re-explaining them.

##### Mesh Device Firmware Update Best Practices

The following sections describe security best practices and
why they should be applied.

Note that the practices are typically applied by the mesh network
operator that manages a given mesh deployment, but the device
vendor must enable the technical means to do so.

###### Use Distinct Encryption Keys for Firmware Messaging

It is a general security best practice to use distinct encryption keys
for specific purposes, and it should be followed in firmware update
messaging. The network manager can bind the BLOB transfer and DFU
models involved in the firmware update to an application key that is
not used for other purposes. Ideally, that application key would be
bound to an underlying network key that is also not used for other
purposes.

The benefit of using a distinct key for a specific purpose is that it
limits the attack surface that opens up if an encryption key
leaks. For example, even if an attacker got hold of the encryption key
used for controlling lighting, they would not be able to initiate a
firmware update as long as a different key is used for that
functionality.

If possible, use both a distinct application key and a distinct network
key; but at least use a distinct application key.

###### Consider Internet Download Security

The Initiator may acquire firmware update images from the Internet, if
the vendor of the Target nodes makes the images available on a firmware
image server. The nodes will provide the Initiator with a URI pointing
to the server during the firmware update process.

In that case, the Mesh Device Firmware Update specification
requires that HTTP over TLS (i.e., HTTPS) is used, but it is important
to note that it is not enough in itself. Using HTTP over TLS ensures
that the communication is encrypted, so that passive eavesdroppers
cannot see what firmware images are being downloaded, but in addition
to that, the Initiator must take care to authenticate the
server. Otherwise, there is no guarantee that the source of the
firmware images is in any way legitimate even if the images are
transmitted over an encrypted link.

It is recommended that the Initiator keeps a list of trusted firmware
server hostnames and does not attempt to connect to a server not
contained in that list. Refer to Target node vendors' documentation
for server hostnames that are valid for a given make and model of
a node.

It is strongly recommended that the name lookup to translate the
server hostname in the URI into an IP address is protected against
manipulation, for example, by using DNSSEC.

It is strongly recommended that the Initiator uses the latest version
of TLS to connect to the server. Using TLS versions with known
vulnerabilities is strongly advised against.

It is strongly recommended that the Initiator keeps a list of trusted
root certificates, and verifies the server certificate only against
root certificates in that list.

It is strongly recommended that the server hostname is checked against
the server certificate.

It is strongly recommended that on encountering any problem with a
server, such as certificate expiration, the Initiator aborts the
attempt to acquire a firmware update from that server and logs the
problem to the user, instead of continuing with the download.

###### Digitally Sign the Firmware Update Images

Silicon Labs bootloader supports digitally signed firmware updates.
This allows a Target node to authenticate the update against a known
trusted encryption key to verify that the upgrade comes from a trusted
source, but also to verify that the upgrade has not been tampered
with.

It is strongly recommended that only digitally signed update images
are applied at the Target node, and any non-signed images are
rejected.

###### Enable Version Rollback Prevention for Secure Boot

Silicon Labs bootloader supports anti-rollback, which means that a
newer firmware image cannot be replaced with an older one. This
feature can help protect from attacks that attempt to replace the
currently running firmware with an older firmware that is from a
legitimate source as such but contains exploitable vulnerabilities.
Without anti-rollback, an attacker might succeed in exploiting a
vulnerability in an old firmware image that has already been fixed in
newer versions.

It is strongly recommended that anti-rollback protection is taken into
use at the Target node.

#### Provisioning and Configuration After a Device Firmware Update

A device may become unprovisioned after a firmware update depending on how configuration data in the new firmware is changed. This section provides information on how to possibly avoid re-provisioning the device after updating the device firmware.

##### Updating Device Firmware from an SDK Version prior to Simplicity SDK 2025.6.0

A new model storage format has been introduced in Simplicity SDK 2025.6.0. If you are creating a new project, the new model storage library _protocol/bluetooth/build/gcc/cortex-m33/mesh_app/release/libbtmesh_model_storage_v2.a_ is added to your project and it will use the new model storage format.

If you are migrating your project from an old SDK, the new model storage format is the default option and therefore model configuration data may not be read properly from NVM3 when a device has been upgraded to new firmware.

To use the old model storage format in your project, install the **Backwards compatible persistent storage for Mesh model configuration data** component and you will find the old model storage library _protocol/bluetooth/build/gcc/cortex-m33/mesh_app/release/libbtmesh_model_storage_v1.a_ added to your project.

> **Note**: uninstalling the component will use the new model storage format.

![backwards compatible persistent storage](/btmesh-provisioning-state-after-device-firmware-update/0.1/images/sld782-image1.png)

With the new model storage format you can flexibly make DCD changes and may not need to re-provision the device after a firmware update. We recommend using the migration library to convert your model configuration data in NVM3 from the old format to the new format to benefit from the flexibility. To use the migration library, install the **Mesh model configuration data migration to current persistent storage format** component.

![migration to current persistent storage](/btmesh-provisioning-state-after-device-firmware-update/0.1/images/sld782-image2.png)

##### Changing Device Composition Data in New Firmware

The default implementation of the Firmware Update Server component in older SDKs performs a factory reset when applying the new firmware to the device. It means a device will become unprovisioned after a firmware update. The default implementation has been changed in Simplicity SDK 2025.6.0. The new implementation of the Firmware Update Server component performs a factory reset when there is model or element deletion in the device composition data of the new firmware.

The default implementation is weak functions implemented in _app/btmesh/common/btmesh_firmware_update_server/sl_btmesh_firmware_update_server_api.c_. The weak functions can be overridden in application by providing a strong implementation of `sl_btmesh_fw_update_server_metadata_check_start()` and `sl_btmesh_firmware_update_server_metadata_check_step()`.

The Firmware Update Server component assumes the metadata contains the Composition Data Page 0 from the new firmware and uses the metadata check to compare it with the Composition Data Page 0 in the device.

```C
  sc = sl_btmesh_node_compare_dcd(DCD_PAGE_0, len, metadata, &diff);

  if (sc != SL_STATUS_OK) {
    return BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_ERROR;
  }
```

The metadata check sets _additional_information_ to **BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION** if the result of the DCD comparison is SIG model deletion, vendor model deletion, or element deletion.

```C
  if (diff & sl_btmesh_node_sig_model_removed
      || diff & sl_btmesh_node_vendor_model_removed
      || diff & sl_btmesh_node_element_removed) {
    fw_additional_information = BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION;
  }

  *additional_information = fw_additional_information;
  return BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_SUCCESS;
```

In `sl_btmesh_fw_update_server_apply()`, a factory reset is performed before applying the firmware, if the metadata check reported that the device will be unprovisioned.

```C
  if (BOOTLOADER_OK == bootloader_setImageToBootload(idx)) {
    // Erase persistent mesh data stored in NVM and make the node unprovisioned
    // only based on the result of metadata check
    if (fw_additional_information == BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION) {
      // Reset node
      sl_btmesh_node_reset();
      // Erase NVM data
      app_btmesh_nvm_erase_all();
    }
    // Delay install
    app_timer_start(&timer, 1000, apply_step, NULL, true);
    apply_cntdwn = APPLY_DELAY;
  }
```

> **Note**: The _app/btmesh/script/generator/FirmwareArchiveGenerator.py_ script in SDK is a tool used to generate a firmware image in compliance with the Bluetooth Mesh DFU specification. It retrieves the content of the Composition Data Page 0 from the ELF file and sets it as the metadata.

##### Changing Stack Configuration in New Firmware

When upgrading device firmware, the new firmware may fail to run node or provisioner initialization if stack configurations in old and new firmware mismatch. One common mistake is decreasing the value of some memory configurations so that the stack will allocate a memory buffer that is not big enough to store the configuration data from NVM3. This includes but is not limited to:

- The number of models in new firmware is less than the one in old firmware
- The number of application bindings is less than the one in old firmware
- The number of subscriptions is less than the one in old firmware

The source code of device composition data configured in Bluetooth Mesh Configurator is generated in _autogen/sl_btmesh_dcd.c_ and _autogen/sl_btmesh_dcd.h_. The stack configuration configured in the Mesh Stack Configuration editor is stored in _config/sl_btmesh_config.h_.

#### Bluetooth Mesh Device Firmware Update

##### Bluetooth Mesh Device Firmware Update

**NOTE: This section replaces _AN1319: Bluetooth Mesh Device Firmware Update_. Further updates to this application note will be provided here.**

This application note provides background information on the Bluetooth Mesh Device Firmware Update feature. It describes the BLOB transfer, the DFU roles in a Bluetooth mesh network, the models required for these roles, and the firmware update process.

Bluetooth Mesh Device Firmware Update is a new feature introduced in the Bluetooth Mesh specification v1.1. The Bluetooth Mesh Device Firmware Update feature provides a standard way to update device firmware over the air. The feature enables the Bluetooth mesh network to check for the availability of device firmware updates, update multiple devices simultaneously for the same firmware, and track the progress of an update.

This application note briefly describes the different types of nodes that are required to run device firmware updates in a mesh network. These nodes play important roles in managing update images for the devices that need a firmware update and distributing the update images to the nodes. This document also describes the procedures to perform a firmware update in a mesh network. To run the DFU examples provided in the Bluetooth Mesh SDK, see [Bluetooth Mesh Device Firmware Update Example Walkthrough](/btmesh/11.0.0/btmesh-device-firmware-update-example).

##### Bluetooth Mesh DFU and BLOB Transfer

Bluetooth Mesh Device Firmware Update is designed as a two-layer architecture to run different protocols. The DFU layer runs the DFU protocol for higher-level decision making that manages and coordinates firmware updates among different types of nodes. The BLOB Transfer layer runs the underlying data transport protocol handling generic large binary object transfer. In principle, the BLOB Transfer component could be used standalone for transferring any data objects that are much larger than the maximum Access Layer PDU size between the network devices.

###### BLOB Transfer

The Bluetooth Mesh BLOB Transfer (MBT) is a component on a node transferring or receiving binary large objects (BLOBs) over a Bluetooth Mesh network. The MBT client sends a BLOB to one or multiple nodes and the MBT server receives the BLOB. Bluetooth Mesh Device Firmware Update uses the MBT component to transfer update images.

The following figure illustrates the concept of how the MBT component transfers an update image. The MBT client breaks an update image into suitably-sized blocks based on the capabilities of the MBT servers and transfers these blocks to the servers. Each block is composed of identically sized chunks of data, except for the last chunk which may be smaller than the other chunks if the block’s size is not an integer multiple of the chunk’s size. A single message carries only a single chunk.

![Bluetooth Mesh BLOB Transfer](/btmesh-device-firmware-update/10.0.0/images/sld779-image1.png)

The transfer may be performed in two modes: **Push BLOB Transfer mode** and **Pull BLOB Transfer mode**. The MBT client selects the transfer mode based on the capabilities supported by the servers. The MBT server may support both or only one of these modes.

In the Push BLOB Transfer mode, the client controls the flow of chunks to the servers, sending all the chunks from a block, then queries the servers to determine which chunks were received. All missing chunks are retransmitted.

In the Pull BLOB Transfer mode, the client transfers a BLOB typically to a single server at a time, although multiple simultaneous receivers can be supported as well. The server requests chunks from the client as it can process them, and the flow of chunks is controlled by the server.

A Low Power Node (LPN) typically only supports the Pull BLOB Transfer mode and therefore the Pull BLOB Transfer mode is typically used only if some of the MBT servers are Low Power Nodes. This mode makes it possible for the MBT server to throttle the transfer speed. This is necessary to ensure that no more chunks than the Friend node can store in its Friend Queue are transmitted at once.

The MBT client or server model is normally used as a transport in a higher-layer model such as the Firmware Update models.

###### Firmware Update Roles

Two to three roles participate in a firmware update over a Bluetooth mesh network: Initiator, Distributor, and Target Node, or Stand-alone Updater and Target Node. The Stand-alone Updater and Distributor as well as the Initiator can also be Target nodes. A firmware update is distributed simultaneously to the devices that have the same firmware. Sets of homogenous nodes are updated sequentially.

![Firmware Update Roles](/btmesh-device-firmware-update/10.0.0/images/sld779-image2.png)

- **Initiator** role: checks for available updates for the firmware running on Target nodes that are included in a list provided by a higher-layer application and then sends the new firmware images to a Distributor. The procedures performed by an Initiator are controlled by a higher-layer application. An Initiator might be a smartphone or gateway device that periodically checks product websites for the availability of new firmware images.
- **Distributor** role: delivers new firmware images to the Target nodes and monitors the progress of the firmware update. The Distributor acts as an intermediary on behalf of the Initiator so that the Initiator does not always need to be present on the mesh network. The Distributor reports progress back to the Initiator when requested. The Distributor continues to have the configured functionality when distributing updates.
- **Stand-alone Updater** role: checks for available updates for the firmware running on Target nodes and delivers the new firmware images directly to the Target nodes. A Stand-alone Updater might be a smartphone or mesh gateway device that has access to the Internet while present on the mesh network to check for the availability of new firmware images for the Target nodes. When a new firmware image is available, it manages the delivery of the firmware image to the Target nodes without an intermediary Distributor.
- **Target Node** role: receives firmware updates and updates itself. The Target node stays in normal operation until a reboot with the new firmware.

###### Firmware Update Models

The Bluetooth Mesh Model specification v1.1 adds new models to support the Bluetooth Mesh Device Firmware Update feature. There are no changes in the Bluetooth Mesh Profile specification. The table below summarizes the models required by each role that participates in firmware updates. A node may support multiple roles. For example, a Distributor may support the Target node role.

|Role|Firmware Distribution Client|Firmware Distribution Server|Firmware Update Client|Firmware Update Server|BLOB Transfer Client|BLOB Transfer Server|
|---|---|---|---|---|---|---|
|Target node|–|–|–|M|–|M|
|Initiator|M|–|M|–|M|–|
|Distributor|–|M|M|–|M|M|
|Stand-alone Updater|C.1|C.2|M|–|M|C.2|

M: Mandatory

C.1: Mandatory if Initiator role is supported, otherwise optional

C.2: Mandatory if Distributor role is supported, otherwise optional

- **Firmware Distribution Client** is the model used by the Initiator to send the firmware image and the firmware distribution parameters to the Distributor, and to start the firmware image transfer.
- **Firmware Distribution Server** is the model used by the Distributor to receive from the Initiator the firmware update parameters, the set of Target nodes to update, and the firmware image to transfer. This model can transfer one firmware image at a time.
- **Firmware Update Client** is the model used by the Distributor and Initiator to manage firmware updates. The Initiator uses this model to retrieve the information about the firmware subsystems installed on the Target node, and to get the download URIs of the new firmware images. The Distributor uses this model to start a firmware image transfer to the Target nodes.
- **Firmware Update Server** is the model used by the Target node to report the firmware images installed on the node and the download URI of new firmware images, and to initiate a firmware update to receive a new firmware image.
- **BLOB Transfer Client** is the model used to transfer BLOBs over a Bluetooth Mesh network. An MBT client can transfer a BLOB to one or more MBT servers, either unicasting or multicasting depending on the situation.
- **BLOB Transfer Server** is the model used to receive BLOBs over a Bluetooth mesh network from an MBT client.

##### Bluetooth Mesh Firmware Update Process

Multiple Target nodes can be updated either simultaneously using a multicast address or individually using unicast addresses. For efficiency, a multicast address should be used when multiple Target nodes indicate that they can accept the same firmware image. The Initiator does this by adding all Target nodes that support the same firmware image to the Target nodes list that is transferred to the Distributor. The Initiator transfers the firmware image to the Distributor and the Distributor distributes the firmware image to the nodes in the Target nodes list. Finally, the Target nodes apply the firmware image when the Distributor instructs them to do so. The Initiator can order the Distributor to either trigger applying the update immediately after the transfer is complete, or to wait for another message from the Initiator before applying the new firmware.

The Initiator optionally can transfer multiple firmware images to the Distributor, but the Distributor can distribute only one firmware image to Target nodes in a firmware update. This means that some nodes may not participate in the firmware update. The Initiator manages firmware images that are identified by the Firmware ID and determines what nodes are to be included in the Target nodes list.

The following figure illustrates an example of the case that only the nodes running the same firmware accept the firmware update. The mesh network has two sets of Target nodes running different firmware, one running Firmware X v1.0 (blue nodes: A, F, and C) and another running Firmware Y v1.0 (yellow nodes: B, E, H, I, and G). Both belong to the same network. The Distributor Node D is distributing Firmware X v2.0.

The blue nodes accepted the Firmware X v2.0. They therefore have subscribed to a multicast address and are simultaneously updating their firmware to version X v2.0. The yellow nodes are not participating in the firmware update because they did not accept the Firmware X v2.0 during the compatibility check and were not added to the Target nodes list by the Initiator.

![Distributor Updates Only Nodes that Accept the Firmware ID and Version](/btmesh-device-firmware-update/10.0.0/images/sld779-image3.png)

The following subsections briefly review the firmware update process.

###### Setting Up an Update

The first step is to set up an update. The Initiator polls the Target nodes for their update URIs and current firmware. The Initiator uses the information to get a newer firmware image and its metadata. The Initiator transfers a Target nodes list and an update image to the Distributor. The Initiator then starts the firmware distribution process. When the distribution is started, the Initiator specifies to the Distributor whether the update should be applied immediately after the transfer completes, or whether the update should be applied only after the Initiator sends a message to the Distributor to trigger applying the update. This mechanism can be used to defer rebooting the devices to a suitable time.

- The Initiator receives a list of Target nodes from the higher-layer application.
- When a new firmware image is available, the Initiator optionally may check whether nodes in the Target nodes list can accept the new firmware image. The nodes also inform the Initiator whether they will become unprovisioned or will have some changes to their composition data. The same information will be provided to the Distributor later on in the process.
- The Initiator optionally may check the information of the firmware images stored on a Distributor and can remove a firmware image from the Distributor at any time.
- The Initiator is not necessarily present on the mesh network after the distribution has started.
- The Initiator may check the status of the firmware image distribution via the Distributor at any time.

![Firmware Update Process: Setting Up an Update](/btmesh-device-firmware-update/10.0.0/images/sld779-image4.png)

###### Starting an Update

The Distributor has received an update image, a Target nodes list, and the Distribution Start command from the Initiator. The Distributor notifies the Target nodes to prepare for an update and sends the metadata of the update image to the Target nodes. The Distributor then negotiates suitable BLOB Transfer parameters with the Target nodes and starts the BLOB Transfer.

- The Target nodes check the metadata and may reject the update.
- The Target nodes inform the Distributor whether they will become unprovisioned after the update or not, and whether they will have changes to their composition data, based on the metadata.
- Upon a request from the Initiator to retrieve the progress of the firmware update for each Target node, the Distributor provides a list of Target nodes and the progress of the firmware image transfer, the update phase of the transfer, and any potential errors.

![Firmware Update Process: Starting an Update](/btmesh-device-firmware-update/10.0.0/images/sld779-image5.png)

###### Sending the Update Image

The MBT client sends the update image to the MBT servers. The section, [BLOB Transfer](02-bluetooth-mesh-dfu-and-blob-transfer#blob-transfer), explains how an update image is transferred.

In the Push BLOB Transfer Mode, the Distributor transfers the chunks from a block to the Target nodes. After the Distributor has sent all chunks of a block, the Distributor queries the Target nodes to report missing chunks and transfers each missing chunk to the Target nodes, until no missing chunks are reported. The Distributor then moves on to next block, until all blocks are sent.

In the Pull BLOB Transfer Mode, the Distributor receives an initial list of chunks from the Target nodes and transfers the chunks from the initial list to the Target nodes. The Distributor then waits for the BLOB Partial Block Report from the Target nodes before transferring the next set of chunks. The Distributor repeats the step transferring the requested chunks to the Target nodes until all blocks are sent.

The higher-layer application can cancel the BLOB Transfer at any time.

![Firmware Update Process: Sending the Update Image](/btmesh-device-firmware-update/10.0.0/images/sld779-image6.png)

###### Applying an Update

The firmware image distribution is complete when the Target nodes have received the update image. The Target nodes check the integrity of the update image, and the Distributor polls them until all Target nodes complete. Then, if the Initiator had instructed the Distributor to start applying the update immediately in the Distribution Start message, the Distributor instructs the Target nodes to apply the update image. Otherwise, the Distributor waits for the applying signal from the Initiator before triggering applying the new firmware. The Target nodes reboot with the new firmware.

- The higher-layer application can cancel the verify firmware procedure at any time.
- The Target nodes can remain provisioned or become unprovisioned after an update image is applied. The states of the Target nodes are reported to the Distributor and Initiator.

![Firmware Update Process: Applying an Update](/btmesh-device-firmware-update/10.0.0/images/sld779-image7.png)

#### Bluetooth Mesh Device Firmware Update Example Walkthrough

##### Bluetooth Mesh Device Firmware Update Example Walkthrough

**NOTE: This section replaces _AN1370: Bluetooth Mesh Device Firmware Update Example Walkthrough_. Further updates to this application note will be provided here.**

The Bluetooth mesh SDK comes with example projects that have the Bluetooth Mesh Device Firmware Update feature enabled to perform firmware updates in a Bluetooth mesh network. The examples assume use of Silicon Labs devices for the distributor node and the nodes whose firmware is to be updated, and the Silicon Labs Bluetooth mesh mobile app as the provisioner and initiator. This document describes the bootloader configurations and the firmware update models in the example projects, and walks through a firmware update demonstration.

The Bluetooth Mesh Model specification v1.1 defines a standard way to update device firmware over a Bluetooth mesh network. The device firmware update process typically requires three types of nodes involved: **Initiator** and **Distributor** nodes, as well as the nodes to be updated, called **Target nodes**. These roles are fulfilled by enabling the Firmware Update and BLOB Transfer models:

- Firmware Distribution Client
- Firmware Distribution Server
- Firmware Update Client
- Firmware Update Server
- BLOB Transfer Client
- BLOB Transfer Server

To understand the basics of the Bluetooth Mesh Device Firmware Update specification, see [Bluetooth Mesh Device Firmware Update](/btmesh/11.0.0/btmesh-device-firmware-update).

This document explains the Bluetooth mesh examples, installed as part of the Bluetooth Mesh SDK, running as the Distributor and Target nodes, and the Silicon Labs Bluetooth Mesh mobile app running as the Initiator. [Bootloader Configurations for Firmware Updates](02-bootloader-configurations-for-firmware-updates) describes the bootloader examples that are an essential program to boot up a Silicon Labs device and to update firmware on the device. [Firmware Update Examples and Models](03-firmware-update-examples-and-models) discusses the models required for running the Distributor and Target nodes, and how to create an update image archive. [Firmware Update Demonstration](04-firmware-update-demonstration) walks through a firmware update demo using the Silicon Labs Bluetooth Mesh mobile app, the Distributor example, and other Bluetooth mesh examples as Target nodes.

###### Requirements

The following is required to run the DFU examples.

- At least two mainboards with a supported board installed, one used for the Distributor and the other(s) for the device firmware update target(s).
- [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio)
- Gecko SDK Suite 4.2.2 (Bluetooth Mesh SDK 4.2.0) or later. The bootloader and DFU examples are included in the SDK.
- [Silicon Labs Bluetooth Mesh Mobile Application](https://www.silabs.com/products/development-tools/software/bluetooth-low-energy/mobile-apps/ble-mesh)  
  - Used for discovering and provisioning devices.  
  - Includes network, group, and publish-subscribe setup.  
  - Allows device configuration for Device Firmware Update.

Example projects and additional code development can be done with GCC (supplied with Simplicity Studio 5), IAR EWARM, or command line tools.

##### Bootloader Configurations for Firmware Updates

The Silicon Labs Gecko Bootloader is a common bootloader for all the newer wireless MCUs from Silicon Labs. The Gecko Bootloader can be configured to perform a variety of bootload functions, from device initialization to firmware upgrades. The Gecko Bootloader uses a proprietary format for its upgrade images, called GBL (Gecko Bootloader). These images are produced with the file extension “.gbl”.

The bootloader performs a firmware image update by writing the firmware update image to a region of flash memory referred to as the download space. The download space is either an external memory device such as an EEPROM or a section of the device’s internal flash. The bootloader partitions the download space into one or multiple storage slots and stores a single firmware update image in a storage slot.

The bootloader example projects provided in the Gecko SDK Suite come with a preconfigured set of installed components and configurations for different specifications of Silicon Labs MCUs. This section discusses the bootloader example configurations you can use to build bootloaders for Bluetooth mesh applications and firmware updates. You may need to change the storage slot size by configuring the **Bootloader Storage Slot Setup** under Storage components in the Platform > Bootloader Software Components in Simplicity Studio. See Section 7 of [Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](/btmesh/11.0.0/bootloader-user-guide-gsdk-4) for more information about the Gecko Bootloader configurations.

###### Bluetooth Mesh Workspaces for Firmware Update

The Bluetooth Mesh _Distributor_ and _Target_ node examples are available as [SLC workspaces](https://siliconlabs.github.io/slc-specification/latest/format/workspace) which means both the example app and matching bootloader are created during workspace generation.
If a workspace is used, then the bootloader shall not be generated manually.

The firmware update workspace packs the following bootloader variants:

- **Bootloader - SoC Internal Storage (Bluetooth Mesh)**
- **Bootloader - SoC SPI Flash Storage (single image for Bluetooth Mesh)**

These are similar to their counterpart from _bootloader package_ but the storage slot size calculation is performed automatically in case of **Bootloader - SoC Internal Storage (Bluetooth Mesh)** based on the device flash size. The Bluetooth Mesh bootloader variants can be generated in _Simplicity Studio_ through mesh workspaces only.

> **Info**: The generated Bluetooth Mesh bootloader variant can be customized by adding components or modifying configuration. Regular storage bootloader examples can be evaluated as well. See the following sections for details.

###### Internal Flash Size

It is not recommended to use the devices that have internal flash smaller than 768 KB for Target nodes and smaller than 1 MB for the Distributor to store firmware update images. You can use one of the following example projects depending on the internal flash size.

- **Bootloader - SoC Internal Storage (single image on 768kB device)** for Target nodes
- **Bootloader - SoC Internal Storage (single image on 1MB device)**
- **Bootloader - SoC Internal Storage (single image on 1536kB device)**
- **Bootloader - SoC Internal Storage (single image on 1920kB device)**
- **Bootloader - SoC Internal Storage (single image on 2MB device)**

The Target node requires only a single storage slot to store and apply a firmware image. The Distributor can optionally store multiple firmware images but can distribute only one firmware image to Target nodes in a firmware update. To store multiple firmware images on the Distributor, Silicon Labs recommends using external flash for multiple storage slots. The **Bootloader - SoC Internal Storage (multiple images on 1MB device)** example project provides an example configuration of 2 storage slots on internal flash. Use this example for the Distributor if the target device has at least 1920 KB of internal flash.

> **Note**: Silicon Labs recommends using a storage bootloader with a single storage slot. The distributor is able to use that single storage slot to update its own firmware or to distribute it to target nodes.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image1.png)

###### Compressed Update Image

Use the **Bootloader - SoC Internal Storage (single image with LZMA compression, 1MB flash)** example project if the firmware image is too big to fit the storage slot but the compressed firmware image can fit it. [Creating Update Image Archive](03-firmware-update-examples-and-models#creating-the-update-image-archive) describes how to create a compressed firmware image.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image2.png)

###### External Flash

Use the **Bootloader - SoC SPI Flash Storage (single image)** example project if the device's external flash is equal to or larger than 512 KB and smaller than 1 MB. Use the **Bootloader - SoC SPI Flash Storage (single image with slot size of 1024k)** example project if the device’s external flash is equal to or larger than 1 MB. The external flash size should be at least 512 KB for Target nodes and at least 768 KB for the Distributor.

The Target node requires only a single storage slot to store and apply a firmware image. The Distributor can optionally store multiple firmware images but can distribute only one firmware image to Target nodes in a firmware update. Use the **Bootloader - SoC SPI Flash Storage (multiple images)** example project if you need of store multiple firmware images on the Distributor. With the bootloader configuration of 2 storage slots, at least 1 MB of external flash is recommended.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image3.png)

##### Firmware Update Examples and Models

To perform firmware updates, you need an Initiator, a Distributor, and at least one Target node. This section describes the setup to run the **Distributor** and **Target nodes** examples provided in the Bluetooth mesh SDK, and the procedures to create an update image archive. See [Getting Started with Silicon Labs Bluetooth Mesh Development](/btmesh/11.0.0/btmesh-getting-started-overview) for an introduction to configuring and building your own projects, and for a guide to additional resources.

The Initiator and Stand-alone Updater are not discussed in this document. However, these functionalities are demonstrated using the Silicon Labs Bluetooth Mesh mobile app, described in [Firmware Update Demonstration](04-firmware-update-demonstration) and [Firmware Update with Stand-alone Updater](05-firmware-update-with-stand-alone-updater), respectively.

Firmware storage is an important part of the device firmware update process. The flash memory is managed by and accessed via the bootloader. See [Bootloader Configurations for Firmware Updates](02-bootloader-configurations-for-firmware-updates) for the flash configurations. The table in [Appendix – Silicon Labs Product Positioning for Bluetooth Mesh DFU](06-appendix-silicon-labs-product-positioning-for-bluetooth-mesh-dfu) is a recommendation of the Silicon Labs parts for running the DFU roles.

The Bluetooth Mesh _Distributor_ and _Target_ node examples are available as [SLC workspaces](https://siliconlabs.github.io/slc-specification/latest/format/workspace) which means both the example app and matching bootloader are created during workspace generation. Both application and bootloader projects can be built as a single step and the workspace postbuild step merges the two binaries into a single one.

> **Note**: The **SLC workspace** is often called **solution** in Simplicity Studio.

###### Distributor Solution

The Distributor solution is provided as a pre-built demo binary image, ready to download and use, and a corresponding example project that you can modify and then build for the target part. The precompiled demo is only available for selected EFR32xG21 and EFR32xG24 parts.

This section describes how to build the solution and run the example application on a Silicon Labs device. The example is only available for a limited set of parts, including selected xG21 and xG24 parts.

Open Simplicity Studio 6 with a compatible SoC wireless kit connected to the computer. Open the **Devices** page in the vertical navigation bar on the left and select your part.

1. Click the **Example Projects & Demos** tab.
2. To see only the solution projects, turn off **Demos** and **Examples**.
3. Under Technology Type, filter on **Bluetooth Mesh**.
4. Add _dfu distributor_ keyword to the filter text box
5. Next to the **Bluetooth Mesh – SoC DFU Distributor with Internal Storage Bootloader** or **Bluetooth Mesh – SoC DFU Distributor with External Storage Bootloader**, click **CREATE**, modify project settings, click **FINISH**.
6. Build and flash the solution to the device.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image4.png)

The example has the components that are required for the Distributor functionality installed by default. To enable the Distributor functionality in other Bluetooth mesh projects, install the **DFU distributor** component that automatically brings the necessary model components:

1. Open the project .slcp file from Project page located in the vertical navigation bar of Simplicity Studio 6.
2. Click the **Software Components** tab.
3. Select the **DFU distributor** component under **Bluetooth Mesh > DFU Roles** and click **Install**.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image5.png)

This component automatically installs the following model components:

- **Bluetooth Mesh > Models > Firmware Update > Firmware Distribution Server**
- **Bluetooth Mesh > Models > Firmware Update > Firmware Update Client**
- **Bluetooth Mesh > Models > Transport > BLOB Transfer Client**
- **Bluetooth Mesh > Models > Transport > BLOB Transfer Server**

See [DFU Model Configurations](#dfu-model-configurations) for the configurations of these Firmware Update and BLOB Transfer models.

###### Target Node Solution

A Target node is a node whose firmware is to be updated.

The Target solution is provided as a pre-built demo binary image, ready to download and use, and a corresponding example project that you can modify and then build for the target part. The precompiled demos are only available for a limited set of parts, including selected EFR32xG21, xG22 and xG24 parts and MGM21, BGM22 modules. The examples can be built for any part supported by the Bluetooth Mesh SDK.

This section describes how to build the solution and run the example application on a Silicon Labs device. The example is only available for a limited set of parts, including selected xG21, xG22, xG24, xG27 SoC (and modules).

Open Simplicity Studio 6 with a compatible SoC wireless kit connected to the computer. Open the **Devices** page in the vertical navigation bar on the left and select your part.

1. Click the **Example Projects & Demos** tab.
2. To see only the solution projects, turn off **Demos** and **Examples**.
3. Under Technology Type, filter on **Bluetooth Mesh**.
4. Add _dfu target_ keyword to the filter text box
5. Next to the **Bluetooth Mesh - SoC DFU Target with Internal Storage Bootloader** or **Bluetooth Mesh - SoC DFU Target with External Storage Bootloader**, click **CREATE**, modify project settings, click **FINISH**.
6. Build and flash the solution to the device.

> **Note**: EFR32xG22 parts have limited support for Bluetooth Mesh.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image6.png)

The examples have the components that are required for the Target node functionality installed by default. To enable the Target node functionality in other Bluetooth mesh projects, install the **DFU target node** component that automatically brings the necessary model components:

1. Open the project .slcp file from Project page located in the vertical navigation bar of Simplicity Studio 6.
2. Click the **Software Components** tab.
3. Select the **DFU target node** component under **Bluetooth Mesh > DFU Roles** in the left panel and click **Install**.

![screenshot](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image7.png)

This component automatically installs the following model components:

- **Bluetooth Mesh > Models > Firmware Update > Firmware Update Server**
- **Bluetooth Mesh > Models > Transport > BLOB Transfer Server**

See the section below for the configurations of these Firmware Update and BLOB Transfer models.

###### DFU Model Configurations

This section describes the main settings of the Firmware Update and BLOB Transfer models. Open the project **.slcp** file from Project page located in the vertical navigation bar of Simplicity Studio 6.

1. Click the **Software Components** tab.
2. Select **Bluetooth Mesh > Models > Firmware Update** or **Bluetooth Mesh > Models > Transport** in the left panel.
3. Click the gear icon next to the model to be configured.

###### Firmware Distribution Server (heading level 7)

Configuration of **Bluetooth Mesh > Models > Firmware Update > Firmware Distribution Server (sl_btmesh_fw_distribution_server_config.h)**:

<table>
    <thead>
        <tr>
            <th>Configuration Option</th>
            <th>Description</th>
            <th>Default Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3">BT Mesh Firmware Distribution Server Configuration</th>
        </tr>
        <tr>
            <td>Default Multicast Threshold</td>
            <td>If the number of servers for any step exceeds or is equal to this number then the group address will be used, otherwise servers will be looped through one by one. Value of 0 disables the feature.</td>
            <td>1</td>
        </tr>
        <tr>
            <td>Retry time of message transmissions</td>
            <td>Retry time of firmware update message transmissions</td>
            <td>3000</td>
        </tr>
        <tr>
            <td>Amount of concurrent messages sent by the Firmware Distribution server</td>
            <td>Defines how many messages are being sent concurrently by the Firmware Distribution Server. If set to 0, the maximum supported value is used.</td>
            <td>4</td>
        </tr>
        <tr>
            <td>Delay between batches of messages</td>
            <td>Controls the delay in milliseconds between batches of messages. Works in conjunction with "Amount of concurrent messages sent by the Firmware Distribution server" to control message sending rate. When the first transmission in the current batch completes, the sender will wait for this delay before refilling the batch up to the "Amount of concurrent messages sent by the Firmware Distribution server" limit with new transmissions.</td>
            <td>0</td>
        </tr>
        <tr>
            <td>NVM key of the firmware list</td>
            <td>NVM key of the firmware list</td>
            <td>0x400A</td>
        </tr>
        <tr>
            <td>Purge FW list on corruption</td>
            <td>If integrity or consistency issues are found when building the firmware list from persistent data at initialization, then the FW list is purged when this configuration option is enabled, otherwise the corrupted FW list elements are dropped only. The FW list persistent data might be corrupted due to power loss or during FW installation when FW reconstruction from delta patch image requires the whole bootloader storage slot space. If the FW list is modified without the knowledge of the initiator then it could lead to wrong FW distribution when the initiator doesn't query the FW list (cached) before each distribution. (only when FW list length is min 2)</td>
            <td>1</td>
        </tr>
        <tr>
            <td>Enable Logging</td>
            <td>Enable / disable logging of Firmware Distribution Server model specific messages</td>
            <td>1</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Enable BT Mesh Stack Platform Callback Logging</td>
            <td>The FW Distribution Server model in BT Mesh stack calls platform callback functions to query the remaining space, firmware count and firmware information.</td>
            <td>0</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Fwid and metadata log format</td>
            <td>Fwid and metada logging format, hex or text format is available</td>
            <td>false</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Text prepended to every log message</td>
            <td>Every log message in the component is started with this text.</td>
            <td>FwDistributor</td>
        </tr>
    </tbody>
</table>

###### Firmware Update Server (heading level 7)

Configuration of **Bluetooth Mesh > Models > Firmware Update > Firmware Update Server (sl_btmesh_firmware_update_server_config.h)**:

<table>
    <thead>
        <tr>
            <th>Configuration Option</th>
            <th>Description</th>
            <th>Default Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3">General</th>
        </tr>
        <tr>
            <td>Number of firmware on device</td>
            <td>Number of firmware on device &lt;1-255&gt;</td>
            <td>1</td>
        </tr>
        <tr>
            <td>Maximum length of metadata</td>
            <td>Maximum length of metadata &lt;0-255&gt;</td>
            <td>255</td>
        </tr>
        <tr>
            <th colspan="3">Firmware Information</th>
        </tr>
        <tr>
            <td>Firmware identifier</td>
            <td>Firmware identifier</td>
            <td>fwid or &lt;specific_node_id&gt;</td>
        </tr>
        <tr>
            <td>Update URI</td>
            <td>Update URI</td>
            <td>https://example.com/upd_uri</td>
        </tr>
        <tr>
            <td colspan="3">Company Identifier</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;CID MSB</td>
            <td>Most Significant Byte of the Company ID. Hexadecimal string literal.</td>
            <td>\x02</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;CID LSB</td>
            <td>Least Significant Byte of the Company ID. Hexadecimal string literal.</td>
            <td>\xFF</td>
        </tr>
        <tr>
            <th>Logging</th>
            <th>Logging</th>
            <th>1</th>
        </tr>
        <tr>
            <td>Period of verification progress logs [ms]</td>
            <td>Setting it to 0 the user interface (log &amp; display) is updated every time when progress is made.</td>
            <td>200</td>
        </tr>
    </tbody>
</table>

The weak functions for the Firmware Update Server model are mostly implementation-dependent and can be overwritten in the application:

|**Function**|**Description**|
|---|---|
|sl_btmesh_fw_update_server_verify_start()|User callback for determining the maximum chunk size of verification|
|sl_btmesh_fw_update_server_verify_step()|User callback to execute one step of the verification|
|sl_btmesh_fw_update_server_verify_progress_ui_update()|User callback to update the user interface with verification progress|
|sl_btmesh_fw_update_server_metadata_check_start()|User callback indicating start of metadata check|
|sl_btmesh_firmware_update_server_metadata_check_step()|User callback executing one step of metadata check|
|sl_btmesh_fw_update_server_update_start()|User callback indicating update start|
|sl_btmesh_fw_update_server_update_canceled()|User callback indicating update cancellation|
|sl_btmesh_fw_update_server_update_aborted()|User callback indicating update abort|
|sl_btmesh_fw_update_server_apply()|User callback indicating firmware apply request|

See `<sdk>/bluetooth_mesh_middleware/common/btmesh_firmware_update_server/sl_btmesh_firmware_update_server_api.h` for further information.

A Target node will become unprovisioned by default after a firmware update. You can overwrite this behavior in the following functions:

- `sl_btmesh_fw_update_server_metadata_check_start()` or `sl_btmesh_firmware_update_server_metadata_check_step()` – set another value to `*additional_information`. The additional information is provided to the Bluetooth mesh stack and will appear in the Firmware Update Status and Firmware Update Firmware Metadata Status messages.  
  ```c  
  *additional_information = BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION;  
  ```  
  ```c  
  if (BOOTLOADER_OK == bootloader_setImageToBootload(idx)) {  
    // Erase persistent mesh data stored in NVM and make the node unprovisioned  
    // only based on the result of metadata check  
    if (fw_additional_information == BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION) {  
      // Reset node  
      sl_btmesh_node_reset();  
      // Erase NVM data  
      app_btmesh_nvm_erase_all();  
    }  
    // Delay install  
    app_timer_start(&timer, 1000, apply_step, NULL, true);  
    apply_cntdwn = APPLY_DELAY;  
  }  
  ```

###### BLOB Transfer Client (heading level 7)

Configuration of **Bluetooth Mesh > Models > Transport > BLOB Transfer Client (sl_btmesh_blob_transfer_client_config.h)**:

<table>
    <thead>
        <tr>
            <th>Configuration Option</th>
            <th>Description</th>
            <th>Default Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3">BT Mesh BLOB Transfer Client Configuration</th>
        </tr>
        <tr>
            <td>Enable Logging</td>
            <td>Enable / disable logging of BLOB Transfer Client model specific messages</td>
            <td>1</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Text prepended to every log message</td>
            <td>Every log message in the component is started with this text.</td>
            <td>BlobTfClient</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Log BLOB Status messages</td>
            <td>Log the content of BT Mesh BLOB status messages.</td>
            <td>1</td>
        </tr>
        <tr>
            <td colspan="3">BLOB Transfer Limits</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Max number of servers</td>
            <td>Maximum number of BLOB transfer servers which can be serviced in a transfer (affects BT Mesh stack memory usage)</td>
            <td>4</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Max number of blocks</td>
            <td>Maximum number of blocks supported in a BLOB Transfer (affects BT Mesh stack memory usage)</td>
            <td>1024</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Max number of chunks per block</td>
            <td>Maximum number of chunks per block supported in a BLOB Transfer (affects BT Mesh stack memory usage). WARNING! If the number of chunks per block exceeds 40 in case of Push BLOB Transfer Mode then high number of BLOB Block Status messages become segmented which could make the BLOB Transfer slower and less robust. Note: Format field of BLOB Block Status message affects the size of the message as well so the segmentation occurs over 40 chunks per block when the format is Some Chunks Missing (0x2).</td>
            <td>40</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Max chunk size</td>
            <td>Maximum chunk size which can be selected during BLOB Transfer</td>
            <td>241</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Preferred chunk size</td>
            <td>If the preferred chunk size is supported by all BLOB Transfer Servers then the default chunk size calculation algorithm tries to select it as chunk size of the block otherwise the chunk size is set to the closest value which fills all segments of the chunk. There is a tradeoff between small and large chunks. The normal (non-AE) segmented chunks are able to transfer 12 bytes per advertisement minus the 1 byte opcode and 2 byte chunk number and 4 bytes of MIC. This means N regular advertisements are able to transfer 12 x N - 7 bytes of chunk data. If N is a big number then the payload per message converges to 12 but if N is low then the fixed 7 byte protocol overhead penalty becomes significant. If there is noise and at least one segment is lost then the whole chunk needs to be retransmitted. Probability of transfer failure is higher for long segmented chunks and it takes more time to retransmit a long chunk. The chunk size can't be arbitrarily low because the max number of chunks per block multiplied by the chunk size shall be greater than or equal to block size. A low chunk size leads to more chunks per block which has negative effects when the number of chunks per block exceeds 40, because the BLOB Block Status message becomes segmented, which means all servers starts to respond with segmented messages. This might have significant impact on the transfer speed. Chunk size with 5 full segments is used as default preferred chunk size because in this case the (12 x N - 7) / (12 x N) = 88% of the ideal (non-noisy) transfer speed is preserved and 40 x (12 x N - 7) = 2120 -&gt; 2048 (2^N) byte blocks can be used without BLOB Block Status message segmentation. If BT Mesh over Advertisement Extension Silabs proprietary feature is turned on then the default chunk calculation algorithm selects the chunk size to fill the AE packet completely with chunk data based on the network PDU size if the chunk size is supported by the BLOB Transfer Servers, otherwise it falls back to the preferred chunk size calculation. (see Advertisement Extension Server component for details)</td>
            <td>53</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Chunk size should be a multiple of this value</td>
            <td>The chunk size selected during BLOB Transfer should be a multiple of this value. This is useful when the BLOB Transfer Server has a specific requirement for the chunk size that cannot be negotiated with the standard Bluetooth Mesh BLOB Transfer model. If other transfer parameters would prohibit the selection of a chunk size that would satisfy this requirement, those take precedence.</td>
            <td>1</td>
        </tr>
        <tr>
            <td colspan="3">Retry and Separation parameters</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Default separation time between chunks</td>
            <td>Default minimum separation time between two chunks in the same block</td>
            <td>0</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Default max local retry of message transmission requests</td>
            <td>Default local max retries of message transmission requests during query info, transfer start, block start, block query chunk transfer and transfer cancel procedures. Default max local retry is used when the BT Mesh stack rejects sending BLOB Transfer messages due to a recoverable error, so BT Mesh stack API returns with recoverable error code, for example due to lack of memory.</td>
            <td>1000</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Default retry threshold of frequent message transmissions</td>
            <td>Default retry threshold of frequent message transmissions during query info, transfer start, block start, block query and transfer cancel procedures before infrequent message transmission is activated with doubled retry time.</td>
            <td>200</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Default local retry time [ms]</td>
            <td>Default local retry time of message transmission requests during query info, transfer start, block start, block query, chunk transfer and transfer cancel procedures. Default local retry time is used when the BT Mesh stack rejects sending BLOB Transfer messages due to a recoverable error, so BT Mesh stack API returns with recoverable error code, for example due to lack of memory.</td>
            <td>500</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Default retry time for push transfer [ms]</td>
            <td>Default retry time of message transmissions during push transfer. The transfer start, block start, block query and transfer cancel procedures use this retry time during push transfer to send the proper procedure specific message again if at least one receiver haven't responded when retry timeout is reached. The query info procedure use this retry time value when the push transfer mode is selected explicitly by upper layer or both transfer modes (push &amp; pull) are allowed by the upper layer. Rationale: transfer mode is chosen after query info procedure in this case. Note: if the expected procedure specific status message is received from a receiver then the retry time measurement is started again to avoid too early message retransmission while the receivers are still responding otherwise the interference between receiver nodes would be even higher.</td>
            <td>2000</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Default retry time for pull transfer [ms]</td>
            <td>Default retry time of message transmissions during pull transfer. The transfer start, block start, block query and transfer cancel procedures use this retry time during pull transfer to send the proper procedure specific message again if at least one receiver haven't responded when retry timeout is reached. The query info procedure use this retry time when the pull transfer mode is selected explicitly by upper layer. Note: if the expected procedure specific status message is received from a receiver then the retry time measurement is started again to avoid too early message retransmission while the receivers are still responding otherwise the interference between receiver nodes would be even higher.</td>
            <td>4000</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Amount of concurrent messages sent by the BLOB Transfer client</td>
            <td>Defines how many messages are being sent concurrently by the BLOB Transfer Client. If set to 0, the maximum supported value is used.</td>
            <td>4</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Delay between batches of messages</td>
            <td>Controls the delay in milliseconds between batches of messages. Works in conjunction with "Amount of concurrent messages sent by the BLOB Transfer client" to control message sending rate. When the first transmission in the current batch completes, the sender will wait for this delay before refilling the batch up to the "Amount of concurrent messages sent by the BLOB Transfer client" limit with new transmissions.</td>
            <td>0</td>
        </tr>
    </tbody>
</table>

The weak functions for the BLOB Transfer Client model are mostly implementation-dependent and can be overwritten in the application:

|**Function**|**Description**|
|---|---|
|sl_btmesh_blob_transfer_client_calculate_block_size_log()|Calculates the binary logarithm of the block size for the current BLOB transfer from the provided parameters which are the result of the Retrieve Capabilities procedure of the BLOB Transfer. The parameters passed represent the aggregated capabilities of the BLOB transfer client and every BLOB transfer server which participates in the current transfer. The default implementation calculates the greatest possible block size from the parameters. If another implementation is required then the strong symbol definition shall be provided for this function with the implementation in the application code.|
|sl_btmesh_blob_transfer_client_calculate_chunk_size()|Calculates the chunk size for the next block in the current BLOB transfer from the previously selected binary logarithm of the block size and from the result of the Retrieve Capabilities procedure of the BLOB Transfer. If the configurable preferred chunk size is supported by all BLOB Transfer Servers then the default chunk size calculation algorithm selects it as chunk size of the block otherwise the chunk size is set to the closest value which fills all segments of the chunk. If another implementation is required then the strong symbol definition shall be provided for this function with the implementation in the application code.|

See `<sdk>/bluetooth_mesh_middleware/common/btmesh_blob_transfer_client/sl_btmesh_blob_transfer_client.h` for further information.

###### BLOB Transfer Server (heading level 7)

Configuration of **Bluetooth Mesh > Models > Transport > BLOB Transfer Server Core (sl_btmesh_blob_transfer_server_config.h)**:

<table>
    <thead>
        <tr>
            <th>Configuration Option</th>
            <th>Description</th>
            <th>Default Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3">General</th>
        </tr>
        <tr>
            <td>Logging</td>
            <td>Logging</td>
            <td>1</td>
        </tr>
        <tr>
            <td>LPN poll logging</td>
            <td>LPN poll logging</td>
            <td>0</td>
        </tr>
        <tr>
            <td>Transfer Start user callback</td>
            <td>Enable/disable callback function when BLOB transfer starts.</td>
            <td>1</td>
        </tr>
        <tr>
            <td>Transfer Progress user callback</td>
            <td>Enable/disable callback function when block transfer is finished.</td>
            <td>1</td>
        </tr>
        <tr>
            <td>Transfer Done user callback</td>
            <td>Enable/disable callback function when BLOB transfer is finished.</td>
            <td>1</td>
        </tr>
    </tbody>
</table>

Configuration of **Bluetooth Mesh > Models > Transport > BLOB Transfer Server (dfu_dist/dfu_target - sl_btmesh_blob_transfer_server_dfu_<dist/target>_config.h)**:

<table>
    <thead>
        <tr>
            <th>Configuration Option</th>
            <th>Description</th>
            <th>Default Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3">General</th>
        </tr>
        <tr>
            <td>Min Block Size Log</td>
            <td>Please note, that decreasing the minimum block size will result in increased heap usage. Block states need to be monitored. The smaller the blocks, the bigger the state storage. Change this value with care.</td>
            <td>0x9</td>
        </tr>
        <tr>
            <td>Max Block Size Log</td>
            <td>Please note, that increasing the maximum block size will result in increased heap usage. Blocks are cached on heap before being written into NVM. Change this value with care.</td>
            <td>0x9</td>
        </tr>
        <tr>
            <td>Block Buffer Memory Type</td>
            <td>If Static is selected then RAM buffer is allocated statically at link time for the worst case Max BLOB Block Size. If Heap is selected then RAM buffer is allocated from the heap at runtime when the BLOB transfer is started and the buffer is deallocated when the BLOB transfer is completed or cancelled. If None is selected then no RAM buffer is allocated. The Heap provides the following advantages over Static block buffer memory type:
                <ul>
                    <li>The block buffer memory is allocated for the BLOB transfer only.</li>
                    <li>The size of allocated block buffer memory is calculated from the actual Block Size Log from BLOB Transfer Start message which might be lower than Max BLOB Block Size.</li>
                </ul>
                The Static provides the following advantages over Heap block buffer memory type:
                <ul>
                    <li>It is guaranteed that Block Buffer Memory is available for BLOB Transfer which improves robustness. Example: if there is a memory leak in the application then it might be impossible to run a firmware update through BLOB Transfer Server without resetting the device because it can't allocate the block buffer memory from the heap.</li>
                </ul>
                The None may be used in special cases, where very large block sizes are used, e.g. large enough to fit the whole BLOB in a single block. As the flash writing has alignment requirements, this mode needs special coordination with the BLOB Transfer Client to ensure a suitable chunk size is used. Note: The BLOB Transfer Server should have buffer for the whole block during BLOB transfer because the BLOB Chunk Transfer messages can be received in any order (e.g. due to interference). The Chunk Data of BLOB Chunk Transfer can't be written in the flash at reception, unless the data size is a multiple of flash write size (alignment).
            </td>
            <td>Heap</td>
        </tr>
        <tr>
            <td>Maximum of number of chunks per block</td>
            <td>Maximum of number of chunks per block</td>
            <td>40</td>
        </tr>
        <tr>
            <td>Maximum chunk size</td>
            <td>If the max chunk size is 8 then the chunk data fits into a single BT Mesh advertisement message. If the chunk data is segmented then N segments is able to transfer (N*12)-7 byte data. The advantage of higher chunk size is the higher throughput in low noise environment. The advantage of lower chunk size is that fewer messages are retransmitted in high noise environment due to lost chunk messages. LPN only: the number of chunk messages (segments) multiplied by requested chunk count in partial block report shall fit into the friend queue.</td>
            <td>241</td>
        </tr>
        <tr>
            <th>Override Element Index</th>
            <th>Default element index is provided by project or components. If the default element index is not sufficient then it can be overridden by activating this option.</th>
            <th>0</th>
        </tr>
        <tr>
            <td>Element Index</td>
            <td>Element index of BLOB Transfer Server model instance. It has an effect only when "Override Element Index" configuration option is activated. Range: 0-255, Default: 0</td>
            <td>0</td>
        </tr>
        <tr>
            <th colspan="3">Supported Transfer Modes</th>
        </tr>
        <tr>
            <td>Push Mode</td>
            <td>Push BLOB Transfer Mode.</td>
            <td>1 / LPN: 0</td>
        </tr>
        <tr>
            <td>Pull Mode</td>
            <td>Pull BLOB Transfer Mode.</td>
            <td>1</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Number of chunks requested in Block Status or Partial Block Report</td>
            <td>Number of chunks requested in Block Status or Partial Block Report</td>
            <td>3</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Interval, in milliseconds, between Partial Block Reports, if nothing is received</td>
            <td>Interval, in milliseconds, between Partial Block Reports, if nothing is received</td>
            <td>1000</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;Number of retries sending the same Partial Block Report, before giving up</td>
            <td>Number of retries sending the same Partial Block Report, before giving up</td>
            <td>8</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;LPN Mode</td>
            <td>Only pull transfer mode can be used on LPN nodes.</td>
            <td>0 / LPN: 1</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPN high throughput mode</td>
            <td>In high throughput mode the LPN node polls the friend node more frequently to increase the throughput at the expense of power consumption.</td>
            <td>1</td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPN poll delay in milliseconds</td>
            <td>The delay of first LPN poll when the BLOB Transfer Server expects messages from the client after an event. The major part of BLOB transfer to LPN is the waiting for the poll timeout to elapse in order to poll the friend node for BLOB Transfer messages. The maximum number of messages can be transferred per polling equals to friend queue size during BLOB transfer to LPN. This poll delay configuration parameter value makes the polling more frequent when BLOB Transfer messages are expected to increase the throughput. The LPN poll delay shall be less than SL_BTMESH_LPN_POLL_TIMEOUT_CFG_VAL in sl_btmesh_lpn_config.h file.</td>
            <td>500</td>
        </tr>
    </tbody>
</table>

###### Creating the Update Image Archive

An update image archive is a **gzip** archive file that consists of:

- **Manifest**: a file named **manifest.json**, which is in the format of JavaScript Object Notation (JSON). It contains a description of the firmware package, including the name of the firmware image file and an optional metadata file for the update.
- **Firmware Image**: the firmware image file in GBL format, as identified in the manifest file.
- **Metadata**: an optional file provided by the vendor and identified in the manifest file, that may provide metadata for the firmware image.

This section describes the procedure to generate a firmware image, manifest file, and update image archive.

###### Step 1: Generating a firmware image (heading level 7)

Building a C-based Bluetooth mesh solution in _Simplicity Studio_ automatically generates the OTA DFU update images (GBL files).
The solution and each project in the solution have their own [post build file (slpb)](https://siliconlabs.github.io/slc-specification/latest/workspace/post-build/) which specifies which post build actions shall be executed and their parameters. The GBL files are generated as post build steps.

If the GBL creation needs to be customized (e.g. compression, encryption) then open the _.slpb_ file from Project page located in the vertical navigation bar to launch **Post Build Editor** in _Simplicity Studio 6_. The **Post Build Editor** can be used to modify the post build steps in Simplicity Studio 6.
The post build steps execute _Simplicity Commander_ commands in the background.
You can find more details on the following pages:

- [Post-Build Editor (PBE)](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-building-and-flashing/post-build-editor)
- [Simplicity Commander](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/)
- [Execute a Project Post-Build File](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-commands/post-build-command)

Two GBL files are generated into the `<workspace-path>/artifact` and `<workspace-path>/<app-name>/artifact` directories by post build steps:

- `<app-name>.gbl`: use when application shall be updated
- `<workspace-name>.gbl`: use when both bootloader and application shall be updated

If you use a bootloader that supports LZMA compression of the firmware update image, as described in [Compressed Update Image](02-bootloader-configurations-for-firmware-updates#compressed-update-image), you should compress the GBL file by selecting **lzma** option from **Compression** drop-down menu in **Post Build Editor** for each GBL generation step.

For more information about the GBL file format, see [Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](/btmesh/11.0.0/bootloader-user-guide-gsdk-4/02-gecko-bootloader-file-format).

###### Step 2: creating a manifest file and firmware archive (heading level 7)

Run `FirmwareArchiveGenerator.py` from `<sdk>/bluetooth_mesh_middleware/script/generator` to generate the firmware archive.

`python FirmwareArchiveGenerator.py -i <workspace-path>/<app-name> -o <workspace-path>/<app-name>/artifact/archive`

> ℹ️ **Note:** The `pyelftools` package is required to run `FirmwareArchiveGenerator.py`. Install it using `pip install pyelftools` before executing the command.

The script creates a file named **manifest.json** that is a text file in JSON format containing the name of the firmware update image, the firmware ID and optionally the name of the metadata file. The format of the `manifest/firmware/firmware_id` member is **Base16**. The `manifest/firmware/metadata_file` member contains the metadata file name if present. The following is an example of the content of the manifest.json file.

```json
{
  "manifest": {
    "firmware": {
      "firmware_image_file": "btmesh_soc_dfu_target.gbl",
      "metadata_file": "btmesh_soc_dfu_target_metadata.bin",
      "firmware_id": "ff02736f6362746d747267745f7631"
    }
  }
}
```

The script extracts the firmware ID and metadata from the `out` (elf) file by default.
The firmware ID is extracted from a constant variable, which stores the `SL_BTMESH_FW_UPDATE_SERVER_FWID_CFG_VAL` configuration parameter of _Firmware Update Server_ model in the application. The metadata is extracted from a constant variable, which stores the Device Composition Data (DCD) Page 0 configured by _Bluetooth Mesh Configurator_ in the application.

If you want to provide the firmware ID and metadata file manually, you can use the following command line options:

- `--fwid <firmware_id>`: specify the firmware ID as hexadecimal string
- `--metadata <metadata>`: specify the metadata as hexadecimal string  
  The script creates the standard gzip archive `<app-name>.gz` in the specified output directory.

The script runs the equivalent of the following command to create the gzip archive:

```sh
tar czf btmesh_soc_dfu_target_firmware.gz btmesh_soc_dfu_target.gbl btmesh_soc_dfu_target_metadata.bin manifest.json
```

##### Firmware Update Demonstration

This section assumes you have flashed the **Bluetooth Mesh – SoC DFU Distributor** example application to one of the devices and the **Bluetooth Mesh – SoC Light** example application to the other(s) and have created an update image archive for the light example. [Firmware Update Examples and Models](03-firmware-update-examples-and-models) describes the setup of the examples and the update image archive.

The Bluetooth Mesh SDK comes with a DFU Python script that supports the provisioner and initiator functionalities. To use the script to update device firmware, see [Provisioning and Firmware Update Using the DFU Python Script](/btmesh/11.0.0/btmesh-provisioning-firmware-update-with-dfu-python-script).

The examples display firmware update status on the device’s LCD and output detailed information of the firmware update process to VCOM UART. To see the logs, open a serial terminal on the serial port assigned for the device with the following serial settings: baud rate 115200, data bits 8, stop bits 1 and parity None.

1. Provision and configure the Distributor node.  
   1. Go to the Provision view and tap **Scan** at the top right.  
   2. Tap **PROVISION** next to the Distributor device and tap **Continue** at the top right.  
   3. In the Device Configuration view, tap **Group** and then select Demo group.  
   4. In the Device Configuration view, tap **Functionality** and then select **Firmware Distribution Server.**    
      ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image8.png)
2. Provision and configure at least one Target node.  
   1. Go to the Provision view and tap **Scan** at the top right.  
   2. Tap **PROVISION** next to a Light device and tap **Continue** at the top right.  
   3. In the Device Configuration view, tap **Group** and then select Demo group.  
   4. In the Device Configuration view, tap **Functionality** and then select a functionality for the node. The **Firmware Update Server** functionality required for the firmware update is invisible but is automatically bound to the selected functionality.  
   5. Repeat above steps for all Target nodes.    
      ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image9.png)
3. Go to the Networks view and tap **Demo network**. Make sure the Distributor node has the active proxy connection.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image10.png)
4. Tap **Firmware distribution** under the Distributor node and then tap **Firmware File**.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image11.png)
5. Choose an update image.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image12.png)
6. In the Firmware distribution view, select the nodes to update firmware, and then tap **Upload to nodes**.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image13.png)
7. The mobile app as the Initiator uploads the update image to the Distributor node and shows the progress. When the progress reaches 100%, tap **Done**.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image14.png)
8. The Distributor node then distributes the update image simultaneously to the selected nodes. The mobile app updates the distribution progress periodically.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image15.png)
9. When the distribution is done, the Target nodes verify the update image.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image16.png)
10. The Distributor node then instructs the nodes that have successfully verified the update image to apply the update image.  
    ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image17.png)
11. Finally, the mobile app shows update results.

![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image18.png)

##### Firmware Update with Stand-Alone Updater

The Silicon Labs Bluetooth Mesh mobile app has the Stand-alone Updater feature that manages the delivery of the firmware image to Target nodes without an intermediary Distributor. To use the feature to perform a firmware update, you should have the node whose firmware is to be updated provisioned to a mesh network.

Refer to Step 2 in [Firmware Update Demonstration](04-firmware-update-demonstration) for provisioning and configuring a light node, and then follow the steps below to update the device’s firmware directly.

1. Go to the Networks view, tap **Demo network**, and select the light node.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image19.jpg)
2. Tap **Firmware Update** in the Configuration view.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image20.jpg)
3. Tap **Pick a file** and choose an update image, and then tap **Upload and apply**.  
   ![image](/btmesh-device-firmware-update-example/10.0.0/images/sld780-image21.jpg)

##### Appendix – Silicon Labs Product Positioning for Bluetooth Mesh DFU

Bluetooth Mesh DFU requires significant space in flash memory to store firmware images. The table below suggests suitable roles for Silicon Labs parts.

<table>
    <thead>
        <tr>
            <th>Part (Flash, RAM)</th>
            <th>Distributor</th>
            <th>Target Node</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td colspan="3"><strong>xG1</strong></td>
        </tr>
        <tr>
            <td>256kB, 32kB</td>
            <td>No</td>
            <td>No</td>
        </tr>
        <tr>
            <td colspan="3"><strong>xG12</strong></td>
        </tr>
        <tr>
            <td>512kB, 64kB</td>
            <td>No</td>
            <td>No (External Flash: Yes)</td>
        </tr>
        <tr>
            <td>1MB, 256kB</td>
            <td>Yes</td>
            <td>Yes</td>
        </tr>
        <tr>
            <td colspan="3"><strong>xG13</strong></td>
        </tr>
        <tr>
            <td>512kB, 64kB</td>
            <td>No</td>
            <td>No (External Flash: Yes)</td>
        </tr>
        <tr>
            <td colspan="3"><strong>xG21</strong></td>
        </tr>
        <tr>
            <td>512kB, 96kB</td>
            <td>No</td>
            <td>No (External Flash: Yes)</td>
        </tr>
        <tr>
            <td>768kB, 96kB</td>
            <td>No (External Flash: Yes)</td>
            <td>Yes</td>
        </tr>
        <tr>
            <td>1MB, 96kB</td>
            <td>Yes</td>
            <td>Yes</td>
        </tr>
        <tr>
            <td colspan="3"><strong>xG22</strong></td>
        </tr>
        <tr>
            <td>352kB, 32kB</td>
            <td>No</td>
            <td>No</td>
        </tr>
        <tr>
            <td>512kB, 32kB</td>
            <td>No</td>
            <td>No (External Flash: Yes)</td>
        </tr>
        <tr>
            <td colspan="3"><strong>xG24</strong></td>
        </tr>
        <tr>
            <td>1536kB, 256kB</td>
            <td>Yes</td>
            <td>Yes</td>
        </tr>
    </tbody>
</table>

#### Provisioning and Firmware Update Using the DFU Python Script

##### Provisioning and Firmware Update Using the DFU Python Script

**NOTE: This section replaces _AN1422: Provisioning and Firmware Update Using the DFU Python Script_. Further updates to this application note will be provided here.**

This application note walks through a device firmware update demonstration using the DFU Python script. The script is an NCP host application that requires an NCP node connected. The user can provision, configure, and manage mesh devices, as well as perform a device firmware update through the NCP node.

The Bluetooth Mesh Model specification v1.1 defines a standard way to update device firmware over a Bluetooth mesh network. This document walks through a firmware update demo using the DFU Python script and the Bluetooth mesh examples, installed as part of the Bluetooth Mesh SDK. The DFU Distributor example runs as the Distributor node. The Light, Switch, Sensor Client, or Sensor Server example runs as the node whose firmware is to be updated, called the Target node, and the DFU Python script is used to provision these nodes and runs as the Initiator node.

To understand the basics of the Bluetooth Mesh Device Firmware Update specification, see [Bluetooth Mesh Device Firmware Update](/btmesh/11.0.0/btmesh-device-firmware-update).

##### Getting Started with the DFU Python Script

The DFU Python script is an NCP host application running on a system with a Python interpreter, and the application requires the Bluetooth mesh stack running in NCP mode on a Silicon Labs device connected to the system. Two or more additional Silicon Labs devices running the DFU examples are needed to perform a device firmware update. To run the DFU examples provided in the Bluetooth Mesh SDK, see [Bluetooth Mesh Device Firmware Update Example Walkthrough](/btmesh/11.0.0/btmesh-device-firmware-update-example).

###### Requirements

The following is required to run the DFU Python script.

- One mainboard with a supported board installed for the NCP target application.
- [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio)
- Gecko SDK Suite 4.2.2 (Bluetooth Mesh SDK 4.2.0) or later, distributed through Simplicity Studio 5. The prebuilt demos and examples are included in the SDK.
- A host system with a Python interpreter, such as MacOS, Linux, or Windows.
- The Python package [PyBGAPI](https://pypi.org/project/pybgapi/) installed in the host system.

To install PyBGAPI, run:

```sh
pip3 install pybgapi
```

Run `pip3 list`. The `pybgapi` package should be version 1.2.0 or later:

```sh
Package     Version
----------  -------
...
pybgapi     1.2.0
pyserial    3.5
...
```

###### Bluetooth Mesh – NCP Empty v1.1 Application

The **Bluetooth Mesh – NCP Empty v1.1** example application is the target application running on a Silicon Labs device. The application is provided as a prebuilt demo binary image, ready to download and use, and a corresponding example project that you can modify and then build for the target part. If you want to build your own projects based on the example project, see the [Getting Started Guide](/btmesh/11.0.0/btmesh-getting-started-overview/). This section describes how to install the prebuilt demo binary to the device.

The precompiled demos are only available for a limited set of parts, including selected EFR32xG13 and xG21 parts and BGM13 and MGM21 modules. The examples can be built for any part supported by the Bluetooth Mesh SDK.

> **Note**: EFR32xG22 parts can run the **Bluetooth Mesh – NCP Empty v1.1** example but do not support provisioner functionality.

1. Open Simplicity Studio 5 with a compatible SoC wireless kit connected to the computer.
2. Select the part in **Debug Adapters** view to open the Launcher perspective.
3. Click the **Example Projects & Demos** tab.
4. To see only the demos, turn off the **Example Projects**.
5. Under **Technology Type**, filter on **Bluetooth Mesh**. Next to **Bluetooth Mesh – NCP Empty v1.1**, click **RUN**.  
   ![screenshot](/btmesh-provisioning-firmware-update-with-dfu-python-script/0.1/images/sld781-image1.png)

###### DFU Python Script

The DFU Python script is the host application running on a computer. Connect the Silicon Labs device running the **Bluetooth Mesh – NCP Empty v1.1** example application to the computer on a USB port. Check the serial port information for the connected device.

On Windows, you can find the serial port number in Device Manager, e.g. `COM7`.

On Linux, you can run the `ls /dev/ttyS*` command in a terminal to list the device file, e.g. `/dev/ttyS0`.

On MacOS, you can run the ls `/dev/tty.usb*` command in a terminal to list the device file, e.g. `/dev/tty.usbmodem0004401234561`.

Open a terminal and change the directory to the path _app/btmesh/example_host/btmesh_host_dfu_ of Gecko SDK. Run `python3 btmesh_host_dfu.py --usb <usb>` and you should not get any error message.

```sh
python3 btmesh_host_dfu.py --usb /dev/tty.usbmodem0004401234561
```

If you are running the script in a directory other than the path to the script folder under Gecko SDK, you need to specify the API files with the `--xapi` option.

```sh
python3 btmesh_host_dfu.py --usb /dev/tty.usbmodem0004401234561 --xapi /Users/<user>/SimplicityStudio/SDKs/gecko_sdk/protocol/bluetooth/api/sl_bt.xapi --xapi /Users/<user>/SimplicityStudio/SDKs/gecko_sdk/protocol/bluetooth/api/sl_btmesh.xapi
```

The script generates 3 files on the first run:

- `btmesh_host_dfu_cfg.ini`: the configuration file the script reads to set command parameters and settings of model profiles. The script generates default values of the configuration options in the script if the configuration file doesn't exist.
- `btmesh_host_dfu_persistence.json`: the script saves its persistent states to the file and loads data from the file on each CLI command and interactive session.
- `btmesh_host_dfu.log`: the log file of the script's executions containing what BGAPI commands and events the script has sent and received. The log file could be helpful when something went wrong.

The script provides command line and interactive modes. You can run the script with the `--help` option to see the script usage and command descriptions in command line mode. The demonstration in [Firmware Update Demonstration Using the DFU Python Script](03-firmware-update-demonstration-using-the-dfu-python-script) will run the script in interactive mode.

```sh
python3 btmesh_host_dfu.py --usb /dev/tty.usbmodem0004401234561 --interactive
```

##### Firmware Update Demonstration Using the DFU Python Script

This section assumes you have installed the **Bluetooth Mesh – NCP Empty v1.1** demo binary to one of the devices, the **Bluetooth Mesh – SoC DFU Distributor** example application to another, and the **Bluetooth Mesh – SoC Light** example application to the other(s). You should also have generated a firmware update image for the light example. Copy the firmware update image `application.gbl` to the root of the script’s directory, run the script in the interactive mode, and then follow the steps below to perform a firmware update.

> **Note**: the DFU Python script sends the GBL file directly to the mesh network.

[Getting Started with the DFU Python Script](02-getting-started-with-the-dfu-python-script) and [Bluetooth Mesh Device Firmware Update Example Walkthrough](/btmesh/11.0.0/btmesh-device-firmware-update-example) describe the setup of the examples and the preparation of the firmware update image.

The examples display firmware update status on the device’s LCD and output detailed information of the firmware update process to VCOM UART. To see the logs, open a serial terminal on the serial port assigned for the device with the following serial settings: baud rate 115200, data bits 8, stop bits 1 and parity None.

1. Perform a factory reset on the provisioner.  
   ```sh  
   >>>reset --type factory  
   Factory reset completed  
   ```
2. Provision all devices.  
   Issue the `prov` command with the `--scan` option. The parameter `.3` stands for 300 milliseconds.  
   ```sh  
   >>>prov --scan .3  
   Scanning for unprovisioned nodes...  
   Unprovisioned beacon: uuid=994c62c4bf480f51bb3995094a266ec2, bearer=PB-GATT, address=68:0a:e2:dd:29:4a, ad-dress_type=Public, rssi=-33  
   Unprovisioned beacon: uuid=5100db6c367ef95aaec40a95fee47966, bearer=PB-GATT, address=d0:cf:5e:68:aa:29, ad-dress_type=Public, rssi=-28  
   Unprovisioned beacon: uuid=36494ea9987db45588b29a7b900a9da2, bearer=PB-GATT, address=84:71:27:6e:f2:cd, ad-dress_type=Public, rssi=-1  
   ...  
   ...  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |   Idx    |               UUID                 |  Bearer   |       Address       | Address Type   |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |    0     |  36494ea9987db45588b29a7b900a9da2  |  PB-GATT  |  84:71:27:6e:f2:cd  |    Public      |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |    1     |  36494ea9987db45588b29a7b900a9da2  |  PB-ADV   |  84:71:27:6e:f2:cd  |    Public      |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |    2     |  5100db6c367ef95aaec40a95fee47966  |  PB-GATT  |  d0:cf:5e:68:aa:29  |    Public      |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |    3     |  5100db6c367ef95aaec40a95fee47966  |  PB-ADV   |  d0:cf:5e:68:aa:29  |    Public      |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |    4     |  994c62c4bf480f51bb3995094a266ec2  |  PB-GATT  |  68:0a:e2:dd:29:4a  |    Public      |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   |    5     |  994c62c4bf480f51bb3995094a266ec2  |  PB-ADV   |  68:0a:e2:dd:29:4a  |    Public      |  
   +----------+------------------------------------+-----------+---------------------+----------------+  
   Select devices to provision  
   Comma/Space separated list of indexes, BT addresses or UUIDs  
   ```  
   When it prompts to select devices to provision, select the **PB-ADV** bearer of devices. In the example, the index 3 is the Distributor device and the indices 1 and 5 are the Light devices.  
   ```sh  
   Devices:3,1,5  
   The device with 5100db6c367ef95aaec40a95fee47966 UUID is provisioned.  
   The device with 36494ea9987db45588b29a7b900a9da2 UUID is provisioned.  
   The device with 994c62c4bf480f51bb3995094a266ec2 UUID is provisioned.  
   ```
3. Rename nodes for easy identification.  
   Issue the `node list` command to show the nodes in the mesh network.  
   ```sh  
   >>>node list  
   +------------+-----------------+--------------------------------------+-------------+--------------+  
   |    Idx     |      Name       |                 UUID                 |   Address   |   Elements   |  
   +------------+-----------------+--------------------------------------+-------------+--------------+  
   |     0      |    Node_2005    |   5100db6c367ef95aaec40a95fee47966   |   0x2005    |      1       |  
   +------------+-----------------+--------------------------------------+-------------+--------------+  
   |     1      |    Node_2006    |   36494ea9987db45588b29a7b900a9da2   |   0x2006    |      3       |  
   +------------+-----------------+--------------------------------------+-------------+--------------+  
   |     2      |    Node_2009    |   994c62c4bf480f51bb3995094a266ec2   |   0x2009    |      3       |  
   +------------+-----------------+--------------------------------------+-------------+--------------+  
   |    3       |   Provisioner   |   764b0e71f3fc5c5ab856d6e1a90b4e32   |   0x2001    |      4       |  
   +------------+-----------------+--------------------------------------+-------------+--------------+  
   ```  
   Issue the node rename command to rename nodes.  
   ```sh  
   >>>node rename Node_2005 Distributor_2005  
   >>>node rename Node_2006 Light_2006  
   >>>node rename Node_2009 Light_2009  
   >>>node list  
   +-----------+---------------------+-------------------------------------+------------+-------------+  
   |    Idx    |        Name         |                UUID                 |  Address   |  Elements   |  
   +-----------+---------------------+-------------------------------------+------------+-------------+  
   |     0     |  Distributor_2005   |  5100db6c367ef95aaec40a95fee47966   |   0x2005   |      1      |  
   +-----------+---------------------+-------------------------------------+------------+-------------+  
   |     1     |     Light_2006      |  36494ea9987db45588b29a7b900a9da2   |   0x2006   |      3      |  
   +-----------+---------------------+-------------------------------------+------------+-------------+  
   |     2     |     Light_2009      |  994c62c4bf480f51bb3995094a266ec2   |   0x2009   |      3      |  
   +-----------+---------------------+-------------------------------------+------------+-------------+  
   |     3     |     Provisioner     |  764b0e71f3fc5c5ab856d6e1a90b4e32   |   0x2001   |      4      |  
   +-----------+---------------------+-------------------------------------+------------+-------------+  
   ```
4. Configure nodes with built-in profiles.  
   Issue the `group add` command to create a new group, specify a group address, specify a configuration profile to apply, and specify what node(s) to be added to the group.  
   Add the Distributor node to the group named GrpDist1:  
   ```sh  
   >>>group add --appkey-idx 0 --group-addr 0xC000 --sub-addrs Dist*[0] --profile distributor --name GrpDist1  
   App group GrpDist1 adds appkey binding to BLOB Transfer Client model on 0x2005 element address.  
   App group GrpDist1 adds appkey binding to Firmware Update Client model on 0x2005 element address.  
   App group GrpDist1 adds appkey binding to Firmware Distribution Server model on 0x2005 element address.  
   App group GrpDist1 adds appkey binding to Firmware Update Server model on 0x2005 element address.  
   App group GrpDist1 adds appkey binding to BLOB Transfer Server model on 0x2005 element address.  
   App group GrpDist1 adds subscription to Firmware Update Server model on 0x2005 element address.  
   App group GrpDist1 adds subscription to BLOB Transfer Server model on 0x2005 element address.  
   ```  
   Add the Light node(s) to the group named GrpLight1:  
   ```sh  
   >>>group add --appkey-idx 0 --group-addr 0xC001 --sub-addrs Light*[0] --profile target_node --name GrpLight1  
   App group GrpLight1 adds appkey binding to Firmware Update Server model on 0x2009 element address.  
   App group GrpLight1 adds appkey binding to BLOB Transfer Server model on 0x2009 element address.  
   App group GrpLight1 adds appkey binding to Firmware Update Server model on 0x2006 element address.  
   App group GrpLight1 adds appkey binding to BLOB Transfer Server model on 0x2006 element address.  
   App group GrpLight1 adds subscription to Firmware Update Server model on 0x2009 element address.  
   App group GrpLight1 adds subscription to BLOB Transfer Server model on 0x2009 element address.  
   App group GrpLight1 adds subscription to Firmware Update Server model on 0x2006 element address.  
   App group GrpLight1 adds subscription to BLOB Transfer Server model on 0x2006 element address.  
   ```  
   Show the group information:  
   ```sh  
   >>>group list  
   +-------------------+-----------------------+---------------------------+--------------------------+  
   |        Idx        |         Name          |       Group Address       |       Appkey Index       |  
   +-------------------+-----------------------+---------------------------+--------------------------+  
   |         0         |       GrpDist1        |         0xC000            |            0             |  
   +-------------------+-----------------------+---------------------------+--------------------------+  
   |         1         |       GrpLight1       |         0xC001            |            0             |  
   +-------------------+-----------------------+---------------------------+--------------------------+  
   ```
5. Upload a firmware image to the Distributor.  
   Issue the `dist upload` command to upload `application.gbl` to the Distributor.  
   ```sh  
   >>>dist upload --distributor Distributor_2005 --fwid 0x02FF:s:light --metadata s:test --timeout-base 1 applica-tion.gbl  
   FW data (427260 bytes) is loaded from application.gbl.  
   Upload progress: 0.00%  
   ...  
   ...  
   ...  
   Upload progress: 100.00%  
   Firmware with 0x02FF:light FWID is uploaded to Distributor (0x2005).  
   ```  
   Show the firmware list from the Distributor.  
   ```sh  
   >>>dist info --fw-list --distributor Distributor_2005  
   +---------------------------------------------+----------------------------------------------------+  
   |                    Index                    |                        FWID                        |  
   +---------------------------------------------+----------------------------------------------------+  
   |                      0                      |                    0x02FF:light                    |  
   +---------------------------------------------+----------------------------------------------------+  
   ```
6. Distribute the firmware image to Light node(s).  
   Issue the `dist start` command to instruct the Distributor to start firmware image distribution.  
   ```sh  
   >>>dist start --distributor Distributor_2005 --fw-list-idx 0 --group GrpLight1  
   Distribution phase is changed to transfer active.  
   Distribution transfer progress: 0%  
   ...  
   ...  
   Distribution transfer progress: 100%  
   Distribution phase is changed to applying update.  
   Distribution phase is changed to completed.  
   The FW distribution of 0 FW list index is completed on the Distributor (0x2005).  
   +-----------------+----------------+----------------------+--------------------+-------------------+  
   |     Address     |     FW Idx     |        Phase         |    BLOB status     |    DFU status     |  
   +-----------------+----------------+----------------------+--------------------+-------------------+  
   |     0x2006      |       0        |    apply success     |      success       |     success       |  
   +-----------------+----------------+----------------------+--------------------+-------------------+  
   |     0x2009      |       0        |    apply success     |      success       |     success       |  
   +-----------------+----------------+----------------------+--------------------+-------------------+  
   ```

### Provisioning

#### Provisioning

In addition to the following documents, which describe the two methods to establish the authenticity of devices wishing to join a mesh network, this section also provides details on [Bluetooth Mesh Security Best Practices](/btmesh/11.0.0/btmesh-provisioning-security-best-practices).

- [**Bluetooth Mesh Remote Provisioning**](/btmesh/11.0.0/btmesh-remote-provisioning): Describes use of standard Mesh networking between a provisioner and a Remote Provisioning Server, so that the server can provision any device in the radio range of the network.
- [**Bluetooth Mesh Certificate-Based Provisioning**](/btmesh/11.0.0/btmesh-certificate-based-provisioning): Certificate-Based Provisioning (CBP), as defined in Bluetooth Mesh protocol specification version 1.1, ensures that devices joining a Bluetooth Mesh network are authentic.

#### Bluetooth Mesh Provisioning Security Best Practices

Security of the provisioning process is a critical component of the
overall Bluetooth mesh network security. The provisioning process
is designed with this in mind and provides security features that,
when used correctly, help defend the network against attacks
targeting device provisioning.

This document provides a quick overview of the provisioning process
security and describes best practices that can be used to hinder
attackers.

For details of the provisioning security, refer to the [**Mesh
Protocol specification**](https://www.bluetooth.com/specifications/specs/mshprt-1-1/),
Section 5 overall and Sections 5.4.2 and 5.4.3
in particular.

Bluetooth SIG also offers an informational publication on Bluetooth [**Mesh Security Overview**](https://www.bluetooth.com/bluetooth-resources/mesh-security-overview/) that provides recommendations on how to use the Mesh security toolbox in general, including provisioning.

##### Provisioning Process

Mesh provisioning can be roughly divided into the following five
phases:

- Session establishment
- Capability negotiation
- Public key exchange
- Device authentication
- Provisioning data distribution

###### Session Establishment

In session establishment, an unprovisioned device announces that it is
ready to be provisioned by transmitting unprovisioned device beacons
or service advertisements for mesh provisioning GATT service. Both of
these contain the device UUID (a 128-bit identifier for the device) as
well as an indication of what out-of-band technologies the device might
support. The Provisioner establishes a provisioning session to the
device when it observes the unprovisioned device's transmissions.

###### Capability Negotiation

Once a provisioning session is established, the device declares its
capabilities to the Provisioner. These capabilities include the
following:

- Which provisioning algorithms the device supports; currently, two provisioning algorithms are defined:  
  - BTM_ECDH_P256_HMAC_SHA256_AES_CCM -- defined in Mesh Protocol specification v1.1  
  - BTM_ECDH_P256_CMAC_AES128_AES_CCM -- defined in Mesh Profile specification v1.0
- If the device supports an out-of-band EC public key or not  
  - Devices supporting Certificate-based Provisioning will support an out-of-band EC public key
- If the device supports input, output, or static out-of-band authentication data
- Characteristics of output out-of-band authentication data, if supported
- Characteristics of input out-of-band authentication data, if supported

The Provisioner decides, based on device capabilities, its own
capabilities, and restrictions configured by the application, which
provisioning algorithm it will use, whether out-of-band public key
will be used, and whether out-of-band authentication data will be
used. It then communicates its decision to the device to conclude
capability negotiation.

For example, suppose that the unprovisioned device has a numeric
keypad and the Provisioner has a display that can show alphanumeric sequences
(such as a dot matrix display). The Provisioner can then decide to make
use of these hardware features for out-of-band authentication during
provisioning.

The Provisioner is free to not provision any device that does not
meet the minimum requirements set by the network operator. For
example, the network operator may consider it a mandatory requirement
that devices support some form of an out-of-band EC public key,
and the Provisioner can abort the provisioning session for devices
that do not support it.

While the Provisioner has the final say in what provisioning features
will be used, Mesh Protocol 1.1 allows a device to request that
out-of-band authentication data is used; and if it is not possible,
the Provisioner has to abort the provisioning instead of forcing
no out-of-band authentication data on the device.

###### Public Key Exchange

After capability negotiation, the Provisioner and the unprovisioned
device exchange EC public keys, so that each is able to derive an EC
Diffie-Hellman shared secret independently. The shared secret will be
the basis of provisioning security, as important data such as session
key will be derived from it.

The Provisioner will always generate a fresh ephemeral EC key for
every provisioning attempt and deliver it to the unprovisioned device
in-band over the provisioning session (that is, using the Bluetooth
radio).

The unprovisioned device will do the same when an out-of-band public key
is not used. If an out-of-band EC public key is used, then the Provisioner
must acquire it using the out-of-band mechanism that gives access to
the key before it can compute the shared secret.

For example, in Certificate-based Provisioning, the out-of-band
mechanism can be an HTTPS request to a key server over the Internet.
Using that, of course, requires that the Provisioner has IP connectivity
and a TCP/IP stack implementation.

###### Device Authentication

Once the public key exchange is complete, the Provisioner
authenticates the device. The authentication is based on both the
Provisioner and the unprovisioned device knowing the exact same
out-of-band authentication data and using it in cryptographic
computations in order to independently compute the same results. How
the authentication data knowledge is shared depends on the chosen
authentication method, as described below:

- For input out-of-band authentication, the Provisioner chooses a  
  random value as the authentication data and outputs it to the  
  user. The user must input the same value to the unprovisioned  
  device.
- For output out-of-band authentication, the unprovisioned device  
  chooses a random value as the authentication value and outputs  
  it to the user. The user must input the same value to the  
  Provisioner.
- For static out-of-band authentication, the authentication data  
  may be chosen randomly by the unprovisioned device, or it may  
  be pre-programmed to the device at the factory. The Provisioner  
  will read the value using an out-of-band technology, such as  
  a QR code or an NFC tag.
- If none of the above is used, the authentication data is  
  essentially zero.

The specification requires that authentication data for output
out-of-band and input out-of-band authentication must be freshly
generated for each attempt, not reused across multiple attempts.

The specification also requires that authentication data used for Mesh
provisioning must not be used in Bluetooth LE pairing, and vice
versa. Distinct data must be used for each. When pre-programmed static
out-of-band authentication is used, this means that the device must be
pre-programmed with two values, one for provisioning and one for
pairing.

###### Provisioning Data Distribution

Once the device authentication completes, both devices will
independently create a session encryption key from the shared secret
and other input material. The Provisioner will use the session
encryption key to encrypt the provisioning data to send to the
unprovisioned device. Once the unprovisioned device receives and
decrypts the provisioning data, it can make use of it to gain access
to the network.

After provisioning data is distributed, the provisioning session will
be torn down and the provisioning process completes.

##### Provisioning Best Practices

###### Consider Device UUID Filtering

Depending on the use case, the Provisioner might know what devices it
is supposed to provision. For example, a shipping manifest for a
deployment could include device UUIDs of the devices to be set up.

If the information is available, Provisioner should not provision
any device with a UUID that is not on the expected devices list.

Furthermore, the Provisioner should know what devices have already
been provisioned and recognize their device UUIDs; it should not
reprovision those devices again unless it is known the devices
have been factory reset intentionally.

###### Allow a Device to be Provisioned only when Needed

An unprovisioned device cannot be attacked over the provisioning
interface if it does not make itself available for provisioning.

Furthermore, the device UUID will not be broadcast for passive
eavesdroppers to see if the device does not transmit unprovisioned
device beacons or service advertisements for mesh provisioning GATT
service to begin with.

Thus, an unprovisioned device should make itself available for
provisioning only when it is time to add the device to a network. This
can be triggered, for example, by pressing a button on the device, by
shaking the device in a manner that is picked up by an acceleration
sensor, or by other suitable physical means.

If the device is not provisioned after a reasonable time has passed
since the trigger it should transition back to idle state.

###### Use the Latest Provisioning Algorithm

Preferably, use the newer algorithm, BTM_ECDH_P256_HMAC_SHA256_AES_CCM,
and only use the older algorithm as a fallback if provisioning a legacy
device that does not implement the newer one.

It is highly recommended that fallback to the older algorithm is only
done if it is positively known that legacy devices need to be
provisioned. Fallback should not be done if it is known that devices
being provisioned support Mesh Protocol specification v1.1.

###### Consider Using Out-of-Band Public Key

The EC public key exchange and the ECDH shared secret derivation
helps to protect provisioning against passive eavesdropping even when both
EC public keys are exchanged in-band. It will, however, not protect
against an active man-in-the-middle attack.

If there is a chance of an active man-in-the-middle attack, device
public key out-of-band delivery helps to protect against such attacks over
Bluetooth.

Note that the out-of-band technology used to access the device public
key must also be resilient to attacks to provide any benefit.

Note that if the Provisioner decides to use an out-of-band EC public key
and it fails to access the key due to an out-of-band mechanism error (e.g.,
the certificate server is not reachable) the Provisioner must then abort
the provisioning session instead of silently falling back to using
in-band keys.

###### Consider PKI Integrity

When using Certificate-based Provisioning, the security of the data
embedded in device certificates depends on the integrity of the PKI
used to produce the certificate.

The network operator is responsible for choosing the root certificates
on which the certificate validation during provisioning builds.
Only trustworthy root certificates should be included in the set of
root certificates the Provisioner uses for certificate validation.
Documents such as the Certificate Authorities' certificate policies
and Certification Practice Statements can help in making PKI
decisions.

Certificate Authorities may issue certificates with clearly declared
certificate policies (policy identifiers recorded as certificate
extensions). A Provisioner may have a list of acceptable policies
in addition to having a set of trusted root certificates.

###### Consider Using Out-of-Band Authentication Data

As with out-of-band public key, if there is a chance of an active
man-in-the-middle attack, using out-of-band authentication data will
help to protect against such attacks over Bluetooth.

Note that the out-of-band technology used to access the authentication
data must also be resilient to attacks to provide any benefit.

It is important to note that, if out-of-band authentication data
is used, the recommended BTM_ECDH_P256_HMAC_SHA256_AES_CCM provisioning
algorithm must be used as well. This is because the older provisioning
algorithm has security flaws that affect authentication.

It is very important to provide a sufficient amount of entropy in the
authentication data to the provisioning procedure

If input or output out-of-band authentication is used, it is important
to note that the specification unfortunately allows input and output
actions (ways to provide the data) that provide only a very limited
amount of entropy. This can make the authentication susceptible to
brute-forcing or even simply guessing.

Blink, Beep, and Vibrate output out-of-band actions are not recommended to be used at all due to the extremely low entropy that they provide.

Push and Twist input out-of-band actions are not recommended to be used at all for the same reason.

Output Numeric and Input Numeric actions are not recommended to be used as they also provide a relatively low entropy. Note the following:

- When Output Numeric or Input Numeric is used, the authentication  
  data is constructed from a string of decimal digits, and the  
  number of possible permutations is 10 to the power of N, where N is the number  
  of digits. This means that, for example, 8 digits provides  
  only 26 bits of entropy to the authentication whereas 6 digits  
  provides only 19 bits of entropy.

Output Alphanumeric and Input
Alphanumeric actions can be used, but note the following:

- When Output Alphanumeric or Input Alphanumeric is used, the  
  data is constructed from a string of decimal digits and  
  uppercase English letters, and the number of possible  
  permutations is 36 to the power of N, where N is the number  
  of digits and letters. For example,  
  8 numbers and letters provides 41 bits of entropy  
  to the authentication whereas 6 numbers and letters  
  provides only 31 bits of entropy.

When static out-of-band authentication is used, 256 bits of entropy
can be provided to the authentication. It is highly recommended that
the full length of the authentication data is made use of when static
out-of-band authentication data is generated. It is not recommended to
use a shorter length and pad the remainder with zeroes, but at minimum
more than 128 bits of entropy should be used.

No out-of-band authentication and no out-of-band public key exchange
can broadly be compared to Bluetooth LE Secure Connections pairing
with Just Works association model; it is convenient to the user, and
secure enough if there is no active man-in-the-middle attacker
present.

#### Bluetooth Mesh Remote Provisioning

##### Bluetooth Mesh Remote Provisioning

> **NOTE: This section replaces _AN1368: Bluetooth Mesh Remote Provisioning_. Further updates to this application note will be provided here**.

This application note describes the Mesh Remote Provisioning feature. Without it, the provisioner and the unprovisioned node must be in radio range of each other. With it, a device can be provisioned without a direct radio connection between the provisioner and the unprovisioned node. The feature uses standard Mesh networking between the provisioner and a Remote Provisioning Server, so that the server can provision any device in the radio range of the network.

###### Key Points

- Remote Provisioning Background information
- Remote Provisioning in Bluetooth Mesh SDK
- Bluetooth Mesh Example Applications
- Remote Provisioning Example Walkthrough

##### Background

Provisioning is a process of adding an unprovisioned device to a mesh network managed by a Provisioner. A Provisioner provides the unprovisioned device with provisioning data that allows it to become a mesh node for the initial term. The provisioning data includes a network key, the current IV Index, and the unicast address for each element.

A Provisioner is typically a smart phone or other mobile computing device, but could be also a gateway or even one of the network devices. Although only a single Provisioner is required on a network to do provisioning, multiple Provisioners may be used. The method to share cached data and coordinate across multiple Provisioners is implementation-specific.

To provision an unprovisioned device, the provisioning bearer (PB) must be established between a Provisioner and an unprovisioned device. An unprovisioned device can be identified to a Provisioner by its Device UUID and other supplementary information that may also be provided, such as some manufacturer-related information.

The PB-ADV bearer allows provisioning of an unprovisioned device by using an advertising bearer.

The PB-GATT bearer allows provisioning of an unprovisioned device by using the Mesh Provisioning Service in the GATT. For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft) Chapter 5 Provisioning, the first two pages.

This application note assumes that you are familiar with using Simplicity Studio to create, configure, build, and flash projects to devices. If you are not, see the [Quick Start Guide](/btmesh/11.0.0/btmesh-getting-started-overview). For more information about the Bluetooth mesh software components, see the [Bluetooth® Mesh Stack and Bluetooth® Mesh Configurator User's Guide for SDK v5.0 and Higher](/btmesh/11.0.0/btmesh-node-configuration-v5x-and-higher).

##### Remote Provisioning

The PB-Remote bearer allows a Provisioner that is outside immediate radio range of an unprovisioned device to communicate with a node supporting the Remote Provisioning Server model that is within immediate radio range of the unprovisioned device, and to use that node as a re-transmitter to communicate with the unprovisioned device using PB-ADV or PB-GATT. This allows a Provisioner to provision unprovisioned devices using nodes of the mesh network.

![The Remote Provisioning Server Using PB-ADV or PB-GATT for Provisioning](/btmesh-remote-provisioning/10.0.0/images/sld821-image1.png)

In legacy Bluetooth mesh provisioning using PB-ADV, the Provisioner node also has the PB-ADV Provisioning Client. It can directly provision an unprovisioned device in the radio range. Bluetooth mesh provisioning using PB-GATT is similar, in that the Provisioner node also has the PB-GATT Provisioning Client (or Mesh Provisioning Service GATT Client).

![Differences Between the Provisioning Bearers](/btmesh-remote-provisioning/10.0.0/images/sld821-image2.png)

##### PB-Remote Bearer

The PB-Remote provisioning bearer uses the existing mesh network to provision an unprovisioned device that is not within immediate radio range of the Provisioner.

PB-Remote uses the PB-ADV bearer or the PB-GATT bearer for the last hop to the unprovisioned device. PB-Remote uses one of the mesh nodes as a PB-Remote Server to manage the PB-ADV or PB-GATT bearer link on behalf of the Provisioner.

Secure Provisioning should be used when PB-Remote is used. Secure Provisioning with an Authentication with No OOB or an Authentication with Static OOB of any size should be used, because these authentication methods do not require direct physical interaction with the unprovisioned device.

When PB-Remote is supported by the Provisioner, the Provisioner uses the PB-Remote Client role. When the node supports the Remote Provisioning Server model, the node uses the PB-Remote Server role.

PB-Remote may also be used to execute the Device Key Refresh procedure or the Node Address Refresh procedure or the Node Composition Refresh procedure between the Provisioner (PB-Remote Client) and the PB-Remote Server.

Multiple instances of the PB-Remote Client can be used by the Provisioner to communicate with many nodes implementing the PB-Remote Server, thus providing the capability to provision many unprovisioned devices at the same time. The PB-Remote Server can only communicate with one PB-Remote Client and can only open one supported provisioning bearer at a time.

For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft) Chapter 5.2.3 PB Remote.

##### Remote Provisioning Procedures

The Provisioning procedure is used for the following purposes:

- To provision a device within immediate radio range of the Remote Provisioning Server.
- To change the Device Key Candidate of the Remote Provisioning Server by using the Device Key Refresh procedure.
- To change the Device Key Candidate and the Composition Data state of the Remote Provisioning Server by using the Node Composition Refresh procedure.
- To change the device key and the primary element address of the Remote Provisioning Server by using the Node Address Refresh procedure.

For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft) Chapter 4.4.5.4 Provisioning procedure.

##### Remote Provisioning Messages

Remote Provisioning messages are used by a Remote Provisioning Client to communicate with a Remote Provisioning Server over a mesh network to find the UUID of unprovisioned devices within immediate radio range of the Remote Provisioning Server and to provision a remote unprovisioned device.

Remote Provisioning messages also can be used to obtain extended information about an unprovisioned device or to execute a Device Key Refresh procedure or a Node Address Refresh procedure or a Node Composition Refresh procedure.

The Remote Provisioning Scan Capabilities are:

1. Remote Provisioning Scan Capabilities Get
2. Remote Provisioning Scan Capabilities Status

The Remote Provisioning Scan Parameters are:

1. Remote Provisioning Scan Get
2. Remote Provisioning Scan Start
3. Remote Provisioning Scan Stop
4. Remote Provisioning Scan Status
5. Remote Provisioning Scan Report
6. Remote Provisioning Extended Scan Start
7. Remote Provisioning Extended Scan Report

The Remote Provisioning Link Parameters are

1. Remote Provisioning Link Get
2. Remote Provisioning Link Open - Can also contain Node Provisioning Protocol Interface (NPPI) procedures
3. Remote Provisioning Link Close
4. Remote Provisioning Link Status
5. Remote Provisioning Link Report
6. Remote Provisioning PDU Send
7. Remote Provisioning PDU Outbound Report
8. Remote Provisioning PDU Report

For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft):

- Chapter 4.3.4 Remote Provisioning messages
- Chapter 4.2.23 Remote Provisioning Scan Capabilities
- Chapter 4.2.25 Remote Provisioning - Link Parameters

##### Node Provisioning Protocol Interface Procedures

The Node Provisioning Protocol Interface is used when a Node Provisioning Protocol Interface procedure is executed.

The Node Provisioning Protocol Interface (NPPI) is an interface used by the node to route the Provisioning PDUs between the Provisioner and the layer that is executing the provisioning protocol.

![diagram](/btmesh-remote-provisioning/10.0.0/images/sld821-image3.png)

###### Device Key Candidate

The Device Key Candidate is a key that can replace the device key when activated. The Device Key Candidate may be delivered to the node by using an OOB mechanism or may be generated by successfully executing the Device Key Refresh procedure. When the Device Key Candidate is available, it can be activated, and replaces the device key.

###### Device Key Refresh Procedure

The Device Key Refresh procedure is used to change the device key (DevKey) without reprovisioning a node and without the need to reconfigure the node.

The Device Key Refresh procedure does not transfer a device key to the device over-the-air. Instead, it uses the provisioning protocol to compute the Device Key Candidate. The device key value change that results from this procedure is thus performed at the same security level as is provisioning of the unprovisioned device. The Address, NetKey, NetKey Index, and IV Index that are provided using the provisioning protocol must match the values stored on the node. The value of the Flags field is ignored.

###### Node Address Refresh Procedure

The Node Address Refresh procedure is used to change the node’s device key and unicast address without reprovisioning.

Executing this procedure ends the current term of the node and starts a new term.

The NetKeys and AppKeys stored in the node are not removed during the procedure. Other configuration states may change. For example, the Composition Data state may change upon successful procedure completion if features are added or removed.

###### Node Composition Refresh Procedure

The Node Composition Refresh procedure is used to change the device key of the node and to add or delete models or features of the node without reprovisioning.

Executing this procedure ends the current term of the node and starts a new term.

Almost all states of the node remain the same during this procedure. The Composition Data state of the node is changed.

For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft) Chapter 3.11.8 Node Provisioning Protocol Interface procedures.

##### Node Models and Features for Remote Provisioning

![diagram](/btmesh-remote-provisioning/10.0.0/images/sld821-image1.png)

Provisioner (with Remote Provisioning support):

- Remote Provisioning Client
- Host provisioner or Embedded provisioner application

Mesh node (relaying the PB-Remote bearer messages):

- Mesh Relay just as without Remote Provisioning as the PB-Remote uses default mesh networking

Mesh node with Provisioning support (to provision the device)

- Remote Provisioning Server
- Provisioning Client, PB-ADV and/or PB-GATT
- Has to be within immediate radio range of the unprovisioned device

Unprovisioned device (to be provisioned)

- Provisioning Server, PB-ADV and/or PB-GATT

##### Bluetooth Mesh Software Components

These components can be found in the Simplicity Studio software components tab under Bluetooth Mesh -> Models -> Remote Provisioning.

Remote Provisioning Client model:

- Used to support remote provisioning client functionality of provisioning devices into a mesh network by interacting with a mesh node that supports the Remote Provisioning Server model.
- SIG Mesh Model ID: 0x0005
- Required only in the embedded remote provisioner
- Not required in the provisioned nodes
- Only configurable feature is to Enable logging
- For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft) Chapter 4.4.6 Remote Provisioning Client model.

Remote Provisioning Server model:

- Used to support remote provisioning server functionality of provisioning a remote device over the mesh network and to perform the Node Provisioning Protocol Interface procedures.
- SIG Mesh Model ID: 0x0004
- Required in all the remote provisioning procedure-capable nodes
- Not required in the provisioned nodes
- Configurable features are Default Bearer Type and Enable logging
- For more details, refer to the Bluetooth Mesh Profile specification (1.1 draft) Chapter 4.4.5 Remote Provisioning Server model

##### Bluetooth Mesh SDK API Additions

Here is a quick look into remote provisioning additions as a list of API commands.

See _sl_btmesh_api.h_ for detailed API commands and events with included documentation.

The new models are defined in _sl_btmesh_model_specification_v1_1_defs.h_. This will be integrated to _sl_btmesh_model_specification_defs.h_ in the future where mesh 1.1 features are a part of a public release.

###### Bluetooth Mesh Stack Provisioner

`sl_btmesh_prov_provision_remote_device`: Provision device over remote provisioning server connection

###### Remote Provisioning Client

`sl_btmesh_remote_provisioning_client_init`: Initialize the remote provisioning client.

`sl_btmesh_remote_provisioning_client_get_scan_capabilities`: Get the value of the Remote Provisioning Scan Capabilities state.

`sl_btmesh_remote_provisioning_client_start_scan`: Start scanning for remote unprovisioned devices, within immediate radio range of the Remote Provisioning Server.

`sl_btmesh_remote_provisioning_client_get_scan_status`: Request scan status.

`sl_btmesh_remote_provisioning_client_stop_scan`: Stop Remote Provisioning Scan procedure.

`sl_btmesh_remote_provisioning_client_start_extended_scan`: Request additional information about a specific unprovisioned device or about the Remote Provisioning Server itself.

`sl_btmesh_remote_provisioning_client_open_link`: Establish the provisioning bearer between a node supporting the Remote Provisioning Server model and an unprovisioned device, or to open the Node Provisioning Protocol Interface (NPPI).

`sl_btmesh_remote_provisioning_client_get_link_status`: Get the Remote Provisioning Link state of a Remote Provisioning Server model.

`sl_btmesh_remote_provisioning_client_close_link`: Close remote provisioning link.

###### Remote Provisioning Server

`sl_btmesh_remote_provisioning_server_init`: Initialize the remote provisioning server.

`sl_btmesh_remote_provisioning_server_open_link`: This command is used to pass a connection handle to the remote provisioning server after having received link_open_request event

`sl_btmesh_remote_provisioning_server_set_default_bearer`: Set default bearer to be used in remote provisioning

##### Bluetooth Mesh Example Applications

###### Remote Provisioner

Bluetooth Mesh - NCP Empty 1.1

- NCP mode target application including remote provisioning support
- Compatible with parts: xG12, xG21, xG24, MGM12, xGM21, xGM24
- Only stack classes for Remote Provisioning Server and Remote Provisioning Client were added, no Models required
- Located in the GSDK folder app/bluetooth/example/btmesh_ncp_empty/btmesh_ncp_empty_v1_1.slcp

BT Mesh Host Provisioner

- PC NCP mode host application for testing host provisioning including Remote Provisioning
- to be used with **Bluetooth Mesh - NCP Empty 1.1** NCP mode target application
- Located in GSDK folder app/bluetooth/example_host/btmesh_host_provisioner
- Quick instructions: compile with a Posix-compatible toolchain with make parameters RPR=1 UI=1. See the README.txt included for more information

###### Remote Provisioning Relay

Any mesh application with Relay feature can relay the PB-Remote bearer messages, for example **Bluetooth Mesh - SoC Light** is a good example to test with.

###### Remote Provisioning Server

No example application is provided. Create an example application, for example **Bluetooth Mesh - SoC Light** and add the Remote Provisioning Server Model component to add mesh node Remote Provisioning Server features.

###### Node to be Provisioned

Any mesh node.

##### Remote Provisioning Example Walkthrough

A three- or two-device setup is used to test the Remote Provisioning feature.

![diagram](/btmesh-remote-provisioning/10.0.0/images/sld821-image4.png)

###### Device Roles

The first device is the **Provisioner** using NCP mode target application with the NCP mode host PC application or our Bluetooth Mesh smartphone application. It will provision the Unprovisioned device into the network indirectly via the Remote Provisioning Server.

The second device is the **Remote Provisioning Server** that really communicates with the Provisioner and provisions the Unprovisioned device.

The third device is the **Unprovisioned device** to be provisioned. This is a generic Bluetooth Mesh device without any additions for Remote Provisioning.

###### Applications

Three devices are required that can run Bluetooth Mesh (two, in the case of using a smartphone as Provisioner). Those can be any of these devices: MG12/BG12, MG21/BG21, MG24/BG24, MGM12, BGM210/MGM210, BGM240/MGM240.

Remember to flash a bootloader to the devices, either by running a demo as those include also a bootloader or by creating, building, and flashing a bootloader separately.

For more information about the bootloaders, see [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/) or [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 or Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/).

###### The Provisioner, Remote Provisioning Client (heading level 7)

If using a smartphone, omit the steps below.

The first device should run **Bluetooth Mesh - NCP Empty 1.1**. It can be the pre-built demo or a compiled example application. It does not need any changes as it already contains the Remote Provisioning Client feature.

Also compile the PC host application, **btmesh_host_provisioner** and test that it connects to the NCP target device. The readme.txt is included in the application folder app/bluetooth/example_host/btmesh_host_provisioner.

###### The Remote Provisioning Server (heading level 7)

This device is also called the PB-Remote Server, the Provisioning Protocol executor target node, the Remote Provisioning Protocol target, the Node Provisioning Protocol Interface executor, the Provisioning Server, and so on.

The project for this device can start from a variety of examples, such as **Bluetooth Mesh - SoC Light**. Then add the component **Remote Provisioning Server Model** found under Bluetooth Mesh -> Models -> Remote Provisioning. Build and flash the application. For more information, see the [Bluetooth Mesh Quick-Start Guide](/btmesh/11.0.0/btmesh-getting-started-overview).

###### The Unprovisioned Device (heading level 7)

The third device should run the **Bluetooth Mesh - SoC Light** example, or any other example. It can be the pre-built demo or a compiled example application, as it does not need any changes.

###### Running the Example with NCP Provisioner

When all three devices are ready, run the PC host provisioner application connected to the first Provisioner device should show a display like this:

```C
Please select a functionality

1. Scan available nodes
2. Provision a beaconing node
3. List nodes in the network
4. Information about a node in the network
5. Remove node from the network
6. List available remote provisioning servers
7. Remote scan unprovisioned nodes
8. Remote provision an unprovisioned node
9. Reset provisioner node
0. Exit application
```

Select **1** to scan for the available unprovisioned nodes. Two nodes should then be visible. Identify which one is the Remote Provisioning Server and which one is the Unprovisioned Device. In this example, the device UUID ending `bc 69` is the Remote Provisioning Server.

```C
1
[I] Scanning started

[I] Unprovisioned node
[I] ID:      0
[I] UUID:    6b 11 40 f7 be 9f e5 56 95 52 30 48 20 60 bc 69
[I] OOB Capabilities: 0x0000

[I] Unprovisioned node
[I] ID:      1
[I] UUID:    6e e9 34 56 5d 73 b5 5c aa 20 31 97 10 3b 4b 84
[I] OOB Capabilities: 0x0000

[I] Scanning stopped

Press enter to continue...
```

Press **Enter** to continue. Then press **2** to provision the Remote Provisioning Server node. This example selects the unprovisioned node with ID **0**. The following is displayed:

```C
0
[I] Provisioning...
[I] Device provisioned
[I] UUID:    6b 11 40 f7 be 9f e5 56 95 52 30 48 20 60 bc 69
[I] Address: 0x20005

Configuration of node (netkey_idx=0,addr=0x2005) is started.
DCD query of node (netkey_idx=0,addr=0x2005) completed.
Node (netkey_idx=0,addr=0x2005) runs btmesh_soc_light example.
[E] Status: model_attr_status = 0x002d (?) Failed to get btmesh model (0xbf42) attributes.
[E] Status: model_attr_status = 0x002d (?) Failed to get btmesh model (0xbf44) attributes.
Configuration of node (netkey_idx=0,addr=0x2005) is successful.

[I] Provisioning finished

Press enter to continue...
```

Ignore the failed models 0xbf42 and 0xbf44 as those are not Remote Provisioning-related.

Press **Enter** and check by pressing **1** if there is still one unprovisioned node and by pressing **3** if there is one provisioned node.

Press **6** to see available Remote Provisioning Servers. The one that was just provisioned should be displayed.

```C
6

[I] Scanning for remote provisioner servers

[I] Remote provisioning server address: 0x2005

[I] Scanning for remote provisioner servers completed

Press enter to continue...
```

Press **Enter** and scan unprovisioned nodes using the Remote Provisioning Server by pressing **7**.

```C
7
Select a remote provisioning server
Type either the ID or the address from the list below

[I] 0. Remote provisioning server: 0x2005
```

Select the server by pressing **0**.

```C
0
[I] Remote scanning for unprovisioned nodes started

[I] Unprovisioned device UUID: 6e e9 34 56 5d 73 b5 5c aa 20 31 97 10 3b 4b 84

[I] Remote scanning completed

Press enter to continue...
```

You can see the Unprovisioned node via the remote server. Provision it by pressing **Enter** and then **8**.

```C
8
Select a remote provisioning server
Type either the ID or the address from the list below

[I] 0. Remote provisioning server: 0x2005
```

Press **0** to select the server.

```C
0
[I] Selected remote provisioning server address 0x2005

Select the unprovisioned node for remote provisioning
Type either the ID, or UUID from the list below

[I] Unprovisioned node
[I] ID:      0
[I] UUID:    6e e9 34 56 5d 73 b5 5c aa 20 31 97 10 3b 4b 84
```

Press **0** to select the node.

```C
0
[I] Remote provisioning...
[I] Device provisioned
[I] UUID:    6e e9 34 56 5d 73 b5 5c aa 20 31 97 10 3b 4b 84
[I] Address: 0x2008

Configuration of node (netkey_idx=0,addr=0x2008) is started.
DCD query of node (netkey_idx=0,addr=0x2008) completed.
Node (netkey_idx=0,addr=0x2008) runs btmesh_soc_light example.
[E] Status: model_attr_status = 0x002d (?) Failed to get btmesh model (0xbf42) attributes.
[E] Status: model_attr_status = 0x002d (?) Failed to get btmesh model (0xbf44) attributes.
Configuration of node (netkey_idx=0,addr=0x2008) is successful.

[I] Provisioning finished

Press enter to continue...
```

Ignore the failed models 0xbf42 and 0xbf44 as those are not Remote Provisioning related.

Press **Enter** and then press **3** to list the nodes in the network. Two should be available, the Remote Provisioning Server and the previously Unprovisioned node, remotely provisioned.

```C
3
[I] Querying DDB list

[I] Address: 0x2005
[I] Element count: 3
[I] UUID:    6b 11 40 f7 be 9f e5 56 95 52 30 48 20 60 bc 69

[I] Address: 0x2008
[I] Element count: 3
[I] UUID:    6e e9 34 56 5d 73 b5 5c aa 20 31 97 10 3b 4b 84

Press enter to continue...
```

###### Running the Example with Smartphone App

Install the Silicon Labs Bluetooth Mesh App from Google Play / App Store. When the “Remote Provisioning Server” and the “Unprovisioned Device” devices are up and running, start the provisioning process. To distinguish the two devices more easily, you can boot up the “Remote Provisioning Server” before the first provisioning.

Scan for the “Remote Provisioning Server” device and provision it the usual way (turn on Proxy and add it to Group).

![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image5.png)  ![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image6.png)

As the Remote Provisioning Server Model is added to the DCD, the App will offer the functionality in the network device list. By selecting it, you can scan for devices available for provisioning, via the Remote Provisioning Server (both devices should be online by now).

![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image7.png)  ![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image8.png)
When the scanning found your “Unprovisioned Device”, you can provision and configure it the same way as you would with the standard provisioning.

![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image9.png)  ![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image10.png)

If your efforts were successful, you will be able to see the newly added device in your network.

![screenshot](/btmesh-remote-provisioning/10.0.0/images/sld821-image11.png)

#### Bluetooth Mesh Certificate-Based Provisioning

##### Bluetooth Mesh Certificate-Based Provisioning

> **NOTE: This section replaces _AN1386: Bluetooth Mesh Certificate-Based Provisioning_. Further updates to this application note will be provided here**.

Certificate-Based Provisioning (CBP) is defined in Bluetooth Mesh protocol specification version 1.1. CBP ensures that devices joining a Bluetooth Mesh network are authentic. This authentication method mitigates the risk of rogue devices joining the network by spoofing the identity of authentic devices.

This application note describes how certificates are used to establish the authenticity of devices wishing to join a mesh network.

###### Key Points

- Certificate-based provisioning
- Bluetooth Mesh protocol specification 1.1

##### Introduction

Certificate-Based Provisioning makes mesh networks more secure by establishing an identity using a signed certificate chain. This can prevent the possibility of rogue devices joining the network by spoofing the advertisement of a legitimate device. Certificate-Based Provisioning mitigates this by requiring the device to present a signed certificate or chain of certificates which can be verified using standard public key cryptography.

###### Requirements

Certificate-Based Provisioning is supported by the following devices:

|**Device**|**Support**|
|---|---|
|EFR32xG21B|Secure Vault|
|EFR32xG24B|Secure Vault|

##### Theoretical Background

###### Certificates

A digital certificate is simply a small, verifiable data file that contains identity credentials and a public key. That data is then signed either with the corresponding private signing key, or a certificate authority’s private signing key. The digital certificate can be used to prove the ownership of a public key.

- If it is signed using the corresponding private key, it is called a self-signed certificate.
- If it is signed by another private key, the owner of that private key is acting as a Certificate Authority (CA).
- A Certificate Authority (CA) is a trusted third party by both the owner and party relying on the certificate.

Concatenation of digital certificates builds a chain of trust.

- At the root of the chain is a self-signed certificate called a root certificate or a CA certificate.
- The root or CA certificate can be used to sign another certificate.

![Digital Certificates and Chain of Trust](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image1.png)

The private key is never included as part of the certificate. It must be stored separately and kept private. The security of the scheme relies on protecting the private keys.

###### Key Usage (heading level 7)

Version 3 of the X.509 standard provides the ability to restrict the purposes that a certificate’s public key can be used for. Bluetooth Mesh CBP certificates must allow the ‘Key Agreement’ usage for the public key. This allows a shared secret to be established between the provisioner and provisionee.

To learn more about certificates, see [Authenticating Silicon Labs Devices Using Device Certificates](/btmesh/11.0.0/authenticating-devices-using-device-certificates), which addresses certificates in detail.

###### Bluetooth Mesh Certificate-Based Provisioning

Bluetooth Mesh Provisioning is described in the Bluetooth Mesh 1.1 Protocol specification. Refer to this document for specifics of provisioning messages and certificate requirements. A certificate chain is used as the out-of-band (OOB) data for provisioning. Provisioning related information is stored on a device as provisioning records. The device certificate can either be requested from the device during provisioning or obtained by the provisioner from a URI indicated in the provisioning record. The provisioner requests the device certificate by sending a Provisioning Record Request message with the ID set to ‘Device Certificate’ to the device to be provisioned. The provisionee responds with a Provisioning Record Response message which includes a device certificate. If intermediate certificate(s) are present, they will be requested by the provisioner and sent one at time. Up to fifteen (15) intermediate certificates can be used in the certificate chain. The provisioner verifies the certificate chain before proceeding with the provisioning process. In case the certificate chain cannot be verified, the provisioning process is terminated.

###### Obtaining Device Certificates from URI (heading level 7)

Device certificates and intermediate certificates may be retrieved by the provisioner from the internet using HTTPS protocol. The base uniform resource indicator (URI) of the device certificate can be included provisioning record.

###### Requirements for Provisioners and Devices (heading level 7)

The provisioner of the network must store the root-of-trust certificate for each chain of trust. The root certificate must not be sent from device to provisioner during the provisioning process nor be able available for retrieval from the URI. It is the responsibility of the provisioner to ensure the integrity of the root-of-trust certificate.

###### Verifying the Device Certificate (heading level 7)

The provisioner must verify the authenticity of the device certificate received. In addition to verifying the authenticity of the certificate, as defined in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280), the Bluetooth Mesh protocol specification requires that the following criteria must be met:

- The device certificate must be verifiable, directly, or indirectly, by the root CA
- The device certificate is not expired
- The device certificate has not been revoked by any certificate revocation list (CRL)

The following table summarizes the fields of the device certificate which shall be present:

<table>
    <thead>
        <tr>
            <th>Certificate Field</th>
            <th>Requirements</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>tbsCertificate</p>
            </td>
            <td>
                <p>As defined by RFC5280 with additional requirements as defined in this table</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>signatureAlgorithm</p>
            </td>
            <td>
                <p>Set to “ecdsa-with-SHA256”</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SignatureValue</p>
            </td>
            <td>
                <p>Signature computed as in RFC5280</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Version</p>
            </td>
            <td>
                <p>“2”</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>serialNumber</p>
            </td>
            <td>
                <p>Must meet the requirements detailed in RFC5280</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>issuer</p>
            </td>
            <td>
                <p>Identifies the signer of the certificate. See RFC5280.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>validity</p>
            </td>
            <td>
                <ul>
                    <li>notBefore time should not be earlier than the manufacture date of the device</li>
                    <li>notAfter time shall be set by the manufacturer</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <p>subject</p>
            </td>
            <td>
                <p>Shall contain a valid distinguished name (DN) with the following restrictions:</p>
                <ul>
                    <li>organization name of the DN shall be set to the vendor name</li>
                    <li>common name of the DN shall contain the device UUID</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <p>subjectPublicKeyInfo</p>
            </td>
            <td>
                <p>As defined by RFC5280 with the following constraints:</p>
                <ul>
                    <li>algorithm field shall contain “id-ecPublicKey” as the algorithm and secp256r1 curve as the parameters. See RFC5480 for details.</li>
                    <li>subjectPublicKey field shall contain the public OOB key of the device</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <p>basicConstraints Extension</p>
            </td>
            <td>
                <ul>
                    <li>cA field shall be present and set to FALSE</li>
                    <li>pathLenConstraint shall not be present</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <p>keyUsage Extension</p>
            </td>
            <td>
                <p>keyAgreement bit shall be set as defined in RFC5280</p>
            </td>
        </tr>
    </tbody>
</table>

The following table summarizes the optional fields in the device certificate which may be included. These fields shall be used as defined in RFC5280 without additional constraints.

|Optional Certificate Fields|
|---|
|Authority key identifier|
|Subject key identifier|
|Certificate policies extension|
|Issuer Alternative Name|
|Subject Directory Attribute extension|
|CRL distribution points extension|
|Freshest CRL extension|
|Authority Information Access extension|
|Subject Information Access extension|

All other fields defined by RFC5280 shall not be present in the device certificate.

##### Creating Example Certificate Authority and Device Certificate

This section describes how to create an example certificate authority and device certificate. **The method described here is only intended for evaluation and should not be used in a production environment.** For production, users are encouraged to obtain root certificates from a qualified certificate authority (CA). Users are strongly discouraged from acting as their own CA.

Certificate-Based Provisioning, as its name suggests, relies on certificates. Each device that participates in Certificate-Based provisioning must be preprogrammed with a:

- **private key**, which can be used to prove the identity of the device.

> **Note**: It is critical that the device private signing key be stored securely.

- **One of the following:**  
  - **Corresponding device certificate**, which holds the identity of the device (including the public key of the device), optionally with one or more intermediate certificates  
  - URI pointing to a server where the device certificate can be downloaded

Additionally, the provisioner must know which are the trusted devices. Therefore, the provisioner must be preprogrammed with the root certificate(s) used to create the certificate chain of any device to be provisioned with a **Certificate Authority (CA) Certificate**, which can be used to validate any certificate that belongs to a trusted device.

Putting this into practice, the following steps must be done before Certificate-Based Provisioning can be applied:

1. A CA Certificate must be created (with self-signing) along with a CA private key that will be used to sign all the device certificates. This is done on a computer. Note that the private key must be securely stored, preferably in a hardware security module (HSM). At a minimum, the private key must not leave this machine.
2. Each device must generate a private key. These private keys must be generated on the devices, and they must not leave the devices.
3. Each device must generate its device certificate signing request, which holds its public key (generated from its private key) and the credentials.
4. Each device must get its device certificate signing request signed by the CA. To do this, the certificate signing request must be transmitted to the central machine (this can be done via UART), and the signed certificate must be transmitted back to the device.
5. The CA certificate must be stored on the provisioner so that it can validate the device certificates of the provisionee devices.

Because this process is not easy to implement, Silicon Labs provides sample applications that do all the required steps.

- The **Bluetooth Mesh - SoC CSR Generator** sample app generates the private key and the device certificate signing request on the device. It can also be used to connect to the certificate authority and send over the device certificate signing request to be signed.
- The **create_authority_certificate.py** (CA) Python script can be used to generate the CA certificate along with the private key. It also creates a header file with the CA certificate that can be stored on the devices.
- The **production_line_tool.py** (PLT) Python script can be used for reading out the device certificate signing requests (CSRs) from the requesting devices, signing the CSRs with the CA private key, and flashing them back to the device.

> **Note**: the private key used by this script is visible in plain text, therefore this tool is not to be used in a secure production environment, a hardware security module (HSM) must be used instead.

The Python scripts can be found in the following folder: {SDK_folder}/app/bluetooth/script/certificate_authorities.

![Signing the Device Certificates](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image2.png)

To generate the device certificate and get it signed, follow this process:

1. Factory-reset your device to make sure that no keys and certificates are stored on it. You can do this with Simplicity Commander using the **Recover Bricked Device** option in the GUI or with the following CLI command: commander device recover.
2. Flash an **Internal Storage Bootloader** to your device. (Must be generated and built as a separate project.) See [Gecko Bootloader User’s Guide for Series 3 and Higher](/btmesh/11.0.0/bootloader-user-guide-series3-and-higher) or [Gecko Bootloader User Guide](/btmesh/11.0.0/bootloader-user-guide-gsdk-4) for specific instructions.
3. Create a new **Bluetooth Mesh- SoC CSR Generator** project in Simplicity Studio.
4. Open the slcp file of the project.
5. On the **Overview** tab, under **Project Details**, open the three-dots-menu, and click the **Configuration** button as shown below.  
   ![Configuration button](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image3.png)
6. Modify the **Certification Subject Data** fields so that your certificate subject contains your company’s information.  
   ![Certificate Subject Data field](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image4.png)
7. Build and flash the project to your device. This will automatically generate the private-public key pair and the certificate signing request on startup.
8. Create a CA certificate. Skip this step if you already have a root certificate you wish to use. Install the Python modules cryptography and jinja2 as follows:  
   ```bash  
   pip3 install cryptography  
   pip3 install jinja2  
   ```  
   Once these modules have been installed, create the CA certificate with the following command:  
   ```bash  
   python3 *{SDK\_folder}*\app\bluetooth\script\certificate authorities\create_authority_certificate.py  
   ```  
   **Note**: This certificate will be created with factory default parameters to customize the certificate with your own unique identifiers. See the help menu for this script, which is available by running the following command:  
   ```bash  
   python3 \<Gecko sdk root\>\app\bluetooth\script\certificate authorities\create_authority_certificate.py -h.  
   ```
9. The CA certificate can now be found in _{SDK_folder}_\app\bluetooth\script\certificate authorities\central_authority\certificate.pem.
10. Check the Jlink serial number of your debug adapter either with Simplicity Studio or with Simplicity Commander by using the command commander adapter probe.  
    ![Jlink serial number](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image5.png)
11. Run the **production_line_tool.py** python script on your computer with the following parameters:  
    ```bash  
    Python3 {SDK_folder}\app\bluetooth\script\certificate authorities\production_line_tool.py --serial \<serialnumber\>  
    ```  
    This will read out the signing request, sign the device certificate, and flash the signed certificate on the device. _Note: the 'serial' parameter is not required if only one device is connected to your PC._
12. Now the key pair and the signed certificate are stored on your device. You can flash a new application to the device. At this stage, it is important to ensure that the flash is not completely erased. Simply flashing a new application, and bootloader if required, are sufficient.

> **Note**: It is important to add a bootloader to your new project that has secure boot enabled. This ensures that the firmware you programmed to the device cannot be changed. See [Series 2 and Series 3 Secure Boot with RTSL](/btmesh/11.0.0/series2-secure-boot-with-rtsl) for more information on secure boot.

##### Preparing a Device for Certificate-Based Provisioning

###### Device

Once a device certificate, and optionally any intermediate certificates, have been installed on the device, there are a few steps as follows to configure the device for Certificate-Based Provisioning:

1. Call `sl_btmesh_node_init_oob()` to indicate that the device has an out-of-band public key.
2. Enable support for provisioning records by calling `sl_btmesh_node_init_provisioning_records()`.
3. Start unprovisioned beaconing by calling `sl_btmesh_node_start_unprov_beaconing()`.

##### Example

###### BTMesh SOC Empty CBP

This section covers the use of the “Bluetooth Mesh – SoC Empty with Certificate-Based Provisioning Support” sample application found in the Gecko SDK.

###### Creating Device Certificate on Device (heading level 7)

1. Follow the steps for creating a device certificate, which are detailed in section [Creating Example Certificate Authority and Device Certificate](03-creating-example-certificate-authority-and-device-certificate).
2. Create an instance of the “Bluetooth Mesh – SoC Empty with Certificate-Based Provisioning Support” sample application for your chosen device.
3. Build the application and flash the output file to your device.

###### Provisioning with the Bluetooth Mesh mobile app

Silicon Labs Bluetooth Mesh mobile app supports Certificate-Based Provisioning starting in version 4.1.0. To being provisioning a node with CBP, open the Bluetooth Mesh mobile app, select the Provision tab, and tap the scan icon as shown below.

![Provision tab](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image6.png)
![Scan](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image7.png)

In the dialog for the unprovisioned node, ensure that the **Use Certificate-based Provisioning** option is enabled then tap the **Obtain certificate from the device** icon as shown below.

![Enabled ](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image8.png)

Once the device certificate has been sent, the **Device certificate** status changes to **Available** as shown below.

![Status Available 1](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image9.png)
![Status Available 2](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image10.png)

Tap the **Select certificate** icon to browse for the root certificate. **Note**: The root certificate must be accessible to the mobile device either through its filesystem or in a cloud storage service such as Dropbox. Once the root certificate file has been selected, it is shown on the Provisioning Records Summary dialog.

Tap the **Provisioning** button at the bottom of the screen to complete the provisioning process.

###### Provisioning with the BT Mesh Host Provisioner Sample Application

The btmesh-host_provisioner sample application runs on a posix-type platform such as RaspberryPi. For instructions on getting started building the Host Provisioner sample app, see [AN1371 - Bluetooth Mesh NCP Host Provisioner Example Walkthrough](https://www.silabs.com/documents/public/application-notes/an1371-bluetooth-mesh-host-provisioner-example.pdf). Note that when exporting the Bluetooth Mesh Host Provisioner code it is necessary to include the CBP flag as follows:

```bash
make export CBP=1
```

To enable Certificate-Based Provisioning, rebuild the sample with the following command:

```bash
make CBP=1
```

###### Installing Root Certificates (heading level 7)

For the BT Mesh provisioner to validate device certificate chains, it must have the root certificate for those chains. The root certificates must be stored in PEM format in the file **CA/ca-certificate.crt** under the BT Mesh host provisioner source folder.

**Example**

The root certificate generated by the script mentioned in section will be C:\Users\<user>\SimplicityStudio\SDKs\gecko_sdk\app\bluetooth\script\certificate_authorities\central_authority\certificate.pem.

Copy this file to the provisioner host:

```bash
\<path to exported files\>/app/btmesh/example_host/btmesh_host_provisioner/CA/ca-certificate.crt
```

###### Specifying a Base URI for Certificate Retrieval (heading level 7)

This section describes how to customize the sample application to include a base URI for certificate retrieval in the provisioning records.

1. Add the following code to the top level of the project’s app.c file.  
   ```C  
   struct mesh_const_provisioning_record {  
   const uint8_t *ptr; //< Provisioning record data  
   uint16_t len; //< Length of provisioning record data  
   };  
   /** Number of spec-defined intermediate certificates */  
   #define MESH_INTERMEDIATE_CERTIFICATE_COUNT 15  
   struct mesh_const_provisioning_records {   
   /** Certificate-based provisioning base URI */  
   struct mesh_const_provisioning_record base_uri;   
   /** Complete local name */  
   struct mesh_const_provisioning_record complete_local_name;   
   /** Appearance */  
   struct mesh_const_provisioning_record appearance;   
   /** Intermediate certificate 1 to 15 */  
   struct mesh_const_provisioning_record intermediate_certificate[MESH_INTERMEDIATE_CERTIFICATE_COUNT];  
   };  
   extern const struct mesh_const_provisioning_records *mesh_const_provisioning_records;   
   static const struct mesh_const_provisioning_records records = {  
   .base_uri = {  
   (const uint8_t *)"\x17//www.example.com/",   
   19,  
   },  
   .complete_local_name = {  
   NULL,  
   0,  
   },  
   .appearance = {  
   NULL,  
   0,  
   },  
   .intermediate_certificate = {  
   { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 },  
   { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 },  
   { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 },  
   },  
   };  
   ```
2. Edit the ‘base_uri’ member to point to the desired URI.
3. Add the following line to `app_init()`:  
   ```C  
   mesh_const_provisioning_records = &records;  
   ```
4. Build the project and download the binary to the target board.
5. Scan for the node as described above. Now the BTMESH mobile app will show that the URI is available as shown below:

![URI Available](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image11.png)

###### Running the BT Mesh Host Provisioner (heading level 7)

The BT Mesh host provisioner can provision nodes to a network with the node’s 128-bit UUID which is obtained by scanning as shown below:

`./exe/btmesh_host_provisioner -u \<serial port\> --scan --c`

![Example 1](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image12.png) as desc

Once the node’s UUID has been found, it can be used to provision the device as shown below:

```bash
./exe/btmesh_host_provisioner -u \<serial port. –c –provision \<UUID\>
```

Example:

```bash
./exe/btmesh_host_provisioner -u /dev/ttyACM0 --c -b 115200 --provision 9c93e21b4ea4a65d871031d7f67bb702
```

![Example 2](/btmesh-certificate-based-provisioning/10.0.0/images/sld822-image13.png)

Now the node is provisioned on the network and can be configured for groups and functionality. For specifics, refer to [AN1371, Bluetooth Mesh NCP Host Provisioner Example Walkthrough](https://www.silabs.com/documents/public/application-notes/an1371-bluetooth-mesh-host-provisioner-example.pdf).

### Performance

#### Performance

This section provides links to Bluetooth Mesh performance documents.

- [**Bluetooth Mesh 1.1 Network Performance**](/btmesh/11.0.0/btmesh-11-network-performance): Highlights performance metrics of new Bluetooth Mesh 1.1 features and provides a performance overview of Silicon Labs’s Bluetooth Mesh software and hardware.
- [**Bluetooth Mesh Device Power Consumption Measurements**](/btmesh/11.0.0/btmesh-power-consumption-measurements): Describes Low Power Node (LPN) and Friend node operation and the parameters related to power consumption.
- [**Bluetooth Mesh Parameter Tuning for Network Optimization**](/btmesh/11.0.0/btmesh-network-optimization): Describes in detail how the Bluetooth Mesh topology can influence network operation.
- [**Bluetooth Mesh Interoperability Testing Report**](/btmesh/11.0.0/bt-mesh-interop-report): Includes the results of the interoperability testing of Silicon Labs’ ICs and Bluetooth Mesh stack with Android and iOS smart phones.

#### Bluetooth Mesh GATT Proxy Best Practices

The GATT Proxy feature in Bluetooth Mesh is useful in allowing devices
such as mobile phones access a Bluetooth Mesh network. Careless use of
the feature may, however, adversely affect the performance of the
network. This document describes best practices that can be used to
configure GATT proxying in a way that does not burden the network.
It also highlights some best practices related to security and
privacy.

##### Consider the Effect of Proxy Service Advertisement on the Network

GATT Proxy servers announce their availability to act as proxies by
advertising the GATT Proxy service using connectable advertisements.

These advertisements occupy the same three advertisement channels that
are used by Mesh data traffic, so care should be taken to not
advertise too often. This is especially the case when there are
multiple GATT Proxy servers in the radio range of each other. For
example, ten GATT Proxy servers near each other, each advertising with
a 100ms interval, produce 100 service advertisements each second in
the area where their radio ranges overlap.

There are three ways to limit the number of GATT Proxy service
advertisements:

- The BGAPI call  
  [sl_btmesh_node_set_proxy_service_adv_interval](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-node#sl-btmesh-node-set-proxy-service-adv-interval)  
  can be used to set the advertisement timing locally on a node.
- The Configuration Manager of the network can remotely toggle GATT  
  Proxy service on or off on a node by using the BGAPI call  
  [sl_btmesh_config_client_set_gatt_proxy](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-config-client#sl-btmesh-config-client-set-gatt-proxy).
- The [On-demand Private Proxy Server](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-on-demand-private-proxy-server)  
  can be used instead of the regular GATT Proxy server. The on-demand  
  server only starts service advertising when it receives a Proxy  
  Solicitation Request from a node. A solicitation request can be  
  sent using [sl_btmesh_proxy_send_solicitation](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy#sl-btmesh-proxy-send-solicitation) BGAPI command.

##### Filter the Proxied Traffic

Only the traffic that the proxy client needs from the network should
be passed across the proxy connection. Even if the connection between
the proxy client and the proxy server has more bandwidth than the
advertisement-based Mesh bearer, a slow connection interval may result
in a queue of PDUs building up on the proxy server
side. Furthermore, the proxy server likely has other duties than just
proxying, so it should not be burdened with proxying unneeded data to
the client.

Proxy filtering controls what PDUs are passed over the proxy
connection. It can be configured with the following BGAPI commands:

- [sl_btmesh_proxy_set_filter_type](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy#sl-btmesh-proxy-set-filter-type) sets the type of filtering (an accept list or a reject list). An accept list is appropriate when the filtering should be done with a small number of addresses to allow traffic from, and to reject anything else; a reject list is appropriate when the filtering should be done with a small number of addresses to reject traffic from, and to allow anything else.
- [sl_btmesh_proxy_allow](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy#sl-btmesh-proxy-allow) allow traffic from the given address. In the case of an accept list, the command adds the address to the list; in the case of a reject list, the command removes the address from the list.
- [sl_btmesh_proxy_deny](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy#sl-btmesh-proxy-deny) block traffic from the given address. In the case of an accept list, the command removes the address from the list; in the case of a reject list, the command adds the address to the list.
- [sl_btmesh_proxy_optimisation_toggle](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy#sl-btmesh-proxy-optimisation-toggle) provides an option to automatically allow unicast PDUs so that only those PDUs whose destination is the proxy client are passed over, regardless of the filter list contents.

##### Consider Proxy Privacy

The regular GATT Proxy Server advertises the proxy service in a manner
that can be tracked, due to both the Bluetooth address and the service
data in the service advertisements containing unchanging
information. A passive observer may keep track of the addresses and
service data it sees, and deduce that it is seeing the same device
again if the information remains constant. While this is maybe not an
issue for stationary networks, such as lighting networks, that are
bound to a fixed location, trackability of devices may be an issue in
some contexts.

Private proxy service advertisements resolve this issue by use of
private Bluetooth addresses that change from time to time, and by use
of service data that changes from time to time. This means that passive
tracking is only possible for the short period before the advertised
address and data changes.

Proxy privacy can be remotely controlled on a proxy server by
[sl_btmesh_private_beacon_client_set_gatt_proxy](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-gatt-proxy)
and
[sl_btmesh_private_beacon_client_set_identity](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-identity)
BGAPI calls available in the [Private Beacon
Client](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-private-beacon-client). The
[Private Beacon Server](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-private-beacon-server)
must be enabled on the proxy server node.

Proxy privacy can be combined with [On-demand Private Proxy Server](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-on-demand-private-proxy-server) described in the following section.

##### Limit Proxy Visibility

By its nature, a proxy server needs to allow LE connections from proxy
clients, and it needs to advertise its presence and availability for
connections using service advertisements so that clients know where to
connect to.

This mechanism makes the presence of a proxy server visible to
everyone, not just the legitimate proxy clients. Someone wanting to
create nuisance can connect to a proxy (repeatedly, if the connection
closes after a timeout) and keep the proxy server occupied so that it is not
available to the legitimate users.

Outside of physical security, the best way to counter such
troublemakers is to use the [On-demand Private Proxy Server](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-on-demand-private-proxy-server)
instead of the regular GATT Proxy server. The on-demand server only
starts service advertising when it receives a Proxy Solicitation
Request from a node, so it is not visible to anyone until that
happens. A solicitation request can be sent using
[sl_btmesh_proxy_send_solicitation](/btmesh/11.0.0/bluetooth-mesh-api/sl-btmesh-proxy#sl-btmesh-proxy-send-solicitation)
BGAPI command.

Solicitation requests are encrypted and can only be sent by nodes that
know the network key. Furthermore, solicitation replay protection
blocks attempts to record and later replay legitimate solicitation
requests. These measures are put in place to help ensure that only
nodes that are a part of the network can make proxy solicitation
requests.

#### Bluetooth Mesh 1.1 Network Performance

##### Bluetooth® Mesh 1.1 Network Performance

> **NOTE: This section replaces _AN1424: Bluetooth® Mesh 1.1 Network Performance_. Further updates to this application note will be provided here**.

This application note highlights performance metrics of new Bluetooth Mesh 1.1 features and provides a performance overview of Silicon Labs’s Bluetooth Mesh software and hardware.

This application note demonstrates how the Bluetooth Mesh network performs overall, with detailed results on the performance of Remote Provisioning and Over-the-Air Device Firmware Update (OTA DFU), both introduced in the 1.1 version of the Bluetooth Mesh specification. The test environment was a commercial office building with active Wi-Fi and Bluetooth Low Energy (LE) networks in range. Wireless test clusters were deployed in hallways, meeting rooms, offices, and open areas. The methodology for performing the benchmarking tests is defined so that others may run the same tests in their environment. These results are intended to provide guidance on design practices and principles as well as expected field performance results.

###### Key Points

- Wireless test network in Silicon Labs Research and Development (R&D) office is described.
- Wireless conditions and environments are evaluated.
- Mesh 1.1 network performance including throughput, latency,and large network scalability is presented.

##### Introduction and Background

Silicon Labs has provided performance testing results from embedded mesh networks as part of developer conferences and industry white papers. The basic performance data of throughput, latency, and impact of security can be used by system designers to define expected behavior. This testing has previously been presented for Zigbee and Thread networks as basic 15.4 mesh networking technologies. These were presented because performance varies even though both systems use the same underlying physical layer defined by IEEE 802.15.4. With the advent of Bluetooth mesh networks, it is common for questions to arise concerning the expected performance differences between a Bluetooth mesh and these 15.4 mesh networks. Prior to discussing the testing and performance differences, we need to review the underlying technologies of these networks as it helps to understand their performance differences.

###### Underlying Physical Layer and Packet Structure

Network performance is based on payload sizing since the application usage does not account for the packet overhead.

Bluetooth low energy is based on the BT 4.x specification and has a 33-byte packet with an underlying data rate of 1 Mbps. The Bluetooth mesh packet size is shown in the figure below and results in a 12 or 16-byte payload. For payloads above 12 bytes, there is a process of segmentation and reassembly.

Bluetooth mesh has a higher data rate but the packet payload is smaller; therefore, it takes more packets to send the same amount of data. Our data on performance is based on payload size as this is the design parameter of concern when building an application. The Bluetooth mesh has designed mesh profiles (application layer) to specifically minimize the packet payload and fit in a single packet where possible.

| |1| |1|3|2|2|12 or 16|4 or 8|
|---|---|---|---|---|---|---|---|---|
|IVI|Network ID|CTL|TTL|Sequence Number|Source Address|Dest Address|Packet Payload|NWK MIC|

Bluetooth Mesh Packet Format

###### Network Routing Differences

Bluetooth mesh uses a managed flooding technique to relay messages instead of routing. This means that instead of building, maintaining, and using defined routes to send messages, Bluetooth mesh relays relay the messages they hear using the following two simple rules:

1. Every message has a unique sequence number.
2. Relays keep track of the recently seen sequence numbers and do not relay the messages they have already seen or relayed before.

The messages also have a time-to-live counter (TTL) and every time a message is relayed, the counter is reduced by one until it reaches a value indicating that it should no longer be relayed.

As there are no acknowledgements used at the network level, Bluetooth mesh relays can be configured to repeat the same message multiple times so that more reliability is achieved due to the air interface packet loss. Typically, this value is set to 3, so each relay repeats the same message three times. Also, a configurable delay between the repetitions is used to optimize between latency and network performance. The minimum delay between repetitions, called the retransmission interval = (Relay Retransmit Interval Steps + 1) * 10ms + 0-10ms random delay, is typically 15 ms per hop.

> **Note**: This performance data is for the Silicon Labs implementation of these mesh networking stacks. As is shown in the test network and infrastructure provided for this testing, no tests were performed with other stacks or systems.

This application note also focuses on the performance of new features introduced in the Bluetooth Mesh 1.1 specification, such as Remote Provisioning and OTA DFU.

##### Goals and Methods

This application note defines a set of tests performed to evaluate mesh network performance, scalability, and reliability and to evaluate the performance of the new BT Mesh 1.1 features. The test conditions and infrastructure are described for these tests, which are conducted over actual wireless devices in test networks and not in simulation.

This testing was done to provide an overview of the Remote Provisioning and OTA DFU performance and to characterize the network used for these tests with the help of the throughput and latency tests.

Since the tests were carried out in a real-life environment, background noise was present at the time of the tests. These noises come from the Bluetooth/Wi-Fi devices in the office used by the employees, as well as from the other test benches in the office, which are in the order of hundreds. While it might be useful to execute the tests in such a noisy environment, some noise reduction was implemented.

For the Remote Provisioning performance test, a multi-hop setup was used, where the performance based on the number of hops in the network was measured.

For the OTA DFU performance test, since the substantial number of nodes prevented having a shielded environment, the tests were carried out in timeslots with no human presence in the office, and with the testbenches turned off on the whole floor. This enabled testing in a slightly more regulated environment.

##### Test Network and Conditions

For Remote Provisioning performance testing, Silicon Labs built an RF-shielded environment to filter out the ongoing interference in the office area.

Large network testing is best conducted in an open-air environment for multiple reasons. The existing and varying RF conditions make this environment closer to a real-life scenario. However, the tests were conducted in the evening of workdays, and on the weekend, to eliminate some of the noise created by the human work in the office. The Silicon Labs Budapest office was used for this open-air testing.

###### Office and Test Network Conditions

The multicast latency and the OTA DFU tests were carried out on the large network test setup located in the office. A total of 43 boxes were scattered around the floor, each containing 4-6 devices to create a 256-node network on a large area with naturally occurring hops in the network.

Each box contained six Silicon Labs Wireless Starter Kits (WSTKs), except one, which contained four WSTKs. The first 27 boxes had four BRD4186C (EFR32xG24) and two BRD4181B (EFR32xG21) radio boards each. Boxes 28-42 had three BRD4186C and three BRD4181B radio boards. Box 43 had four BRD4186C radio boards and one BRD4181B radio board.

The office is rectangular in shape, with sides of 38m and 19m. There is an 18.5m by 7.5m area where devices were not placed because of stairs, elevators, bathrooms, and different maintenance rooms.

![Large Network Topology](/btmesh-11-network-performance/10.0.0/images/sld823-image1.png)

###### Wireless Conditions in the Office

There were multiple test setups located on the floor, with hundreds of devices using BLE protocol. In the office, there were also four different Wi-Fi networks accessible on 2.4 GHz. The following chart was taken as a snapshot of a normal workday Wi-Fi scan. This is considered the normal Wi-Fi background traffic.

![normal Wi-Fi background traffic](/btmesh-11-network-performance/10.0.0/images/sld823-image2.png)

Running the tests on the evenings and weekends eliminated a large part of this noise, while maintaining real-life scenarios.

###### Multi-Hop Test Network

For the Remote Provisioning performance and multi-hop latency, tests were carried out in an RF-shielded multi-hop test network. Eight RF isolation boxes were chained together via SMA and attenuation barrels, and each of these boxes contained at least one BRD4187C (EFR32xG24) radio board, which were used for the BT Mesh test cases. This setup ensured that no RF interference affected the testing, minimizing variability, while also creating six hops in the network.

##### Testing and Results

###### Latency

The latency was tested both in the open-air and RF-shielded environment.

###### Bluetooth Mesh Unicast Latency

Silicon Labs tested sending unicast one-to-one payload messages at the defined rate and measuring the packet round trip time, by having the client model acknowledge the packets sent by the server mode in one of two ways:

- Lower transport layer acknowledgements of segmented PDUs
- Client model layer acknowledgements of unsegmented PDUs

During the tests, only one relay was configured for each hop.

The following parameters were used for each test:

|**Parameter**|**Description**|**Used Values**|
|---|---|---|
|Size of network|Number of nodes used for the test|2-8|
|Run size|Number of payload sends to attempt|1,000|
|PDU size|Size of the PDU in bytes|8, 11, 16, 32, 48, 64, 96, 128|
|Net TX|Network transmission repeat count|3|
|Relay TX|Relay level repetition count|3|
|Rate|Rate at which the messages are dispatched from the server in ms|1,500|
|Number of hops|The number of daisy-chained relay nodes in the network|1-7|
|Segmentation|8 and 11 bytes PDUs can be send out without segmentation, but segmentation forcing can be set up|8, 11 bytes: with and without segmentation 16, 32, 48, 64, 96, 128: with segmentation|

![Buletooth Mesh Latency](/btmesh-11-network-performance/10.0.0/images/sld823-image3.png)

![Buletooth Mesh Unsegmented](/btmesh-11-network-performance/10.0.0/images/sld823-image4.png)

![Bluetooth Mesh small payload comparison](/btmesh-11-network-performance/10.0.0/images/sld823-image5.png)

###### Bluetooth Mesh Multicast Latency (heading level 7)

For this test, there was one server node and multiple client nodes subscribed to a network address. The server sent the packets to this address, and the time between sending and receiving on a given client was measured for each client separately.

The server node was set to be a device on box #6 in the lower right corner of the office, in order to ensure that at least one naturally occurring hop was in the network.

The test steps:

1. Configure the server and the clients.
2. One client triggers the payload sending on the server with the desired configuration using a Test Config message.
3. Server sends payloads and generate BGAPI events, which are recorded.
4. Clients receive payloads and generate BGAPI events, which are recorded.
5. Process the recorded event to calculate latency.

![calculate latency](/btmesh-11-network-performance/10.0.0/images/sld823-image6.png)

The parameters used for the test:

|**Parameter**|**Description**|**Used Values**|
|---|---|---|
|Size of network|Number of nodes used for the test|10, 50, 100, 256|
|Run size|Number of payload sends to attempt|1,000|
|PDU size|Size of the PDU in bytes|8, 16, 32|
|Net TX|Network transmission repeat count|3|
|Relay TX|Relay level repetition count|3|
|Rate|Rate at which the messages are dispatched from the server in ms|3,000|
|Relay frequency|The frequency at which the nodes are set to behave as a relay (5 meaning that every 3rd node in the network is set to be a relay)|1, 6|

**Results based on node network size**

![10 Node](/btmesh-11-network-performance/10.0.0/images/sld823-image7.png)

![50 Node](/btmesh-11-network-performance/10.0.0/images/sld823-image8.png)

![100 Node](/btmesh-11-network-performance/10.0.0/images/sld823-image9.png)

![256 Node](/btmesh-11-network-performance/10.0.0/images/sld823-image10.png)

**Results based on PDU size**

![8 byte](/btmesh-11-network-performance/10.0.0/images/sld823-image11.png)

![16 byte](/btmesh-11-network-performance/10.0.0/images/sld823-image12.png)

![32 byte](/btmesh-11-network-performance/10.0.0/images/sld823-image13.png)

**Results with Advertising Extension (AE)**

![256 Node](/btmesh-11-network-performance/10.0.0/images/sld823-image14.png)

###### Remote Provisioning Performance

To test the time of the remote provisioning based on the number of hops between the Remote Provisioning Server and Remote Provisioning Client, the test is carried out in the multi-hop RF-shielded test setup. The layout of the devices in the RF-shielded boxes can be seen on the next table. Note that each box can receive messages only from the neighboring boxes.

|Box|1|2|3|4|5|6|7|8|
|---|---|---|---|---|---|---|---|---|
|Devices in box|Remote Provisioning Server (**S**) Remote Provisioning Client (**C**)|Device0 (**D0**)|Device0 (**D1**)|Device0 (**D2**)|Device0 (**D3**)|Device0 (**D4**)|Device0 (**D5**)|Device0 (**D6**)|

**Test Steps**

1. The Remote Provisioning Server node (server = **S**) was provisioned traditionally by the Provisioner (Remote Provisioning Client = client = **C**). Relay mode was enabled on **S**.
2. The first device (device0 = **D0**) was provisioned remotely, this was the 0 hops case. Elapsed time was measured.
3. Relay mode was enabled on **D0**.
4. Remote Provisioning Server was initialized on **D0**.
5. Iterated through the remaining devices, where i started at 1:
6. **Di** started unprovisioned beaconing.
7. **C** opened link between **Di** and **Di-1** using the Remote Provisioning Bearer.
8. **Di** was provisioned remotely. Elapsed time was measured.
9. Relay mode was enabled on **Di**.
10. Remote Provisioning Server was initialized on **Di**.

Only the time between starting the provisioning (issuing `btmesh prov_provision_remote_device`) and receiving the provisioned event (`btmesh_evt_node_provisioned`) was measured.

![Remote Provisioning](/btmesh-11-network-performance/10.0.0/images/sld823-image15.png)

###### Over-The-Air Device Firmware Update (OTA DFU) Performance

###### Introduction (heading level 7)

See [Bluetooth Mesh Device Firmware Update](/btmesh/{build-docspace-version}/btmesh-device-firmware-update) for details on this feature. This document focuses more on the performance aspects of this feature, when running on larger, open-air networks.

Note that, while the target nodes are receiving the new image, the Mesh network remains operational, although the packet latency and loss rate might increase due to the increased amount of network traffic. It is also important to note that, if some target nodes fail to receive the new image, or the whole distribution fails for some reason, then the target nodes remain operational (running their old software), and the device firmware update procedure can be repeated.

It is possible to do multiple rounds of image distribution with different sets of target nodes, or with different distributor nodes, so it is not mandatory to update the whole network at once.

To test the Mesh OTA DFU feature, a software setup is used that would be easy to reproduce. That means such examples are used that are present in the release GSDK package, so no custom embedded application is needed to reproduce the results.

The image distribution is done using push transfer mode.

Distribution time is also measured with the Advertisement Extension (AE) feature enabled, which achieves better performance by increasing the network packet size. This is described in detail in _AN1405: Bluetooth Mesh on Advertising Extensions_.

###### Initiator Configuration (heading level 7)

As an initiator, the BT-Mesh Host DFU example application was used, running on a PC (tested on Windows and Linux as well), with a Bluetooth Mesh - NCP Empty v1.1 application on the embedded side, running on a BRD4186C board. The example application had the following changes in it:

New component added:

- btmesh_stack_advertiser_extended

Parameters changed:

- NVM3_DEFAULT_CACHE_SIZE:2200
- SL_BT_CONFIG_BUFFER_SIZE:40000
- NVM3_DEFAULT_NVM_SIZE:0x18000
- SL_HEAP_SIZE:30000
- SL_STACK_SIZE:11264
- SL_BTMESH_CONFIG_MAX_PROVISIONED_DEVICES:155
- SL_BTMESH_CONFIG_RPL_SIZE:155

###### Distributor Configuration (heading level 7)

As a distributor, the Bluetooth Mesh - SoC DFU Distributor example application was also running on a BRD4186C. It had the following changes:

New components added:

- btmesh_event_log
- btmesh_ae_server
- btmesh_firmware_update_server

Parameters changed:

- SL_BTMESH_CONFIG_MAX_RECV_SEGS:40
- SL_BTMESH_CONFIG_MAX_SEND_SEGS:20
- SL_BTMESH_FW_DIST_SERVER_MULTICAST_THRESHOLD_DEFAULT_CFG_VAL:1
- SL_BTMESH_BLOB_TRANSFER_CLIENT_LOGGING_CFG_VAL:0
- SL_BTMESH_BLOB_TRANSFER_CLIENT_LOG_BLOB_STATUS_MSG_CFG_VAL:0
- SL_BTMESH_BLOB_TRANSFER_SERVER_DIST_TARGET_MAX_CHUNKS_PER_BLOCK_CFG_VAL:0x28
- SL_BT_CONFIG_BUFFER_SIZE:60000
- SL_HEAP_SIZE:50000
- SL_STACK_SIZE:16384
- SL_BTMESH_CONFIG_MAX_PROV_BEARERS:3
- SL_BTMESH_FW_DIST_SERVER_MAX_NODE_LIST_SIZE_CFG_VAL:155
- SL_BTMESH_BLOB_TRANSFER_CLIENT_MAX_SERVERS_CFG_VAL:155
- SL_BTMESH_BLOB_TRANSFER_CLIENT_RETRY_TIME_MS_DEFAULT_CFG_VAL:1000
- SL_BTMESH_CONFIG_RPL_SIZE:155
- SL_BTMESH_BLOB_TRANSFER_CLIENT_MAX_BLOCKS_CFG_VAL:1024

The SAR Transmitter state (SAR Configuration Server model) was also modified:

- SAR Multicast Retransmissions Count state = 2
- SAR Multicast Retransmissions Interval Step = 25 ms

###### Target Nodes Configuration (heading level 7)

As target nodes, the Bluetooth Mesh - SoC Sensor Server was used both on BRD4186C and BRD4181B boards.

New components added:

- btmesh_event_log
- btmesh_ae_server

Parameters changed:

- SL_BTMESH_BLOB_TRANSFER_SERVER_DFU_TARGET_MAX_BLOCK_SIZE_LOG_CFG_VAL:0xb
- SL_BTMESH_BLOB_TRANSFER_SERVER_DFU_TARGET_MAX_CHUNKS_PER_BLOCK_CFG_VAL:0x28

###### Test Setup (heading level 7)

The distributor and the initiator node were chosen to be at the center of the network as much as possible, and close to each other. They were chosen to be in cluster number 8 (see [Office and Test Network Conditions](03-test-network-and-conditions#office-and-test-network-conditions)).

The tests were run with multiple network sizes and with or without the increased network PDU size (advertisement extension).

Two GBL files were used as update targets. One was a so called, dummy image that was smaller, and the nodes failed to verify it so would not apply it, and the other one was a real SOC Sensor Server GBL file that was much larger, and the nodes successfully applied it after the distribution. In the case of the dummy image, the test expected outcome was that the nodes would report a Verification Failed state at the end.

###### Summary of Important DFU Parameters

###### Block Size and Block Count (heading level 7)

The Block size is negotiated during the distribution, and in this case is affected by the Max Block Size Log configuration value on the target nodes. Note that increasing the maximum block size will result in increased heap usage, which could be especially critical on the target nodes, because those are usually more limited in resources such as RAM, and the whole block needs to be stored there during distribution. The higher block size will increase the chunk size as well when the maximum chunk count cannot be satisfied with the preferred chunk size.

Larger chunks have a higher probability of being lost because they contain more segments. The penalty of lost chunks is higher because more segments need to be retransmitted.

The configuration parameter (on the target nodes):

- SL_BTMESH_BLOB_TRANSFER_SERVER_DFU_TARGET_MAX_BLOCK_SIZE_LOG_CFG_VAL

Found in `sl_btmesh_blob_transfer_server_config.h`.

The Block Count was calculated from the BLOB Size and Block Size by ceil(BLOBSize / BlockSize) formula.

The Block Count affected the size of BLOB Transfer Status message and the number of Block Start & Query phases during BLOB Transfer.

N block results to ceil((23 + 8 x ceil(N / 8)) / 12) BLOB Transfer Status segments.

###### Firmware Distribution Server BLOB Multicast Threshold (heading level 7)

If the number of servers for any step exceeded or was equal to this number, then the group address was used; otherwise, servers were looped through one by one. Value of 0 disabled the feature.

Configuration parameter (on distributor):

- SL_BTMESH_FW_DIST_SERVER_MULTICAST_THRESHOLD_DEFAULT_CFG_VAL

Found in `sl_btmesh_fw_distribution_server_config.h`.

###### Distributor Segmentation and Reassembly Multicast Retransmission Count / Interval (heading level 7)

These parameters determined how many times and what interval each segment of a segmented multicast message was repeated on the Distributor.

The fields that were modified were:

- SAR Multicast Retransmissions Count State
- SAR Multicast Retransmissions Interval Step

These parameters were configured by setting the SAR Transmitter state at the SAR Configuration Server model on the distributor.

###### Distributor Max Send Segs and Max Recv Segs (heading level 7)

Maximum number of simultaneous BT-Mesh segmented message transmissions and receptions.

Configuration parameters (on distributor):

- SL_BTMESH_CONFIG_MAX_SEND_SEGS,
- SL_BTMESH_CONFIG_MAX_RECV_SEGS

These parameters are `found in sl_btmesh_config.h`.

###### Test Procedure Steps

The tests used the BT-Mesh Host DFU (`btmesh_host_dfu`) example script. For details about the following commands and their arguments, check the script help.

When the script runs the first time, it creates a default configuration file `btmesh_host_dfu_cfg.ini`. In this file, the following options are changed to accommodate the large network setup:

- [common]
- retry_max_default = 15
- retry_interval_default = 4.0
- retry_cmd_max_default = 15
- retry_cmd_interval_default = 2.0
- retry_multicast_threshold_default = 20
- retry_auto_unicast_default = True
- conf_retry_max_default = 10
- silabs_retry_max_default = 15
- silabs_retry_interval_default = 2.0
- auto_conf_dcd_query = false
- auto_conf_default_ttl = false
- auto_conf_network_tx = false
- auto_conf_sar = false
- [dist_clt]
- dist_retry_max_default = 100
- dist_retry_multicast_threshold_default = 100
- [network]
- random_netkey = false
- random_appkey = false

For further details, check the created INI file next to the script, where you will find these options with their default values and descriptions.

Target nodes are flashed with the modified SOC Sensor Server example application in batches of 5. Then, provisioning is done using advertisement bearer.

Groups are created from the nodes by executing the following commands:

**group add -a 0 -g 0xC000 -s *Dist*[1] -m distributor -n DG1**

**group add -a 0 -g 0xC001 -s *Target*[0] -m target_node -n TNG1**

The SAR configuration is done on the distributor node:

**conf set --sar-tx-mc-retx-cnt 2 --sar-tx-mc-retx-int 25 --update *Dist***

If the advertisement extension feature is used for testing, then the following group is created, and configuration is done to set the PDU size to 227 bytes:

**group add -a 0 -g 0xC002 -s *Node* -S SILABS_CONFIGURATION_SERVER -n AE1**

**conf ae -t 2m -p 227 --en --mdls *BLOB* -e 0 1 -g 0xFFFF -n ***

The tested update target image is uploaded to the distributor:

**dist upload -d *Dist*[1] -f 0x02ff:s:test_image -m s:0123 -T 1 example.gbl**

The test starts a timer to measure the distribution time, and then executes the distribution:

**dist start -d *Dist*[1] -f 0x02FF:s:test_image -G TNG1 -T 10 --poll-int 20**

After the above command finishes, a table is printed out on the console with the target node statuses, and in case of a dummy image, the test expects the state to be “verification failed”, otherwise it expects “apply success”. The test measures the time of distribution when this table is printed out.

###### Network Topology

For measuring the transfer speed, a 60-node Mesh network was created. There were no relay nodes in this setup. On the floor plans below, the orange circle signals the location of the initiator and distributor nodes. The pale blue areas are where the clusters (containing six devices each), indicated with solid blue boxes, were used to form the network.

![60-Node Network Floor Plan](/btmesh-11-network-performance/10.0.0/images/sld823-image16.png)

###### 60-Node Network Results

Without the Advertising Extension feature enabled:

|Image Type|Image Size (b)|Time (min)|Failed Node Count|
|---|---|---|---|
|Dummy|21,160|16.0|1|
|Real|350,076|203.2|0|

With the Advertising Extension feature enabled:

|Image Type|Image Size (b)|Time (min)|Failed Node Count|
|---|---|---|---|
|Dummy|21,160|12.5|0|
|Real|350,076|158.2|0|

##### Summary

Performance testing of Bluetooth mesh shows excellent latency when the payload is contained within a single packet. Throughput results show latency can be maintained below 200 milliseconds, even out to 6 hops if the payload is less than 16 bytes.

For larger networks, as the number of nodes in the network increase or the packet payload increases, the latency also increases. The network size has a smaller effect on latency than the payload size, which can result in a large increase.

The reliability of these networks when running these results is greater than 99%.

To obtain low latency and high reliability in Bluetooth mesh applications:

- Application payload should fit into a single packet.
- Applications which require multicast messaging should not use segmented messages.

###### Follow-up Testing Considerations

The testing described in this application note requires follow-up tests to further define the device behavior and network operations. The following specific items are noted for follow-up testing:

1. Failure testing can also be added by dropping nodes out of this network during these tests to evaluate recovery time and impact on reliability.
2. Testing should be performed with different device types running in System-on-Chip and Network Co-Processor (NCP) modes. Previous testing has revealed some differences between these modes of operation, so this should be further characterized.

###### Related Literature

This application note has provided information on Bluetooth mesh networking. For information on Zigbee and Thread mesh networking, and a comparison of all three technologies, refer to the following application notes:

[Zigbee Mesh Network Performance](https://docs.silabs.com/zigbee/latest/zigbee-mesh-network-performance/)

[OpenThread Mesh Network Performance](https://www.silabs.com/documents/public/application-notes/an1408-openthread-mesh-network-performance.pdf)

[Mesh Network Performance Comparison](https://docs.silabs.com/zigbee/latest/mesh-network-performance-comparison/)

#### Bluetooth Mesh Device Power Consumption Measurements

##### Bluetooth Mesh Device Power Consumption Measurements

> **NOTE: This section replaces _AN1315: Bluetooth Mesh Device Power Consumption Measurements_. Further updates to this application note will be provided here**.

Silicon Labs offers a complete portfolio of fully-certified modules and System On a Chip (SoC) solutions for Bluetooth mesh connectivity that are known collectively as the EFR32BG family. This application note describes Low Power Node (LPN) and Friend node operation and the parameters related to power consumption. It also describes how to measure the power consumption of EFR32BG devices acting as Bluetooth mesh LPNs using the setup and procedures recommended in _AN969: Measuring Power Consumption on Wireless Gecko Devices_.

###### Key Points

- One EFR32BG WSTK is required.
- Another device can be an EFR32BG WSTK or an equivalent product.
- Test examples are available in the  
  Bluetooth Mesh SDK.
- Results from the test example are provided using an EFR32BG21.

##### Bluetooth Mesh Node Power Consumption

Bluetooth mesh nodes (other than Low Power nodes) are always listening for messages from the other nodes. Because the nodes are always on and receiving, they consume quite a lot of power and are typically connected mains or respective power sources (for example, coin or button cell batteries might have too short a lifespan for actual usage). You can learn about the radio/power operation and consumption in the datasheets for your part, SoC, or module.

The _Mesh Profile Bluetooth® Specification_ Revision v1.0.1 defines a Low Power Node, Friend node, and the concept of friendship as follows:

- Low Power Node: The ability to operate within a Bluetooth mesh network at significantly reduced receiver duty cycles. Minimizing the time the radio receiver is on leads to lower power consumption with the node only enabling the receiver when strictly necessary. LPNs achieve this through establishing a friendship with a Friend node.
- Friend Node: The ability to help an LPN operate by storing messages destined for the LPN and only forwarding them to it when the LPN explicitly requests messages from the Friend node.

###### Low Power Node and Friend Node

An LPN must first make a friendship with a Friend node. Once this has been established, the Friend node will receive and queue various messages going to the LPN on behalf of the LPN. There are configurable limitations for the messages that the Friend node can store for LPNs to control Friend node memory usage. Because the LPN does not have to be on and receiving all the time, it can sleep and periodically check the incoming messages from its Friend node. The LPN can send a mesh message to the Friend node and other nodes at any time. There are also some mechanisms like timeouts and maximum retries set for the communication and if those occur, the friendship will end. The friendship does not remain after restarting the device (LPN or Friend node). However, it is always possible to establish the friendship again.

###### Creating a Friendship

When the Friend node is started, it does not have any friendships with LPNs; it is just waiting for a Friend Request from LPNs. A Friend node can have several friendships with LPNs at the same time, depending on the Friends resources. After receiving Friend Requests with requirements that the Friend node can serve, the Friend node will reply with a Friend Offer. An LPN can also have requirements that are not compatible with the Friend node. In this case, the Friend node will not reply.

When the LPN is started, it also does not recall any friendships but starts transmitting Friend Request and waits for Friend Offer replies. Currently an LPN can have only one friendship at a time in the Silicon Labs implementation. When establishing a friendship, the LPN uses a great deal of power, so it usually wants to find a reliable friendship quite soon and not waste any power when searching for Friend nodes.

As the LPN sends Friend Requests, it will inform the Friend node of its requirements such as the PollTimeout and ReceiveDelay parameters (see [PollTimeout](#poll-timeout) and [ReceiveDelay](#receive-delay)). As a return it can get several Friend Offers from Friend nodes. The Friend node provides information about itself such as ReceiveWindow size, message queue size, message subscription list size and RSSI measured from the Friend node.

The timing parameters are illustrated in Figure 3.17: Friendship timing parameters of the _Mesh Profile Bluetooth® Specification_ Revision: v1.0.1.

After receiving Friend Offers, a very good Friend Offer, or waiting for Friend Offers for a while (depending on the implementation), the LPN will use some algorithm to select a Friend Offer that fits the best and sends a Friend Poll message to the selected Friend node. The Friend node replies with a Friend Update message which concludes the process by providing the security parameters and the friendship is established.

The friendship establishment is illustrated with one Friend node in Figure 3.19: Establishment of a friendship and for multiple Friend nodes in Figure 3.21: Friend establishment example of the _Mesh Profile Bluetooth® Specification_ Revision: v1.0.1.

###### Maintaining the Friendship

A Friend node is always listening for messages. If it does not receive certain messages (typically a Friend Poll) from an LPN before the PollTimeout has passed, the Friend node will terminate the friendship. If the Friend node receives a correct message from an LPN, it will send a message back after ReceiveDelay during the ReceiveWindow. The Friend node responds to Friend Poll messages with queued Bluetooth mesh messages that could be normal messages, configuration messages, or security updates. The Friend node informs the LPN that it has no more queued messages using a Friend Update reply with the MD flag set to 0. Other messages or Friend Update replies with the MD flag set to 1 will continue being sent to the LPN.

An LPN can send a Bluetooth mesh message at any time to a Friend node or other nodes. But it has to send certain messages (typically a Friend Poll) to its Friend node before the PollTimeout has passed; otherwise, the Friend node terminates the friendship. Also, if the Friend node does not reply to LPN messages after several retries (the default is three times), the Friend node terminates the friendship.

PollTimeout timer is illustrated in Figure 3.18: Poll Timeout timer illustration of the _Mesh Profile Bluetooth® Specification_ Revision: v1.0.1.

###### Low Power Node Settings

The following subsections describe the LPN settings related to the power consumption.

###### PollTimeout (heading level 7)

The PollTimeout setting has the following characteristics:

- Establishes a maximum time which may elapse between two consecutive requests sent by the LPN to its Friend node. If no requests from an LPN are received by the Friend node before the PollTimeout timer expires, the Friend terminates the friendship.
- Duration: 10 to 3,455,999 in 100 ms = 1 sec to 345,600 sec = 5,760 min = 96 hours = 4 days
- The longer the PollTimeout, the more the LPN can sleep. On the other hand, this also means that the LPN receives messages less often and it takes more time for other nodes or the Provisioner to communicate with the LPN.
- This is the most important parameter when controlling the LPN power consumption.

###### ReceiveDelay (heading level 7)

The ReceiveDelay setting has the following characteristics:

- The time which elapses between the LPN sending a request to the Friend node and the Friend node starting to listen for a response. This allows the Friend node time to prepare its response and send it back.
- Duration: 10 to 255 ms
- Requested by the LPN.
- If it is too small, the Friend node might not send a Friend Offer.
- Can be adjusted by the application.
- Does not have much effect on LPN power consumption.

###### Friend Node Settings

The following subsections describe the Friend node settings.

###### ReceiveWindow (heading level 7)

The ReceiveWindow setting has the following characteristics:

- The time that the LPN spends listening for a response.
- Duration: 1 to 255 ms
- Defined by the Friend node.
- The smaller the ReceiveWindow, the less time the LPN needs to stay on and listen for messages if no message is received.
- If there is a response, listening stops immediately.
- Usually set by the system, not the application.
- Different Friend node brands have different ReceiveWindow sizes.
- Silicon Labs products normally have a ReceiveWindow of 10 to 20 ms.
- If the maximum of 255 ms is used for the ReceiveWindow setting in Friend node, the LPN power consumption can be much larger, as much as 25 times larger if no message is received in time.
- The LPN can affect power consumption by selecting a Friend node with the smallest ReceiveWindow.
- ReceiveWindow has a significant effect on LPN power consumption if the connection is not perfect. However, with a good signal and connection, the size of the ReceiveWindow does not matter.

###### Power Consumption-Related Guidelines

- Proxy feature uses a lot of power so avoid using this frequently. See the measurements in [Low Power Node Friendship Established](03-measurements#low-power-node-friendship-established) and [Low Power Node Friendship Established with Proxy turned Off](03-measurements#low-power-node-friendship-established-with-proxy-turned-off).
- Transmit as few messages as possible as transmission always increases power consumption noticeably.
- Subscribe as few messages as possible.
- Do not change subscriptions often.
- Target fewer unicasts to the LPN.
- Be sure that the LPN receives a Friend node, and the friendship stays (that is, the signal is sufficient). An LPN that is just on the signal edge could make a friendship, then lose it, and make it again. Going back and forth like this is not very efficient because establishing every friendship consumes more power than being in a friendship.
- Do not restart the LPNs or Friend nodes often as the friendship has to be established again.
- When an LPN is establishing a friendship, do not blindly keep trying in a busy loop. Have a backoff policy if no acceptable Friend Offers are received.
- Acknowledged messages and especially segmented acknowledged messages for other nodes might be slow as the acknowledgements return via the Friend node. This also might have an effect in power consumption.
- Do not keep the node in unprovisioned state because it will remain awake and consume high current, accordingly.

For more detailed information about the LPN, Friend node, friendship, and timing parameters, see chapter 3.6.6 Friendship of the _Mesh Profile Bluetooth® Specification_ Revision v1.0.1.

##### Setup

1. Obtain two Bluetooth Wireless Starter Kits suitable for Bluetooth mesh.
2. Build and install the applications as described in [Build and Install the Applications](#build-and-install-the-applications).
3. Provision and control the operation using the Silicon Labs Bluetooth mesh mobile application.
4. See _AN969: Measuring Power Consumption on Wireless Gecko Devices_ for the power measurement setups and how to make the measurements. You can either use a separate DC Power Analyzer device or WSTK Advanced Energy Monitoring (AEM) with the Simplicity Studio Energy Profiler tool which is used in this application note.

###### Build and Install the Applications

To observe power consumption, first program the devices with a suitable test application. Follow these steps:

1. If you have not already done so, install Simplicity Studio and the Bluetooth Mesh SDK. The Bluetooth Mesh SDK includes several software examples to create Bluetooth mesh application projects. Follow the directions in _QSG176: Silicon Labs Bluetooth® Mesh SDK v2.x Quick-Start Guide_ to build and flash the example project to the device.
2. Program the Bluetooth Mesh - SoC Switch Low Power example onto the device with the WSTK. You can either use a ready-built demo (which includes the bootloader) or create a source code example, build it, and flash it onto the device.
3. Program the Bluetooth Mesh - SoC Light example onto another device. You can use a ready-built demo or create a source code example, build it, and flash it onto the device.  
   Remember when using the source code examples that there is also a bootloader. The easiest way to get this is to install the demo first and then your own application if you do not want to create a bootloader example, build it, and flash it.  
   If you create a source code example, the Low power node settings are in the Studio Component named Low Power Node (Bluetooth Mesh->Features->Low Power Node) as shown in the following figure.  
   ![Low Power Node](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image1.png)  
   You can also find these additional power consumption-related settings:  
   - During friendship: PollTimeout, Poll timeout in ms, LPN_POLL_TIMEOUT, default 5000 ms  
   - When finding friendship: Timeout in ms between retries to find a friend, LPN_FRIEND_FIND_TIMEOUT, default 2000 ms  
   There are also communication retry, Friend node, and initialization settings.  
   The Friend node source code has fewer settings. Those are located in the Studio Component named Bluetooth Mesh Stack (Bluetooth Mesh->Bluetooth Mesh Stack). The settings are memory consumption-related, not power consumption-related, such as Maximum number of Friendships allowed and others.
4. After flashing the example, both nodes should be in an unprovisioned state. If this is not the case (or you are not sure because there is no display or other issue), Silicon Labs recommends using Simplicity Commander to empty the flash before and then flash the demos and examples. For more information, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).
5. Now you are ready to start the power measurements with a separate DC Power Analyzer tool or using Simplicity Studio Energy Profiler. For more information, see _AN969: Measuring Power Consumption on Wireless Gecko Devices_.

##### Measurements

The following examples use this two-node Bluetooth mesh setup:

- Switch LPN: SLWSTK6023A EFR32xG21 Bluetooth Starter Kit with a main board and radio board running the Bluetooth Mesh - SoC Switch Low Power example. The example has LPN, Proxy (communication with Bluetooth LE devices like the mobile phone connection), and Relay features.
- Light node acting as a Friend node: SLWSTK6023A EFR32xG21 Bluetooth Starter Kit with a radio board running the Bluetooth Mesh – SoC Light example having Friend, Proxy, and Relay features. Also, some other Bluetooth mesh-compatible boards can be used instead of this. See _QSG176: Bluetooth® Mesh SDK v2.x Quick-Start Guide_ for a list of compatible products.

###### Unprovisioned Low Power Node

Because the LPN using the Bluetooth Mesh - SoC Switch Low Power application is still unprovisioned, the current measurement should look like the following figure. Be sure to measure the Bluetooth Mesh - SoC Switch Low Power node not the Bluetooth Mesh - SoC Light node.

![Current Profile for EFR32xG21 Series 2, unprovisioned](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image2.png)

The current measurement is on a steady high level (average 10.68 mA in the example) because the node is running and waiting for provisioning. When using some a device family other than the EFR32xG21, the current might be different.

###### Low Power Node Looking for a Friend Node

Open the Bluetooth mesh mobile application and provision the Bluetooth Mesh - SoC Low Power Switch node. Refer _QSG176: Bluetooth® Mesh SDK v2.x Quick-Start Guide_ for mobile application and provisioning instructions. At this point, provision only the Switch and do not change any Device Configuration settings at this time.

After provisioning, remember to return to the mobile application main level so that the Bluetooth connection with the mobile phone is closed. You should then see a current profile like the following figure.

![ Current Profile for EFR32xG21 Series 2, Looking for a Friend Node, with Proxy](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image3.png)

On average the current measurement is now much lower (3.94 mA in this example). The approximately one second lasting high current part occurs when the LPN is looking for a Friend node by sending Friend Request messages. The lower current part with spikes that takes approximately two seconds occurs when the device is sleeping (no Bluetooth mesh communication) and using the Proxy feature (Bluetooth LE device connectivity).

By changing the parameter LPN_FRIEND_FIND_TIMEOUT it is possible to affect the power consumption when the LPN is looking for a Friend node. The LPN_FRIEND_FIND_TIMEOUT default is two seconds in the example (the part with lower current levels and spikes).

###### Low Power Node Friendship Established

Provision Bluetooth Mesh - SoC Light (the Light node) also acting as a Friend node. Now the Switch LPN establishes a friendship with the Light node.

The power measurements look like the following figure.

![Current Profile for EFR32xG21 Series 2, Friendship established, with Proxy](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image4.png)

The current consumption is now only 736 µA on average which is much less than the original over 10 mA measurement.

###### Low Power Node Friendship Established with Proxy turned Off

Turn the Proxy off: Turn off the Bluetooth Mesh - SoC Light node to make sure the device is connecting directly to the Bluetooth Mesh - SoC Low Power Switch node. Use the mobile application to connect the network, select the Bluetooth Mesh - SoC Low Power Switch node, refresh the Proxy feature, and then disable it. Also remember to return to the mobile application main level so the Bluetooth connection with the mobile phone is closed. Now turn the Bluetooth Mesh - SoC Light node back on to establish friendship again. The new measurements should look like the following figure.

![Current Profile for EFR32xG21 Series 2, Friendship established, no Proxy](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image5.png)

The current measurement is now only 6.6 µA. There is no communication visible as the poll period (PollTimeout) is so long that it is not detected. A longer—over 120-second measurement—appears in the following figure.

![Current Profile for EFR32xG21 Series 2, Friendship established, no Proxy, long PollTimeout](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image6.png)

There is now just a little less than 120 seconds between the Friend Polls and the current consumption is 8.5 µA on average. The communication current spike after every about 120 seconds looks like the following figure.

![Current Profile for EFR32xG21 Series 2, Friendship established, no Proxy, Friend Poll & Update](/btmesh-power-consumption-measurements/10.0.0/images/sld818-image7.png)

There are two parts in the communication:

- Sleeping time of 119.3 seconds using average current of 6.6 µA.
- Friend Poll: Friend Update that takes about 67 ms and average current is 3.22 mA.

These are a few other examples with different PollTimeout settings:

- 120 seconds PollTimeout: (120 s * 0.0066 mA + 0.067 s * 3.22 mA) / (120 s + 0.067 s) = 8.4 µA (received what was measured which is correct)
- 10 seconds PollTimeout: (10 s * 0.0066 mA + 0.067 s * 3.22 mA) / (10 s + 0.067 s) = 28 µA
- 1 seconds PollTimeout: (1 s * 0.0066 mA + 0.067 s * 3.22 mA) / (1 s + 0.067 s) = 210 µA = 0.21 mA

As Bluetooth mesh uses Bluetooth communication, refer to _AN1246: EFR32BG SoC Bluetooth® Smart Device Power Consumption Measurements_ for more detailed information.

#### Bluetooth Mesh Parameter Tuning for Network Optimization

##### Bluetooth Mesh Parameter Tuning for Network Optimization

> **NOTE: This section replaces _AN1316: Bluetooth Mesh Parameter Tuning for Network Optimization_. Further updates to this application note will be provided here**.

This document describes in detail how the Bluetooth mesh topology can influence network operation. Additionally, tips are provided on how to tune your network and its nodes to achieve best performance.

For more detail on how to monitor Bluetooth Low Energy and Mesh data traffic, refer to [Using the Network Analyzer with Bluetooth Low Energy and Mesh](/btmesh/{build-docspace-version}/network-analyzer-with-ble-btmesh). The present document is based on Bluetooth Mesh profile and model 1.0.1 specifications.

As a prerequisite, it is assumed that you are already familiar with Bluetooth Low Energy concepts such as GATT protocol, connections, advertising, broadcasting, and scanning. It is also assumed that you are familiar with the Bluetooth mesh terminology and are accustomed to the meaning of terms “node” and “provisioner”. For more detail, please refer to the Bluetooth Mesh profile specification 1.0.1.

###### Key Points

- Bluetooth mesh networking
- Network topology
- Networking parameters
- Advertising bearer versus GATT bearer

##### Introduction

This section gives an overview of Bluetooth mesh topology concepts.

###### Bluetooth Mesh Topology

Although the Bluetooth mesh technology uses Bluetooth Low Energy (Bluetooth LE) for message transport, when it comes to data flow, there are significant differences.

Bluetooth mesh does not use a point-to-point communication scheme. Rather, it relies on advertising packets being sent and relayed through the mesh network. A node can identify if a network packet is addressed to itself via its destination mesh address (unicast, group or virtual address) which is different from a regular public or private Bluetooth LE address. For more information, please refer to the Bluetooth mesh profile specification.

The following example illustrates a Bluetooth mesh network with the various roles and bearers (taken from the Bluetooth mesh profile specification 1.0.1):

![image1](/btmesh-network-optimization/0.1/images/sld819-image1.png)

As opposed to Bluetooth LE, Bluetooth mesh nodes have a “many-to-many” relationship with mesh devices within their radio range. In the case where two nodes are not within radio range, the data is relayed by nodes supporting that feature from the emitter to the receiver.

Additionally, nodes in a network have different energy consumption requirements. This impacts the network design, as a node taking part would constantly need to scan for incoming advertising packets and transmit, if necessary, which requires a relatively large amount of power. To mitigate that, nodes can be put to sleep and rely on other nodes within radio range and with fewer power constraints, to store the messages addressed to them.

Finally, Bluetooth mesh relies on the advertising/scanning state of the Bluetooth LE Link Layer. As a result, no low-level collision control exists. If a device does not support the advertising bearer, the GATT bearer can be used (relying on connection). This allows a device to communicate with nodes of a mesh network that support both bearers and that can operate as a proxy between the advertising and GATT bearer.

When building a Bluetooth mesh network, it is important to consider aspects such as these to ensure maximum efficiency.

This document lays out the basic principles and discusses the main parameters that influence network operation.

##### Bluetooth Mesh Node Principles and Optimization

This section focuses on the network operation from the node perspective.

###### Bluetooth Mesh Stack Layers

The current Bluetooth mesh stack (Bluetooth Mesh profile/model spec 1.0.1) is built on top of the Bluetooth Low Energy core specification. The following image illustrates the layers composing the Bluetooth mesh stack running on each node:

![image2](/btmesh-network-optimization/0.1/images/sld819-image2.png)

The Bluetooth mesh specification defines two bearers over which mesh may be transported:

- An advertising bearer, using advertising packets as defined in the Bluetooth Low Energy core specification with dedicated mesh AD types.
- A GATT bearer, which allows devices not supporting the advertising bearer to participate to a mesh network. The GATT bearer can transmit and receive network layer packets, encapsulated in what is called the “Proxy protocol”, through regular Bluetooth Low Energy connections.

The network layer defines the Network packet data unit (PDU) format that allows data to be transported by the mesh bearers. It decrypts, authenticates, and forwards packets upstream, to the Lower Transport Layer, and downstream, to the bearer layer. For more detail on the Network layer and the Networks PDUs, see [Bluetooth Mesh networking principles](03-bluetooth-mesh-networking-principles).

The Lower Transport Layer and Upper Transport Layer handle Transport PDUs. The Lower Transport Layer implements message segmentation and reassembly of Transport PDUs. Also at that level application keys associated with the message are identified. In the case of a friend node, a list of messages is stored for each associated low power (LP) node at this level. For more detail, see [Friend](#friend).

The Upper Transport Layer implements message integrity checking and encryption/decryption.

Finally, the Access Layer defines the format of application data such as models. It also handles model publishing and subscribing. The access layer mainly handles application data and therefore will not be described extensively in this document, as it focuses on mesh networking operation.

###### Node Features

Node functionality is determined by the features that they support. Each node can support one or several of the features described in the Introduction, that is:

- Relay node
- Proxy node
- Friend node
- Low Power node

This section exposes the meaning of each feature with some practical recommendations.

###### Relay (heading level 7)

Bluetooth mesh expands the range of the network by relaying messages. Any Bluetooth mesh device supporting the feature may be configured to act as a relay, but it is not mandatory for a network to have relay nodes (in case of small networks for example).

This relaying is undirected and is referred to as “message flooding”. It ensures a high probability of message delivery, without requiring any information on the network topology.

The Bluetooth mesh profile specification does not provide any routing mechanisms. As a result, all messages are forwarded by all relays until a counter-based time-to-live (TTL) mechanism reaches zero (more detail on TTL can be found in the dedicated section in the Bluetooth mesh profile specification). To avoid messages being forwarded by the same relays over and over, all Bluetooth mesh devices maintain a message cache, used for filtering out packets that the device has already handled.

**Recommendations**

The flooding-based approach to message relaying can cause a lot of redundant traffic on air, which may impact the throughput and reliability of the network. Therefore, it is highly recommended to limit the number of relays in a network to restrict this effect.

The number of relay-enabled devices in the network is a trade-off between message redundancy and reliability. It should be tuned according to:

- Network size (number of nodes)
- Traffic volume
- Requirements for reliability and responsiveness

###### Proxy (heading level 7)

To enable support for legacy Bluetooth LE devices that do not support receiving mesh network packets, Bluetooth mesh defines a separate protocol for tunneling mesh messages over the Bluetooth LE GATT protocol. For this purpose, the Bluetooth mesh profile specification defines a GATT bearer and the corresponding GATT Proxy Protocol. This protocol allows legacy Bluetooth LE devices to participate in the Bluetooth mesh network by establishing a GATT connection to a Bluetooth mesh device that has the proxy feature enabled.

The legacy device gets assigned an address and the necessary keys to become a full-fledged member of the network. The device receives the security credentials through the regular provisioning procedure or through some out-of-band mechanism.

**Recommendations**

Unprovisioned devices should support both the advertising bearer and the GATT bearer.

A provisioner should support at least one of the bearers. It is highly recommended that it support the advertising bearer.

For a provisioner, when provisioning over the GATT bearer (PB-GATT) it is highly recommended that the connection interval for the connection between a Provisioner and device be between 250 and 1000 milliseconds (implementation-specific). This enables very low power operation for the device and allows the device to calculate the Diffie-Hellman shared secret without wasting significant energy to maintain an idle link.

###### Friend (heading level 7)

To enable broadcast-based communication, the devices must continuously keep their radio in listening mode. This causes significantly higher power consumption than in a typical Bluetooth LE device.

To enable low power devices to take part in the mesh network, Bluetooth mesh contains a friendship feature. This protocol lets low power devices establish a relationship with a regular Bluetooth mesh device, which will then cache and forward messages to the low power device at regular intervals. This saves the low power device from having to stay on to listen for incoming messages.

**Recommendations**

Limit the number of friend relationship a node can have, as this has direct effects on the message queue the friend node needs to maintain for the low power nodes it is associated with. If the friend queue is full and a new message needs to be stored, the oldest entries of the friend message queue will be discarded to make room for the new message.

###### Low Power (LP) Node (heading level 7)

Some types of nodes have limited power resources, such as coin cell batteries. Those battery-powered devices need to conserve energy as much as possible. The low power node feature allows nodes that support it to establish an association with other nodes within radio range, to store mesh packets for them while they are on energy saving mode (deep sleep).

The devices at the other end of that relationship are called friend nodes. An LP node can only have one friend node, but a friend node can have a friend relationship with several LP nodes.

Furthermore, devices of this type may be predominantly concerned with sending messages but still have a need to occasionally receive messages.

**Recommendations**

Low power edge nodes that mostly sends requests, such as light switches, do not need to act as a relay. Adjust the time-to-live counter (TTL) setting based on location within radio range of devices it controls.

###### Node Message Handling

This section lays out the mechanisms put in place by the Bluetooth mesh stack for message handling on a node.

###### Network Interfaces and Filtering (heading level 7)

On each node, the network layer supports sending and receiving messages via multiple bearers. As a result, multiple instances of a bearer might be present. Each of these instances interacts with the mesh network via a network interface.

For example, a node may have two network interfaces: one for Network PDU handling via the advertising bearer and another one for Network PDU handling via a GATT bearer. This is illustrated in the following figure.

![image3](/btmesh-network-optimization/0.1/images/sld819-image3.png)

The interface output filter of each interface makes sure only messages passing the defined rules are passed to the network layer and bearers. The output filter of the interface connected to advertising or GATT bearers must drop all messages with TTL values set to 1.

The following routines can be used to set up the input/output filtering rules for GATT bearers. For more information, see the Silicon Labs Bluetooth mesh API documentation:

```c
- `sl_btmesh_proxy_allow()`
- `sl_btmesh_proxy_deny()`
- `sl_btmesh_proxy_set_filter_type()`
```

###### Network Message Cache (heading level 7)

To reduce unnecessary security checks and excessive relaying, nodes include a network message cache of all recently seen Network PDUs. If a Network PDU is received that is already in the network message cache, then the Network PDU is not processed (that is, immediately discarded). If a Network PDU is received and that Network PDU is not in the message cache, then the Network PDU is processed (for example, checked against network security and relayed) and, if it is a valid Network PDU, it is stored in the network message cache.

It is not mandatory, nor is it necessary, to store entire Network PDUs in the network cache. For instance, the network cache as implemented in the Silicon Labs Bluetooth mesh stack consists of a ring buffer of cache entries stored internally by the stack in RAM. For resource optimization purposes, only some of the Network PDU information is stored in cache, rather than the encapsulated Transport PDU.

A cache entry, in the Silicon Labs Bluetooth mesh stack, is structured as:

- Network key index (2 bytes)
- IV index and SEQ number (4 bytes)
- Mesh source address (2 bytes)

That is 8 bytes in total. The total memory space allocated to the network cache is determined by the **Network Cache size** parameter in the **Bluetooth Mesh Stack** component. By default, this is set to 16 cache entries, or 128 bytes.

![image4](/btmesh-network-optimization/0.1/images/sld819-image4.png)

Typically, it is good practice to set a large cache size for all nodes that support relaying and have it enabled.

###### Bluetooth Mesh Stack Component

As mentioned earlier, the Bluetooth mesh stack on each node can be configured to optimize network operation. This is done through the **Bluetooth Mesh Stack** component. Open the project by double-clicking the .slcp file, go to the SOFTWARE COMPONENTS tab, and search for and select the **Bluetooth Mesh Stack** component. Click **Configure**.

![image5](/btmesh-network-optimization/0.1/images/sld819-image5.png)

The Component Editor opens.

![image6](/btmesh-network-optimization/0.1/images/sld819-image6.png)

Among the configurable parameters, some are especially relevant for network efficiency optimization. A list of parameters that should be considered follows. For an exhaustive description of all the parameters, refer to [UG472: Bluetooth Mesh Stack and Configurator User’s Guide for SDK v2.x](https://www.silabs.com/documents/public/user-guides/ug472-bluetooth-mesh-v2x-node-configuration-users-guide.pdf).

**Network Cache size**

For more detail on this, see [Network Message Cache](#network-message-cache). It is good practice to increase the size of the cache on relay nodes. The number entered is the number of cache entries

**Replay Protection List Size**

For more detail on the replay protection list size see section [Bluetooth Mesh Networking Principles](03-bluetooth-mesh-networking-principles). The number entered is the number of replay protection list entries.

**Maximum Number of Segments Allowed for Transmitted/Received Packets**

At the transport level, messages can be segmented, meaning that large length messages can be sliced into smaller entities called segments and sent/received in bursts (or batches).

In the case of a receiver, _Maximum number segments allowed for received packets_ determines the number of segments the node’s stack receive task can process in one burst. To maximize throughput, it is good practice to increase the value of that parameter.

In the case of a transmitter, _Maximum number segments allowed for transmitted packets_ determines the number of segments the node’s stack transmit task can process in one burst. To maximize throughput, it is good practice to increase the value of that parameter.

The maximum number of segments for both receiving and transmitting is 32, corresponding to the maximum length of the access layer PDUs payload.

_Do not interfere significantly with segmentation as this could have negative consequences. The use of unsegmented messages is always preferred._

For more detail on segmentation, see the Bluetooth mesh profile specification.

**Maximum Number of Friendship Allowed**

This parameter indicates, on a node that supports the Friend feature, the maximum number of friendships that can be established. This should be adjusted on each node.

**Maximum Size of Total Friend Cache**

On a node that supports the Friend feature, this parameter indicates the amount of RAM dedicated for the LP node message queues. This is does not have a direct effect on network operation but is strongly correlated to the following parameter _Maximum size of Cache for a single Friendship_.

**Maximum Size of Cache for a Single Friendship**

On a node that supports the Friend feature, this parameter indicates the length of the logical structure used by the stack to store LP node messages. The length of the message queue should be adjusted to the LP nodes’ poll time, which is the duration they periodically spend in deep sleep.

**Maximum Number of Connections to Reserve for GATT Proxies**

On a node that supports the Proxy feature, this indicates maximum number of GATT bearer-based connections that can be made. This can be set to 0 when only the advertising bearer is used.

###### Radio Range

One parameter to take in account when setting up a mesh network is the reach of each node. Nodes that do not have a strong power constraint can increase the TX output power to enhance their reach. As a result, on such nodes, setting transmit power to the maximum legal value is recommended. This is, of course, not the case for LP nodes. In case of relay overlap, it is good practice to increase radio range.

It is recommended to keep the node’s advertising rate as low as possible. Devices will usually have some advertising configured, including unprovisioned device/proxy advertisements and other miscellaneous advertising. As the number of nodes in the network increases, the rate of these advertisements can have a very detrimental effect on provisioning/configuration performance and network performance. The rate of these advertisements must be carefully selected by considering the expected size of the network and the application requirements (that is,. how quickly a mobile app needs to connect to a node, and so on).

##### Bluetooth Mesh Networking Principles

This section describes Bluetooth mesh networking and the parameters influencing good operation. The information presented in this section focus on the following principles:

- **Scalability**: Adding and removing a node from a network should be a seamless procedure.
- **Robustness**: All information needed by a node for normal operation should reach it.
- **Efficiency**: Irrelevant radio communication should be reduced as much as possible to avoid collisions and unnecessary power consumption.
- **Security**: No weakness should be introduced in the network due to incorrect parameter settings.

###### Bluetooth Mesh Network Layer

The following description defines the Network PDU format:

![image7](/btmesh-network-optimization/0.1/images/sld819-image7.png)

The following table describes the fields:

|Field Name|Bits|Description|
|---|---|---|
|IVI|1|Least significant bit of the IV index (see the Bluetooth mesh profile specification for more detail)|
|NID|7|Value derived from the network key used to identify the internal security keys used to secure this Network PDU (see the Bluetooth mesh profile specification for more detail)|
|CTL (1)|1|Network control|
|TTL (1)|7|Time to live|
|SEQ (1)|24|Sequence number|
|SRC (1)|16|Source address|
|DST (2)|16|Destination address|
|TransportPDU (2)|8 to 128|Transport protocol data unit|
|NetMIC|32 to 64|Message integrity check for network|

(1) Fields are obfuscated, meaning that they are combined with the result of a single encryption function designed to prevent a passive eavesdropping.

(2) Fields are encrypted and authenticated. Authentication and encryption in this context is equivalent to Bluetooth LE terminology. For more detail on Network PDU encryption and obfuscation, refer to the Bluetooth mesh profile specification.

In the Network PDUs, not all fields are relevant for network operation optimization. The following parameters are the ones that should be considered first.

###### IV Index (heading level 7)

The IV index is a 32-bit value known and shared by all nodes of a network. It is used for authentication and encryption at various levels in the stack (network, transport and application layers). For more information, see [IV Update in a Bluetooth Mesh Network](/btmesh/{build-docspace-version}/btmesh-iv-update).

###### Time to Live (TTL) (heading level 7)

Every device acting as a relay will decrement the time-to-live (TTL) value in received messages and forward them if the TTL equals two or higher.

The following values are defined for the time-to-live counter:

- 0: A Network PDU has never been relayed and will not be relayed.
- 1: The Network PDU has been relayed but will not be relayed. All Network PDUs with this TTL value will be dropped by the node’s network output filter.
- 2 to 126: The Network PDU has been relayed and can be relayed.
- 127: The Network PDU has not been relayed and will not be relayed.

The default TTL value of a node can be accessed and modified in the application code by any node supporting the configuration client model (typically the provisioner, but not necessarily):

- `sl_btmesh_config_client_get_default_ttl(net_key_index,node_address,pointer_to_handle)`
- `sl_btmesh_config_client_set_default_ttl(net_key_index,node_address,default_ttl_value,pointer_to_handle)`

This can also be done on model basis:

- `sl_btmesh_config_client_get_model_pub() /\* See BT Mesh API documentation for the arguments \*/`
- `sl_btmesh_config_client_set_model_pub() /\* See BT Mesh API documentation for the arguments \*/`

Note that the test API in the Silicon labs Bluetooth mesh API also allows modification of the TTL value for debugging purposes.

Adjust the default TTL value of a node carefully, depending on the supported features.

Typically, publishing model TTL value should be tailored to the application’s need. As a trivial example, a lightness client model controlling a room within direct radio range should be set to publish with TTL=0. A sensor that sends data to a collector node somewhere in the network should publish with a TTL value big enough to just reach the collector across a chain of relays with and addition of 1 or 2 hops for relay redundancy.

Default TTL should be set so that Network PDUs can reach the Provisioner. If the provisioner is a mobile device accessing the network via a proxy node, the default TTL needs to be set so that the node reaches the whole network.

###### SEQ (heading level 7)

Each Network PDU increments a sequence counter (SEQ) to protect the receiver node from replay attacks. It is a 24-bit value that can be combined with the source address and IV index of a network to identify messages individually. This value is part of the network cache and replay protection list entries in the Silicon Labs Bluetooth mesh stack.

###### SRC and DST (heading level 7)

The SRC and DST fields are 16-bit values identifying the source and destination of the Network PDU. The SRC field is a unicast address, while the DST field may be a unicast, group, or virtual address.

Both fields are untouched when the PDU is relayed.

###### Message Replay Protection

A malicious device can passively receive all traffic whether encrypted or not, and then replay one or a sequence of messages to take advantage of the infrastructure. In common security terms, this is called a replay attack.

Since the originating element has encrypted and authenticated the message using the correct keys, the receiver node has no means to determine whether it is under a replay attack.

To increase protection against replay attacks, each element increases the sequence number (SEQ) for each new message that it sends. If a valid message has been received from an originating element with a specific sequence number, any future messages from the same originating element that contain numerically lower or equal sequence numbers than the last valid sequence number are very likely replayed messages and should be discarded. Therefore, messages are delivered to the access layer in sequence number order.

To guard against malicious devices replaying previous messages, every device keeps a running sequence number, which is used for outbound messages. Each Bluetooth mesh message is sent with a unique pair of sequence number and source address. When receiving a message, the receiving device stores the sequence number and makes sure that it is more recent than the last sequence number it received from the same source address. This is handled by the replay protection list described In the following section.

###### Replay Protection List (heading level 7)

A replay protection list entry in the Silicon Labs Bluetooth mesh stack, is structured as:

- Source address (2 bytes)
- IV index and SEQ number (7 bytes)
- IV index and SEQ number authenticated (7 bytes)
- Saved flag (1 byte)

That totals 17 bytes. The total memory space allocated to the network replay protection list (RPL) is determined by the **Replay Protection List size** parameter in the **Bluetooth Mesh stack** configuration component. The default setting for the replay protection list is 32.

The RPL size sets the upper limit for the number of devices (or more accurately, the number of elements) this device can communicate with. When the RPL cannot be amended with an entry corresponding to a new received message, because the RPL is full, any such message will be dropped

![image8](/btmesh-network-optimization/0.1/images/sld819-image8.png)

The composition data page 0, part of what is referred to as Device Composition Data (DCD) in the Silicon Labs Bluetooth mesh stack, contains a field indicating the minimum number of entries in a node replay protection list. The following table illustrate the content:

|Field|Size (bytes)|Description|
|---|---|---|
|CID|2|16-bit company identifier.|
|PID|2|16-bit vendor-assigned product identifier.|
|VID|2|16-bit vendor-assigned product version identifier.|
|CRPL|2|16-bit value representing the minimum number of replay protection list entries in a device.|
|Features|2|Contains a bit field indicating the supported features of the device.|
|Elements|variable|A sequence of elements|

The CRPL value corresponds to the value set in the **Bluetooth Mesh Stack** component.

Silicon Labs’ stack allows you to save the replay protection list in non-volatile memory (NVM) to ensure replay protection over power cycles. The following routines can be used:

- `sl_btmesh_node_save_replay_protection_list()`
- `sl_btmesh_node_get_replay_protection_list_status(uint16_t \* total_entries, uint16_t \* unsaved_entries)`

The replay protection list should be saved regularly, especially after a topology change or an IV index update, for example. When a node is removed or added in the network. It is good practice to save the RPL before the devices power off.

The publish rate of a model on each node (set by the configuration client) is also a critical parameter. If the publish rate is too high, it can drastically increase the traffic on the network and cause sluggish performance.

For more information, see the Silicon Labs Bluetooth mesh API documentation.

###### Relays

Relaying in Bluetooth mesh networks is important, but often misuse of that feature leads to problems. This section clarifies the functionality and suggests ways to improve robustness and scalability of your network.

As mentioned earlier in this document, message flooding is the mechanism put in place to ensure two nodes unable to reach each other directly by radio, can still communicate. This means that messages coming from the origin node will be received by relay nodes within radio range and then retransmitted to other relay nodes until the information finally reaches its original destination node.

This is a very effective and simple way to solve the network scalability issue but comes with some drawbacks:

- If too many relay nodes are enabled in the network, the redundant data traffic may increase in an uncontrollable way.
- Relay nodes must constantly listen for incoming advertising packets and retransmit them, which is very costly in term of power.
- A lot more information travels over the air, potentially making attacks easier.

As a result, a network designer must take caution when using the relay feature and limit the number of relay nodes to what is necessary.

For example:

- Devices powered by a building’s electric system, such as light bulbs, are not power-constrained and most likely will be active on the mesh network. As a result, it makes sense for these nodes to support the relay feature. The network cache and replay protection list size should be adjusted depending on how many nodes surrounds it. Additionally, the TTL value should be set based on the hop count needed to reach its configuration device.
- An LP node would typically never need to support the relay feature, as it is incompatible with its power constraints.

###### Network Repetitions and Repetition Delays (heading level 7)

Relays retransmit network PDUs. The configuration client (provisioner, configurator) determines whether a device behaves as a relay along with the number of retransmissions and the delay between retransmissions. The Silicon Labs configuration client commands for these are as follows:

- `sl_btmesh_config_client_get_relay(net_key_index,node_address)`
- `sl_btmesh_config_client_set_relay(net_key_index,node_address,value,retransmit_count,retransmit_interval)`

The number of retransmission count is encoded on 3 bits and goes from 0b000, meaning the messages are retransmitted once, to 0b111, meaning one transmission and 7 retransmissions.

The time interval between retransmissions is encoded on a 5-bit value multiplied by a 10 ms time step. The value 0b00000 represent 10 ms: (0b00000 +1) * 10 ms. The value 0b11111 represent 320 ms: (0b11111 + 1) * 10 ms.

This is described in the Bluetooth mesh profile specification as relay state and should be carefully set to achieve maximum network performance. Additionally, a similar mechanism at the network layer level exists for non-relay nodes This is described in the Bluetooth mesh profile specification as network transmit state.

- `sl_btmesh_config_client_get_network_transmit(net_key_index,node_address,pointer_to_handle)`
- `sl_btmesh_config_client_set_network_transmit(net_key_index,node_address,transmit_count,transmit_interval,pointer_to_handle)`

Those routines allow a configuring node that is supporting the configuration client model to set the network transmit state. For more information, see the Silicon Labs Bluetooth mesh API documentation.

Only in areas with very few relays should the network/relay repetitions be enabled.

#### Bluetooth Mesh Interoperability Testing Report

##### Bluetooth Mesh Interoperability Testing Report

> **NOTE: This section replaces _AN1308: Bluetooth Mesh Interoperability Testing Report_. Further updates to this application note will be provided here**.

This document includes the results of the interoperability testing of Silicon Labs’ ICs and Bluetooth Mesh stack with Android and iOS smart phones. The document also has details of the test setup, test cases and extension of the results based on the Bluetooth qualification of the smart phones.

###### Key Points

- Proxy, Relay, Friend and Low Power Node features tested
- Provisioning, Control and Network Reconfiguration tested
- EFR32xG13, EFR32xG21 and EFR32xG22 tested
- Tested against mobile devices with both Android and iOS across various OS versions

##### Test Setup

Tests were performed using Silicon Labs evaluation hardware. Each tested product family was running functionally-equivalent embedded test software. Interoperability against mobile phones running various versions of Android and iOS were tested corresponding to the test specifications listed below. The table below provides the details of the software and hardware that was used to execute the testing.

|Setup Component|Version / Board|
|---|---|
|Bluetooth Mesh SDK (embedded)|1.7.2|
|Bluetooth Mesh ADK (mobile)|2.3.2|
|ERF32xG13|BRD4104A Rev A02|
|ERF32xG21|BRD4181A Rev A01|
|EFR32xG22|BRD4182A Rev B04|
|Advertisement noise generators|ORICO USB to Bluetooth 4.0 Adapter|

##### Test Environment

The overall test environment is shown in the figure below. The table below describes roles for development boards used to support different roles in the mesh network. The mobile phone is used as the provisioner in all cases while the application on the mobile phone is used to control the mesh networks for various test cases that are described in subsequent sections. Each of the reference boards is connected to a PC, which runs the Simplicity Studio development tool. Because in a real-world mesh network a lot of devices might be in radio range, ten devices were used to generate advertising packets and emulate the presence of additional devices in the mesh network.

![Test Environment](/bt-mesh-interop-report/10.0.0/images/sld816-test-environment.png)

|Role|Device Used|
|---|---|
|Proxy|EFR32BG13|
|Relay|EFR32BG13|
|Friend|EFR32BG21|
|Low Power Node|EFR32BG22|
|Provisioner|Mobile Phone|

##### Test Case

The table below provides test case details. All test cases were executed using the setup described in section [Test Environment](02-test-environment) with multiple phones. Test cases are designed to test interoperability only between the mobile phones and Silicon Labs Bluetooth mesh implementation.

> **Note**:
> 
> 1. The UUIDs provided in the below table relate to the devices and roles described in [Test Environment](02-test-environment).
> 2. Devices transmitting advertizing packets were configured to have 60 ms advertising interval in all of the cases below.

|Test ID|Test Sub-Type|Configuration|Test Procedure|Pass Criteria|
|---|---|---|---|---|
|**Test Type - Provisioning**| | | | |
|1.1|PB-GATT Beaconing  Scan Mode Low Latency|Device: Set to beaconing with PB-GATT with specific UUID 0x000102030405060708090A0B0C0E0F.  Mobile: set Scan mode of mobile phone to SCAN_MODE_LOW_LATENCY.|Mobile starts scanning for device and checks if the device with correct UUID is found.|Pass: Found device with UUID = 0x000102030405060708090A0B0C0E0F within 1500ms  Max Retries: 3|
|1.2|PB-ADV, PB-GATT Beaconing  Scan Mode Low Latency|Device: Set to beaconing with both PB-ADV, PB-GATT with specific UUID 0x000102030405060708090A0B0C0E1F  Mobile: Set scan mode of mobile phone to SCAN_MODE_LOW_LATENCY.|Mobile starts scanning for device and checks if the device with correct UUID is found.|Pass: Found device with UUID = 0x000102030405060708090A0B0C0E1F in 2500ms  Max Retries: 3|
|1.3|PB-ADV, PB-GATT Beaconing  Scan Mode Low Power|Device: Set to beaconing with both PB-ADV, PB-GATT with specific UUID: 0x000102030405060708090A0B0C0E2F   Mobile: Set scan mode of mobile phone to SCAN_MODE_LOW_POWER.|Mobile starts scanning for device and checks if the device with correct UUID is found.|Pass: Found device with UUID = 0x000102030405060708090A0B0C0E2F in 1500ms for iOS and 4000ms for Android  Max Retries: 3|
|1.4|PB-ADV, PB-GATT Beaconing  Scan Mode Balanced|Device: Set to beaconing with both PB-ADV, PB-GATT with specific UUID : 0x000102030405060708090A0B0C0E3F  Mobile: Scan mode of mobile phone to SCAN_MODE_BALANCED.|Mobile starts scanning for device and checks if the device with correct UUID is found.|Pass: Found device with UUID = 0x000102030405060708090A0B0C0E3F in 1500ms for iOS and 5500ms for Android  Max Retries: 3|
|1.5|Authentication with no OOB|Device:   UUID: 0x000102030405060708090A0B0C0E0F    Set to No OOB    Mobile: Provisions with no OOB authentication mode.|Mobile starts provisioning with no OOB Mobile configures node:  Binds to "IOP Test Group"    Enables Proxy feature    Disables other features     Enables retransmission    Binds Appkey to model Generic OnOff Server model.|Pass: Provisioning successful in 10s  Max Retries: 3|
|1.6|Authentication with Static OOB|Device:   UUID: 0x000102030405060708090A0B0C0E1F    Fix static value of the authentication mode with value: 0112233445566778899aabbccddeeff (Static OOB)    Mobile: Use this value for authentication.|Mobile starts provisioning with static OOB using the same value as device is configured to.Mobile configures node:  Binds to "IOP Test Group"    Enables Relay feature    Disables other features,    Enables retransmission,     Binds Appkey to Generic OnOff Server model|Pass: Provisioning successful in 10s.  Max Retries: 3|
|1.7|Authentication with output OOB|Device   UUID: 0x000102030405060708090A0B0C0E2FAuthentication mode set to output OOB.    Mobile: Use output OOB for authentication.|Mobile starts provisioning with output OOB.Device generates random number and show 4 digits on LCDUser inputs those 4 digits that number on mobile for authenticationMobile configures node:  Binds to "IOP Test Group"    Enables Friend feature     Disables other features,    Enables retransmission,     Binds Appkey to Generic OnOff Server model|Pass: Provisioning successful in 30s  Max Retries: 3|
|1.8|Authentication with input OOB|Device   UUID: 0x000102030405060708090A0B0C0E3FAuthentication mode set to input OOB.|Mobile start provisioning with input OOB. Mobile generates and outputs a random number between 0 and 10.User input the random number by pressing PB0 button appropriate number of times. User press button PB1 for confirmation and continue provision process.  Mobile configures node:    Binds to "IOP Test Group"    Enables LPN feature     Disables other features    Enable retransmissions     Bind Appkey to Generic OnOff Server model|Pass: Provisioning successful in 30s  Max Retries: 3|
|**Test Type: Unicast and Multicast Control**| | | | |
|2.1|Unicast Control of Proxy Node with ACK|Device   UUID = 0x000102030405060708090A0B0C0E0F Provisioned as in Test ID 1.5.     Mobile: to use "with ACK" and parameters transition time = 0, delay time = 0.|- Mobile sends Set command with Ack to set state to ON addressing the Proxy node.|Pass: Received success for setting ON state.|
|2.2|Unicast Control of Proxy Node without ACK|Device:   UUID = 0x000102030405060708090A0B0C0E0F Provisioned as in Test ID 1.5.     Mobile: to use "without ACK" and parameters transition time = 0, delay time = 0. Use Get command to get status.|- Mobile sends Set command without Ack to set state to OFF addressing the Proxy node.  - Mobile sends Get command|Pass: Mobile receives success for setting OFF state in 180ms.  Max Retries: 3|
|2.3|Unicast Control of Relay Node with ACK|Device   UUID = 0x000102030405060708090A0B0C0E1F Provisioned as in Test ID 1.6.    Mobile: to use "with ACK" and parameters transition time = 0, delay time = 0|- Mobile sends Set command with Ack to set state to ON addressing the Relay node.|Pass: Received success for setting ON state.|
|2.4|Unicast Control of Relay Node without ACK|Device  UUID = 0x000102030405060708090A0B0C0E1F Provisioned as in Test ID 1.6.    Mobile: to use "without ACK" and parameters transition time = 0, delay time = 0. Use Get command to get status.|- Mobile sends Set command without Ack to set state to OFF addressing the Relay node.  - Mobile sends Get command|Pass: Mobile receives success for setting OFF state in 180ms.  Max Retries: 3|
|2.5|Unicast Control of Friend Node with ACK|Device   UUID = 0x000102030405060708090A0B0C0E2F    Provisioned as in Test ID 1.7.    Mobile: to use "with ACK" and parameters transition time = 0, delay time = 0.|- Mobile sends Set command with Ack to set state to ON addressing the Friend node.|Pass: Received success for setting ON state.|
|2.6|Unicast Control of Friend Node without ACK|Device   UUID = 0x000102030405060708090A0B0C0E2F Provisioned as in Test ID 1.7.    Mobile: to use "without ACK" and parameters transition time = 0, delay time = 0. Use Get command to get status.|- Mobile sends Set command without Ack to set state to OFF addressing the Friend node.  - Mobile sends Get command|Pass: Mobile receives success for setting OFF state in 180ms.  Max Retries: 3|
|2.7|Unicast Control of LPN Node with ACK|Device   UUID = 0x000102030405060708090A0B0C0E3F     Provisioned as in Test ID 1.8.    Mobile: to use "with ACK" and parameters transition time = 0, delay time = 0.|- Mobile sends Set command with Ack to set state to ON addressing the Low Power node.|Pass: Received success for setting ON state.|
|2.8|Unicast Control of LPN Node without ACK|Device   UUID = 0x000102030405060708090A0B0C0E3F     Provisioned as in Test ID 1.8.    Mobile: to use "without ACK" and parameters transition time = 0, delay time = 0. Use Get command to get status.|- Mobile sends Set command without Ack to set state to OFF addressing the Low Power node.  - Mobile sends Get command|Pass: Mobile receives success for setting OFF state in 180ms.  Max Retries: 3|
|2.9|Multicast Control of all 4 nodes|Devices:  Provisioned as per Test ID: 1.5 to 1.8    Mobile:    To use multicast with UNACK.|Mobile sends Set command with UNACK to set state of all the devices to ON addressing the "IOP Test Group"  Mobile sends Get command to read state of all the devices    Mobile sends Set command with UNACK to set state of devices to OFF addressing the "IOP Test Group"    Mobile sends Get command to read state of all the devices|Pass: Received success for setting ON / OFF state in 180ms   Max Retries: 5|
|**Test Type: Reconfiguration of the network**| | | | |
|3.1|Removing nodes from network|Devices:  Provisioned as in Test ID: 1.5 to 1.8 with respective UUIDS    Mobile:    To remove two nodes from the network|- Mobile removes LPN node with UUID: 0x000102030405060708090A0B0C0E3F- Mobile removes Friend node with UUID: 0x000102030405060708090A0B0C0E2F|Pass: There is no error and only 2 devices left in subnet.|
|3.2|Adding node to the network|Devices:  Proxy and Relay nodes provisioned as in Test ID 1.5 and 1.6    Mobile:    To add one node into the network.|- Mobile provisions device with UUID: 0x000102030405060708090A0B0C0E2F and as a normal node.- Mobile sends Set command with ack to set state of new node to ON- Mobile sends Set command with ack to set state of new node to OFF|Pass: The state of new node changes to ON then OFF  Max Retries: 3|
|3.3|Reconnection|Devices:  Proxy and Relay nodes provisioned as in Test ID 1.5 and 1.6    Normal node provisioned as in Test ID 3.2    Mobile:    To disconnect Proxy node and reconnect again.|-Mobile disconnects Proxy node from network-Mobile reconnects Proxy Node to the network|Pass: Reconnection is successful in 30s  Max Retries: 3|
|3.4|Remove all nodes from the network|Devices:  Proxy and Relay nodes provisioned as in Test ID 1.5 and 1.6    Normal node provisioned as in Test ID 3.2    Mobile:    To removes all nodes from the network|- Mobile removes all nodes from subnets- Mobile scans and found 4 un-provisioned devices|Pass: Found 4 un-provisioned devices with UUID: 0x000102030405060708090A0B0C0E0F,0x000102030405060708090A0B0C0E1F,0x000102030405060708090A0B0C0E2F,0x000102030405060708090A0B0C0E3F.|

##### Test Results

###### Tested Phones

This section provides a list of phones and relevant information against which all test cases were executed.

###### Summary of Tested Phones

The table below shows a high-level view of the phones tested across iOS and Android platforms. Note that the choice of the version numbers was made to provide a wide coverage. The earliest iOS version tested was 12.3, which was released in May 2019 and latest version is 14.2, which was released in October 2020. This included older devices like iPhone 5s which were released in 2013 upgraded to newer version of the OS. iPhone 11 pro was the latest of the iOS devices tested. Similarly, Android OS versions coverage ranged from 6.0 released in Oct 2015 to Android 10 released in Sep 2019, which at the time of testing was the latest of the generally available Android versions. The Android phones were sourced from various manufacturers across the world.

|OS Platform|Number of Phones|Version Coverage|
|---|---|---|
|iOS|17|OS Version: 12.3, 12.4.8, 13.3.1, 13.4.1, 13.5.1, 13.6.1, 13.7, 14.2|
|Android|72|OS Version: 6.0, 6.0.1, 7.0, 7.1.1, 8.0.0, 8.1.0, 9, 10  API Level: 23, 24, 25, 26, 27, 28, 29|

###### Details of Tested Phones

> **Notes**:
> 
> 1. Phone code is provided by the phone and extracted using specific APIs.
> 2. For Android, read the OS version as Android_SDK: <API_Level>_(<Android version>).

|Phone code|OS version|Test ID: 1.1 - 1.8|Test ID: 2.1-2.9|Test ID: 3.1-3.4|
|---|---|---|---|---|
|OnePlus_GM1925|Android_SDK:_28_(9)|Pass|Pass|Pass|
|OnePlus_IN2020|Android_SDK:_29_(10)|Pass|Pass|Pass|
|LGE_LGM_G600L|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-T295|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Google_Pixel|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Google_Pixel_2|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Google_Pixel_2_XL|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Google_Pixel_3|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Google_Pixel_3_XL|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Google_Pixel_XL|Android_SDK:_29_(10)|Pass|Pass|Pass|
|HUAWEI_COR_AL10|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|HUAWEI_DRA_AL00|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|HUAWEI_INE-LX2|Android_SDK:_28_(9)|Pass|Pass|Pass|
|HUAWEI_WAS_AL00|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|HUAWEI_MAR-LX2|Android_SDK:_28_(9)|Pass|Pass|Pass|
|HUAWEI_DUB_LX2|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|LGE_LG-H818|Android_SDK:_23_(6.0)|Pass|Pass|Pass|
|Xiaomi_Mi_10_Pro|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Nexus 5|Android_SDK:_23_(6.0.1)|Pass|Pass|Pass|
|OPPO_CPH1923|Android_SDK:_28_(9)|Pass|Pass|Pass|
|OPPO_CPH1912|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|OppO_CPH1905|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|OPPO_CPH1987|Android_SDK:_28_(9)|Pass|Pass|Pass|
|OPPO_CPH1917|Android_SDK:_29_(10)|Pass|Pass|Pass|
|HUAWEI_ELS_NX9|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Xiaomi_Redmi_5_Plus|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|Xiaomi_Redmi_6_Pro|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|Xiaomi_Redmi_7|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_Redmi_K20_Pro_Premium_Edition|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Xiaomi_Redmi_K30_Pro|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Xiaomi_Redmi_Note_8|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_Redmi_Note_5|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-G988B|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Samsung_SM-A105G|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Samsung_SM-A107F|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-A305F|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-A505F|Android_SDK:_28_(9)|Pass|Pass|Pass|
|SM-A515F|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Samsung_SM-A605G|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|Samsung_SM-A750GN|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|Samsung_SM-A705F|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-A805F|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-A920F|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Samsung_SM-J510FN|Android_SDK:_25_(7.1.1)|Pass|Pass|Pass|
|Samsung_SM-J710F|Android_SDK:_23_(6.0.1)|Pass|Pass|Pass|
|Samsung_SM-M205G|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-N950F|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Samsung_SM-N960F|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Samsung_SM-G975F|Android_SDK:_29_(10)|Pass|Pass|Pass|
|SM-G970F|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Samsung_SM-G930F|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|Samsung_SM-G935F|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|Samsung_SM-G950F|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|Samsung_SM-G955F|Android_SDK:_26_(8.0.0)|Pass|Pass|Pass|
|LGE_VS995|Android_SDK:_24_(7.0)|Pass|Pass|Pass|
|LGE_LG-H931|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_MI_9|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_Mi_9T|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Xiaomi_Mi_A2_Lite|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|Xiaomi_MI_6|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_MI_6X|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|Xiaomi_MI_8|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_Mi9_Pro_5G|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_MI_9_SE|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_MI_MAX_3|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|Xiaomi_MI_8_Lite|Android_SDK:_27_(8.1.0)|Pass|Pass|Pass|
|Xiaomi_Mi_A2|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_Mi_A3|Android_SDK:_29_(10)|Pass|Pass|Pass|
|Xiaomi_Mi_MIX_3_5G|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_MIX_2S|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Xiaomi_Redmi_7A|Android_SDK:_28_(9)|Pass|Pass|Pass|
|Redmi Note 7|Android_SDK:_29_(10)|Pass|Pass|Pass|
|iPhone 8 Plus|iOS 14.2|Pass|Pass|Pass|
|iPhone 5S|iOS 12.4.8|Pass|Pass|Pass|
|iPhone 6|iOS 12.4.8|Pass|Pass|Pass|
|iPhone X|IOS 13.6.1|Pass|Pass|Pass|
|iPhone 7 Plus|iOS 14.2|Pass|Pass|Pass|
|iPhone  Xs|IOS 13.5.1|Pass|Pass|Pass|
|iPhone 8|iOS 13.5.1|Pass|Pass|Pass|
|iPhone 6 Plus|iOS 12.4.8|Pass|Pass|Pass|
|iPhone 7|iOS 13.7|Pass|Pass|Pass|
|iPhone 6S|iOS 13.7|Pass|Pass|Pass|
|iPhone SE (2nd generation)|iOS 13.5.1|Pass|Pass|Pass|
|iPhone 11 Pro|iOS 14.2|Pass|Pass|Pass|
|iPad mini (5th generation)|iOS 13.4.1|Pass|Pass|Pass|
|iPad (7th generation)|iOS 13.4.1|Pass|Pass|Pass|
|iPad Air(3rd generation)|iOS 13.3.1|Pass|Pass|Pass|
|iPAD 11 Pro|iOS 13.5.1|Pass|Pass|Pass|
|iPhone XS Max|iOS 12.3|Pass|Pass|Pass|

###### Extended Set of Phones

![High Level System Architecture](/bt-mesh-interop-report/10.0.0/images/sld816-high-level-system-architecture.png)

While testing was done on a limited set of phones, the results can be extended to infer wider interoperability considering the overall system architecture and the Bluetooth qualification process.

Figure above provides a high-level architecture of the different components used in testing on the mobile phones and on the EFR32 SoCs. While it is evident that the respective components interact with each other, note that the Bluetooth mesh implementation is provided by Silicon Labs on both devices.

Bluetooth Controller and Bluetooth Host Stack components vary across different phones. The Bluetooth qualification process states that "If an organization produces more than one product that incorporates the same Bluetooth design, those additional products can be listed within the same qualification at no additional cost". See [https://www.bluetooth.com/develop-with-bluetooth/qualification-listing/](https://www.bluetooth.com/develop-with-bluetooth/qualification-listing/) for more information. This is used by several companies to qualify different models of the mobile phones using the same qualification ID when the Bluetooth design is the same. With reference to the figure above, the Bluetooth design refers to the combination of the Controller and the Host Stack.

Considering both the Bluetooth architecture and qualification process, it can be reasonably inferred that mobile phones, which share the same qualification ID with the phones used for testing will exhibit the same behavior and the same level of interoperability.

The table below provides a list of 2,242 devices arranged by qualification ID, which they share with one of the phones used for testing.

|Phone code|OS version|Qualification Reference|Models with Shared Qualification|
|---|---|---|---|
|OnePlus_GM1925|Android_SDK:_28_(9)|128467 - End Product|OnePlus 7 Pro, GM1915OnePlus 7 Pro, GM1913OnePlus 7 Pro, GM1917OnePlus 7 Pro 5G, GM1920OnePlus 7 Pro 5G, GM1925OnePlus 7 Pro, GM1911OnePlus 7 Pro, GM1910OnePlus 7, GM1900OnePlus 7, GM1903OnePlus 7, GM1901|
|OnePlus_IN2020|Android_SDK:_29_(10)|144662 - End Product|Smart Phone, IN2017OnePlus 8 5G UW, IN2019OnePlus 8, IN2015OnePlus 8, IN2013OnePlus 8, IN2010OnePlus 8, IN2011OnePlus 8 Pro, IN2020OnePlus 8 Pro, IN2021OnePlus 8 Pro, IN2023OnePlus 8 Pro, IN2025|
|LGE_LGM_G600L|Android_SDK:_28_(9)|92094 - End Product|LG Mobile Phone, LGM-G600LLG Mobile Phone, LGM-G600KLG Mobile Phone, LGM-G600SLG Mobile Phone, LGM-G600LRLG Mobile Phone, LGM-G600SRLG Mobile Phone, LGM-G600KRLG Mobile Phone, LGM-G600LPLG Mobile Phone, LGM-G600SPLG Mobile Phone, LGM-G600KP|
|Samsung_SM-T295|Android_SDK:_28_(9)|134106 - End Product|Galaxy Tab A, SM-T295Galaxy Tab A, SM-T295NGalaxy Tab A, SM-T297Galaxy Tab A, SM-T295CGalaxy Tab A, SM-T290|
|Google_Pixel|Android_SDK:_28_(9)|85767 - End Product|Pixel, PixelPixel XL, Pixel XL|
|Google_Pixel_2|Android_SDK:_29_(10)|98278 - End Product|Pixel 2, G011A|
|Google_Pixel_2_XL|Android_SDK:_28_(9)|98638 - End Product|LG Mobile Phone, G011C|
|Google_Pixel_3|Android_SDK:_29_(10)|111802 - Controller Subsystem115459 - Host Subsystem|Pixel 3, G013APixel 3, G013BPixel 3 XL, G013CPixel 3 XL, G013D|
|Google_Pixel_3_XL|Android_SDK:_29_(10)|122387 - Profile Subsystem111802 - Controller Subsystem115459 - Host Subsystem|Pixel 3a XL, G020A G020B G020C G020DPixel 3a, G020E G020F G020G G020H|
|Google_Pixel_XL|Android_SDK:_29_(10)|85767 - End Product|Pixel, PixelPixel XL, Pixel XL|
|HUAWEI_COR_AL10|Android_SDK:_27_(8.1.0)|101927 - Host Subsystem86634 - Controller Subsystem107026 - Profile Subsystem|COL-AL10, COL-AL10COL-AL00, COL-AL00COL-TL10, COL-TL10COL-TL00, COL-TL00COL-L29, COL-L29Smart Phone,Honor, COR-TL00Smart Phone,Honor, COR-AL00Smart Phone,Honor, COR-AL10Smart Phone,Honor, COR-L29Smart Phone, HUAWEI, PAR-AL00Smart Phone, HUAWEI, PAR-TL00Smart Phone, HUAWEI, PAR-LX1Smart Phone, HUAWEI, PAR-LX9Smart Phone, HUAWEI, PAR-LX1MSmart Phone, HUAWEI, PAR-TL20Smart Phone, HUAWEI, INE-AL00Smart Phone, HUAWEI, INE-TL00Smart Phone, HUAWEI, SNE-AL00Smart Phone, HUAWEI, INE-LX1Smart Phone, HUAWEI, INE-LX2Smart Phone, HUAWEI, SNE-LX1Smart Phone, HUAWEI, SNE-LX2Smart Phone, HUAWEI, SNE-LX3Smart Phone, HUAWEI, JKM-LX1Smart Phone, HUAWEI, JKM-LX2Smart Phone, HUAWEI, JKM-LX3Smart Phone, HUAWEI, JKM-TL00Smart Phone, HUAWEI, JKM-AL00Smart Phone, HUAWEI, JKM-AL00aSmart Phone, HUAWEI, JKM-AL00bSmart Phone, HONOR, JSN-AL00Smart Phone, HONOR, JSN-AL00aSmart Phone, HONOR, JSN-TL00Smart Phone, HONOR, JSN-L21Smart Phone, HONOR, JSN-L22Smart Phone, HONOR, JSN-L42Smart Phone, HONOR, JSN-L23Smart Phone, HUAWEI, INE-LX2rSmart Phone, HUAWEI, INE-LX1rSmart Phone, HONOR, POT-LX1AFSmart Phone, HONOR, POT-LX1Smart Phone, HONOR, POT-LX3Smart Phone, HONOR, POT-LX2JSmart Phone, HUAWEI, VCE-TL00Smart Phone, HUAWEI, VCE-AL00Smart Phone, HONOR, POT-L72JSmart Phone, HONOR, POT-L62JSmart Phone, HONOR, HRY-AL00Smart Phone, HONOR, HRY-AL00aSmart Phone, HONOR, HRY-TL00Smart Phone, HONOR, HRY-LX1Smart Phone, HONOR, HRY-LX1MEBSmart Phone, HONOR, HRY-LX2Smart Phone, HUAWEI, POT-LX1Smart Phone, HUAWEI, POT-LX1AFSmart Phone, HUAWEI, POT-LX3Smart Phone, HUAWEI, POT-LX2JSmart Phone, HUAWEI, POT-L62JSmart Phone, HUAWEI, POT-L72JSmart Phone, HUAWEI, VCE-L22Smart Phone, HUAWEI, POT-TL00aSmart Phone, HUAWEI, POT-AL00Smart Phone, HUAWEI, POT-AL00aSmart Phone, HUAWEI, POT-LX1TSmart Phone, HUAWEI, MAR-TL00Smart Phone, HUAWEI, MAR-AL00Smart Phone, HUAWEI, MAR-LX2Smart Phone, HUAWEI, MAR-LX1ASmart Phone, HUAWEI, MAR-LX1MSmart Phone, HUAWEI, MAR-LX3ASmart Phone, HUAWEI, MAR-LX2JSmart Phone, HONOR, HRY-AL00TaSmart Phone, HONOR, HRY-AL00TSmart Phone, HONOR, HRY-TL00TSmart Phone, HONOR, HRY-LX1TSmart Phone, HONOR, ASK-AL00xSmart Phone, HONOR, ASK-AL00axSmart Phone, HONOR, ASK-TL00xSmart Phone, HONOR, ASK-TL00axSmart Phone, HONOR, ASK-LX1xSmart Phone, HONOR, ASK-LX2xSmart Phone, HONOR, ASK-LX2xSmart Phone, HUAWEI, ATR-AL00xSmart Phone, HUAWEI, ATR-AL00axSmart Phone, HUAWEI, ATR-TL00xSmart Phone, HUAWEI, ATR-TL00axSmart Phone, HUAWEI, ATR-LX1xSmart Phone, HUAWEI, ATR-LX2xSmart Phone, HUAWEI, ATR-LX3xSmart Phone, HUAWEI, STK-LX1aSmart Phone, HUAWEI, STK-LX1Smart Phone, HUAWEI, STK-L21Smart Phone, HUAWEI, STK-L21aSmart Phone, HUAWEI, STK-L22Smart Phone, HUAWEI, STK-L22aSmart Phone, HUAWEI, STK-LX3Smart Phone, HUAWEI, STK-LX3aSmart Phone, HUAWEI, STK-AL00Smart Phone, HUAWEI, STK-AL00aSmart Phone, HUAWEI, STK-TL00Smart Phone, HUAWEI, STK-TL00aSmart Phone, HUAWEI, STK-L23BAKSmart Phone, HUAWEI, GLK-TL00Smart Phone, HUAWEI, GLK-AL00Smart Phone, HUAWEI, GLK-LX1UrSmart Phone, HUAWEI, GLK-LX1USmart Phone, HUAWEI, GLK-LX1VrSmart Phone, HUAWEI, GLK-LX2rSmart Phone, HUAWEI, GLK-LX2Smart Phone, HUAWEI, GLK-LX1rSmart Phone, HUAWEI, GLK-LX1Smart Phone, HUAWEI, GLK-LX3rSmart Phone, HUAWEI, GLK-LX3Smart Phone, HUAWEI, MAR-LX1AmSmart Phone, HUAWEI, MAR-LX2mSmart Phone, HUAWEI, MAR-LX1MmSmart Phone, HUAWEI, MAR-LX3AmSmart Phone, HUAWEI, HWV33Smart Phone, HUAWEI, MAR-LX2JmSmart Phone, HUAWEI, MAR-LX1ASmart Phone, HUAWEI, MAR-LX1MSmart Phone, HUAWEI, MAR-LX3ASmart Phone, HUAWEI, MAR-LX2JSmart Phone, HUAWEI, AQM-AL00TSmart Phone, HUAWEI, AQM-AL00TaSmart Phone, HUAWEI, AQM-AL00Smart Phone, HUAWEI, AQM-AL00aSmart Phone, HUAWEI, AQM-TL00Smart Phone, HUAWEI, AQM-TL00aSmart Phone, HUAWEI, AQM-LX1MEBaSmart Phone, HUAWEI, AQM-LX1MEBSmart Phone, HUAWEI, AQM-LX2Smart Phone, HUAWEI, AQM-LX2aSmart Phone, HUAWEI, AQM-LX1Smart Phone, HUAWEI, AQM-LX1AFSmart Phone, HUAWEI, AQM-LX1aSmart Phone, HUAWEI, AQM-LX1AFaSmart Phone, HUAWEI, AQM-LX3Smart Phone, HUAWEI, AQM-LX3aSmart Phone, HUAWEI, LRA-AL00aSmart Phone, HUAWEI, LRA-AL00Smart Phone, HUAWEI, LRA-TL00Smart Phone, HUAWEI, LRA-TL00aSmart Phone, HUAWEI, LRA-LX1TSmart Phone, HUAWEI, LRA-LX1Smart Phone, HUAWEI, LRA-LX1AFSmart Phone, HUAWEI, LRA-LX3Smart Phone, HUAWEI, LRA-LX2JSmart Phone, HUAWEI, LRA-LX1TaSmart Phone, HUAWEI, LRA-LX1aSmart Phone, HUAWEI, LRA-LX1AFaSmart Phone, HUAWEI, LRA-LX3aSmart Phone, HUAWEI, LRA-LX2JaSmart Phone, HUAWEI, LRA-LX2Smart Phone, HUAWEI, LRA-LX2aSmart Phone, HUAWEI, GLK-LX1VmSmart Phone, HUAWEI, GLK-LX1UmSmart Phone, HUAWEI, GLK-LX2mSmart Phone, HUAWEI, GLK-LX1mSmart Phone, HUAWEI, GLK-LX3mPlay, COR-TL10Smart Phone, HUAWEI, MAR-TL00mSmart Phone, HUAWEI, MAR-AL00mSmart Phone, HUAWEI, GLK-AL00mSmart Phone, HUAWEI, GLK-TL00mSmart Phone, HONOR, HRY-AL10TaSmart Phone, HONOR, HRY-AL10Smart Phone, HONOR, HRY-AL10TSmart Phone, HONOR, HRY-TL00aSmart Phone, HONOR, HRY-TL00TaSmart Phone, HONOR, HRY-LX2TSmart Phone, HONOR, HRY-LX3Smart Phone, HONOR, HRY-LX3TSmart Phone, HUAWEI, POT-AL10aSmart Phone, HUAWEI, POT-AL10Smart Phone, HUAWEI, POT-AL20aSmart Phone, HUAWEI, POT-AL20Smart Phone, HUAWEI, POT-TL10aSmart Phone, HUAWEI, POT-TL10Smart Phone, HUAWEI, POT-LX2Smart Phone, HUAWEI, POT-LX2TSmart Phone, HUAWEI, POT-LX3TSmart Phone, HONOR, JAT-AL00Smart Phone, HONOR, JAT-TL00Smart Phone, HONOR, JAT-L29Smart Phone, HONOR, JAT-LX1Smart Phone, HONOR, JAT-LX3Smart Phone, HONOR, JAT-L41Smart Phone, HONOR, JAT-L29XSmart Phone, HONOR, JAT-LX1XSmart Phone, HONOR, JAT-L41XSmart Phone, HONOR, JAT-AL00Smart Phone, HONOR, JAT-TL00Smart Phone, HONOR, JAT-L29Smart Phone, HONOR, JAT-LX1Smart Phone, HONOR, JAT-LX3Smart Phone, HONOR, JAT-L41Smart Phone, HONOR, JAT-L29XSmart Phone, HONOR, JAT-LX1XSmart Phone, HONOR, JAT-L41XSmart Phone, HUAWEI, MRD-LX2Smart Phone, HUAWEI, MRD-LX3Smart Phone, HUAWEI, MRD-LX1Smart Phone, HUAWEI, MRD-LX1NSmart Phone, HUAWEI, MRD-LX1FSmart Phone, HUAWEI, MRD-TL00Smart Phone, HUAWEI, MRD-AL00Smart Phone, HUAWEI, MRD-LX3XSmart Phone, HUAWEI, MRD-LX2XSmart Phone, HUAWEI, MRD-LX1XSmart Phone, HUAWEI, MRD-LX1FXSmart Phone, HUAWEI, MAR-TL00mSmart Phone, HUAWEI, MAR-AL00mSmart Phone, HUAWEI, GLK-AL00mSmart Phone, HUAWEI, GLK-TL00mSmart Phone, HUAWEI, GOG-AL00Smart Phone, HUAWEI, GOG-AL10Smart Phone, HUAWEI, GOG-TL00Smart Phone, HUAWEI, GOG-TL10Smart Phone, HUAWEI, GOG-TL10Smart Phone, HUAWEI, GOG-LX2Smart Phone, HUAWEI, GOG-LX2ASmart Phone, HUAWEI, GOG-LX2BSmart Phone, HUAWEI, GOG-LX1MSmart Phone, HUAWEI, GOG-LX1MASmart Phone, HUAWEI, GOG-LX1MBSmart Phone, HUAWEI, GOG-LX1Smart Phone, HUAWEI, GOG-LX1ASmart Phone, HUAWEI, GOG-LX1BSmart Phone, HUAWEI, GOG-LX3Smart Phone, HUAWEI, GOG-LX3ASmart Phone, HUAWEI, GOG-LX3BHUAWEI/HONOR, JAT-AL00HUAWEI/HONOR, JAT-TL00HUAWEI/HONOR, JAT-L29HUAWEI/HONOR, JAT-LX1HUAWEI/HONOR, JAT-LX3HUAWEI/HONOR, JAT-L41HUAWEI/HONOR, JAT-L29XHUAWEI/HONOR, JAT-LX1XHUAWEI/HONOR, JAT-L41XHUAWEI/HONOR, MRD-LX3HUAWEI/HONOR, MRD-LX2HUAWEI/HONOR, MRD-LX1HUAWEI/HONOR, MRD-LX1NHUAWEI/HONOR, MRD-LX1FHUAWEI/HONOR, MRD-TL00HUAWEI/HONOR, MRD-AL00HUAWEI/HONOR, MRD-LX3XHUAWEI/HONOR, MRD-LX2XHUAWEI/HONOR, MRD-LX1XHUAWEI/HONOR, MRD-LX1FXHUAWEI/HONOR, KSA-LX9HUAWEI/HONOR, KSA-LX9XHUAWEI/HONOR, KSA-LX2HUAWEI/HONOR, KSA-LX3HUAWEI/HONOR, KSA-AL00HUAWEI/HONOR, KSA-TL00HUAWEI/HONOR, AMN-LX9XHUAWEI/HONOR, AMN-LX9HUAWEI/HONOR, AMN-LX1HUAWEI/HONOR, AMN-LX2HUAWEI/HONOR, AMN-LX3HUAWEI/HONOR, AMN-LX3XHUAWEI/HONOR, MED-LX3HUAWEI/HONOR, MED-LX2HUAWEI/HONOR, MED-LX1HUAWEI/HONOR, MED-LX1NHUAWEI/HONOR, MED-LX1FHUAWEI/HONOR, MED-TL00HUAWEI/HONOR, MED-AL00HUAWEI/HONOR, MOA-TL00HUAWEI/HONOR, MOA-AL00HUAWEI/HONOR, MOA-L29HUAWEI/HONOR, MOA-LX1HUAWEI/HONOR, MOA-LX3HUAWEI/HONOR, MOA-L41HUAWEI/HONOR, PKA-AL00HUAWEI/HONOR, PKA-TL00HUAWEI/HONOR, PKA-LX1HUAWEI/HONOR, PKA-LX2HUAWEI/HONOR, PKA-LX3HUAWEI/HONOR, PKA-LX9HUAWEI/HONOR, KEM-AL00HUAWEI/HONOR, KEM-TL00HUAWEI/HONOR, KEM-LX1HUAWEI/HONOR, KEM-LX2HUAWEI/HONOR, KEM-LX3HUAWEI/HONOR, KEM-LX9HUAWEI/HONOR, PEK-AL00HUAWEI/HONOR, PEK-AL10HUAWEI/HONOR, PEK-AL00aHUAWEI/HONOR, PEK-AL10aHUAWEI/HONOR, MKY-LX3HUAWEI/HONOR, JGA-AL00HUAWEI/HONOR, MKY-LX2HUAWEI/HONOR, MKY-LX1HUAWEI/HONOR, MKY-LX1NHUAWEI/HONOR, MKY-LX1FHUAWEI/HONOR, MKY-TL00HUAWEI/HONOR, MKY-AL00HUAWEI/HONOR, LPD-TL00HUAWEI/HONOR, LPD-AL00HUAWEI/HONOR, LPD-L29HUAWEI/HONOR, LPD-LX1HUAWEI/HONOR, LPD-LX3HUAWEI/HONOR, MNE-TL00HUAWEI/HONOR, MNE-AL00HUAWEI/HONOR, MNE-L29HUAWEI/HONOR, KNA-AL00HUAWEI/HONOR, KNA-TL00HUAWEI/HONOR, KNA-LX1HUAWEI/HONOR, KNA-LX2HUAWEI/HONOR, KNA-LX3HUAWEI/HONOR, KNA-LX9HUAWEI/HONOR, JGA-LX3HUAWEI/HONOR, JGA-LX2HUAWEI/HONOR, JGA-LX1HUAWEI/HONOR, JGA-LX1NHUAWEI/HONOR, JGA-LX1FHUAWEI/HONOR, JGA-TL00HUAWEI/HONOR, LPD-L41HUAWEI/HONOR, MNE-LX1HUAWEI/HONOR, MNE-LX3HUAWEI/HONOR, MNE-L41HUAWEI/HONOR, JDN2-L59HUAWEI/HONOR, JDN2-W59HNHUAWEI/HONOR, JDN2-AL50HNHUAWEI/HONOR, JDN2-AL50HUAWEI/HONOR, JDN2-W59HUAWEI/HONOR, WS8200HUAWEI/HONOR, WS8100HUAWEI/HONOR, WS8300HUAWEI/HONOR, WS8400HUAWEI/HONOR, WS8500HUAWEI/HONOR, WS8600HUAWEI/HONOR, WS8700HUAWEI/HONOR, WS8800HUAWEI/HONOR, WS8900HUAWEI/HONOR, WS8200HUAWEI/HONOR, WS8100HUAWEI/HONOR, WS8300HUAWEI/HONOR, WS8400HUAWEI/HONOR, WS8500HUAWEI/HONOR, WS8600HUAWEI/HONOR, WS8700HUAWEI/HONOR, WS8800HUAWEI/HONOR, WS8900HUAWEI/HONOR, MED-LX2HUAWEI/HONOR, MED-LX3HUAWEI/HONOR, MED-LX1HUAWEI/HONOR, MED-LX1NHUAWEI/HONOR, MED-LX1FHUAWEI/HONOR, MED-TL00HUAWEI/HONOR, MED-AL00HUAWEI/HONOR, MOA-TL00HUAWEI/HONOR, MOA-AL00HUAWEI/HONOR, MOA-L29HUAWEI/HONOR, MOA-LX1HUAWEI/HONOR, MOA-LX3HUAWEI/HONOR, MOA-L41HUAWEI/HONOR, PKA-AL00HUAWEI/HONOR, PKA-TL00HUAWEI/HONOR, PKA-LX1HUAWEI/HONOR, PKA-LX2HUAWEI/HONOR, PKA-LX3HUAWEI/HONOR, PKA-LX9HUAWEI/HONOR, KEM-AL00HUAWEI/HONOR, KEM-TL00HUAWEI/HONOR, KEM-LX1HUAWEI/HONOR, KEM-LX2HUAWEI/HONOR, KEM-LX3HUAWEI/HONOR, KEM-LX9HUAWEI/HONOR, PEK-AL00HUAWEI/HONOR, PEK-AL10HUAWEI/HONOR, PEK-AL00aHUAWEI/HONOR, PEK-AL10aHUAWEI/HONOR, KNA-AL00HUAWEI/HONOR, KNA-TL00HUAWEI/HONOR, KNA-LX1HUAWEI/HONOR, KNA-LX2HUAWEI/HONOR, KNA-LX3HUAWEI/HONOR, KNA-LX9HUAWEI/HONOR, GOG-AL10HUAWEI/HONOR, GOG-AL00HUAWEI/HONOR, GOG-TL00HUAWEI/HONOR, GOG-TL10HUAWEI/HONOR, GOG-LX2HUAWEI/HONOR, GOG-LX2AHUAWEI/HONOR, GOG-LX2BHUAWEI/HONOR, GOG-LX1MHUAWEI/HONOR, GOG-LX1MAHUAWEI/HONOR, GOG-LX1MBHUAWEI/HONOR, GOG-LX1HUAWEI/HONOR, GOG-LX1AHUAWEI/HONOR, GOG-LX1BHUAWEI/HONOR, GOG-LX3HUAWEI/HONOR, GOG-LX3AHUAWEI/HONOR, GOG-LX3BHUAWEI/HONOR, AQM- L41AHUAWEI/HONOR, MRD-LX1NXHUAWEI/HONOR, JAT-LX3XHUAWEI/HONOR, MED-LX9HUAWEI/HONOR, MOA-LX2HUAWEI/HONOR, MOA-LX9HUAWEI/HONOR, JGA-LX9HUAWEI/HONOR, MKY-LX9HUAWEI/HONOR, LPD-LX2HUAWEI/HONOR, LPD-LX9HUAWEI/HONOR, MNE-LX2HUAWEI/HONOR, MNE-LX9HUAWEI/HONOR, JFN-AN00HUAWEI/HONOR, JFN-AN10HUAWEI/HONOR, JFN-NX1HUAWEI/HONOR, JFN-NX2HUAWEI/HONOR, JFN-NX3HUAWEI/HONOR, JFN-AL00HUAWEI/HONOR, JFN-TL00HUAWEI/HONOR, JFN-LX1HUAWEI/HONOR, JFN-LX2HUAWEI/HONOR, JFN-LX3HUAWEI/HONOR, AQM-LX3aHUAWEI/HONOR, AQM-TL00aHUAWEI/HONOR, AQM-L62JHUAWEI/HONOR, AQM-AL00HUAWEI/HONOR, AQM-AL00aHUAWEI/HONOR, AQM-AL10HUAWEI/HONOR, AQM-AL10aHUAWEI/HONOR, AQM-AL20aHUAWEI/HONOR, AQM-AL20HUAWEI/HONOR, AQM-TL00HUAWEI/HONOR, AQM-TL00aHUAWEI/HONOR, AQM-TL10HUAWEI/HONOR, AQM-LX1HUAWEI/HONOR, AQM-LX1THUAWEI/HONOR, AQM-LX1AFHUAWEI/HONOR, AQM-L41AHUAWEI/HONOR, AQM-LX1BHUAWEI/HONOR, AQM-LX3HUAWEI/HONOR, AQM-LX1MEHUAWEI/HONOR, AQM-LX2HUAWEI/HONOR, AQM-LX2JHUAWEI/HONOR, AQM-LX62JHUAWEI/HONOR, AQM-LX3THUAWEI/HONOR, LRA-TL00aHUAWEI/HONOR, LRA-LX3TaHUAWEI/HONOR, LRA-AL00HUAWEI/HONOR, LRA-AL00aHUAWEI/HONOR, LRA-AL10HUAWEI/HONOR, LRA-AL10aHUAWEI/HONOR, LRA-TL00HUAWEI/HONOR, LRA-TL10HUAWEI/HONOR, LRA-TL10aHUAWEI/HONOR, LRA-AL20HUAWEI/HONOR, LRA-AL20aHUAWEI/HONOR, LRA-LX1HUAWEI/HONOR, LRA-LX1MEHUAWEI/HONOR, LRA-LX2HUAWEI/HONOR, LRA-LX2MEHUAWEI/HONOR, LRA-LX1THUAWEI/HONOR, LRA-LX2THUAWEI/HONOR, LRA-LX3THuawei / Honor , CV52Huawei / Honor, CV51Huawei / Honor , CV53Huawei / Honor , CV54Huawei / Honor, CV55Huawei / Honor , CV56HUAWEI/HONOR, JNY-AL10HUAWEI/HONOR, JNY-AL00HUAWEI/HONOR, JNY-TL00HUAWEI/HONOR, JNY-TL10HUAWEI/HONOR, JNY-LX2HUAWEI/HONOR, JNY-LX2AHUAWEI/HONOR, JNY-LX2BHUAWEI/HONOR, JNY-LX1MHUAWEI/HONOR, JNY-LX1MAHUAWEI/HONOR, JNY-LX1MBHUAWEI/HONOR, JNY-LX1HUAWEI/HONOR, JNY-LX1AHUAWEI/HONOR, JNY-LX1BHUAWEI/HONOR, JNY-LX3HUAWEI/HONOR, JNY-LX3AHUAWEI/HONOR, JNY-LX3BHUAWEI/HONOR, JNY-LX2JHUAWEI/HONOR, JNY-LX2JAHUAWEI/HONOR, JNY-LX2JBHUAWEI/HONOR, MAS-AL00HUAWEI/HONOR, MAS-AL10HUAWEI/HONOR, MAS-TL00HUAWEI/HONOR, MAS-TL10HUAWEI/HONOR, LRA-L41ATHUAWEI/HONOR, LRA-L41THUAWEI/HONOR, LRA-LX1BHUAWEI/HONOR, LRA-LX1BTHUAWEI/HONOR, LRA-LX3HUAWEI/HONOR, LRA-LX2JHUAWEI/HONOR, LRA-L62JHUAWEI/HONOR, MED-TL20HUAWEI/HONOR, MED-AL20HUAWEI/HONOR, MOA-TL20HUAWEI/HONOR, MOA-AL20HUAWEI/HONOR, JGA-TL20HUAWEI/HONOR, JGA-AL20HUAWEI/HONOR, MKY-TL20HUAWEI/HONOR, MKY-AL20HUAWEI/HONOR, LPD-TL20HUAWEI/HONOR, LPD-AL20HUAWEI/HONOR, MNE-TL20HUAWEI/HONOR, MNE-AL20HUAWEI/HONOR, MED-AL10HUAWEI/HONOR , MED-TL10HUAWEI/HONOR, MOA-TL10HUAWEI/HONOR, MOA-AL10HUAWEI/HONOR, PKA-AL20HUAWEI/HONOR, PKA-AL10HUAWEI/HONOR, PKA-TL10HUAWEI/HONOR, PKA-TL20HUAWEI/HONOR, KEM-AL20HUAWEI/HONOR, KEM-AL10HUAWEI/HONOR, KEM-TL10HUAWEI/HONOR, KEM-TL20HUAWEI/HONOR, PEK-AL20HUAWEI/HONOR, KNA-AL20HUAWEI/HONOR, KNA-AL10HUAWEI/HONOR, KNA-TL10HUAWEI/HONOR, KNA-TL20HUAWEI/HONOR, MKY-TL10HUAWEI/HONOR, JGA-TL10HUAWEI/HONOR, LPD-TL10HUAWEI/HONOR, OVL-TL10Smart Phone, HUAWEI/HONOR, BKK-AL30Smart Phone, HUAWEI/HONOR, BKK-AL20Smart Phone, HUAWEI/HONOR, DUB-AL10Smart Phone, HUAWEI/HONOR, DUB-AL10aSmart Phone, HUAWEI/HONOR, DUB-AL30HUAWEI/HONOR, AQM-LX1BTHUAWEI/HONOR, AQM-L41ATHUAWEI/HONOR, AQM-LX1METHUAWEI/HONOR, AQM-LX2THUAWEI/HONOR(1), LRA-L41AHUAWEI/HONOR, AMN-TL00HUAWEI/HONOR, AMN-AL00HUAWEI/HONOR, AMN-AL10HUAWEI/HONOR, KSA-AL10HUAWEI/HONOR, AMN-TL10HUAWEI/HONOR Smart Phone, MAR-LX1BHUAWEI/HONOR Smart Phone, MAR-LX2BHUAWEI/HONOR Smart Phone, MAR-LX3BmHUAWEI/HONOR Smart Phone, POT-AL10NOVA Smart Phone, MAR-LX1HHUAWEI/HONOR Smart Phone , JGA-AL30HUAWEI/HONOR Smart Phone, JGA-TL30HUAWEI/HONOR Smart Phone , JGA-AL10HUAWEI/HONOR Smart Phone , JGA-L41HUAWEI/HONOR Smart Phone , MKY-TL30HUAWEI/HONOR Smart Phone , MKY-AL30HUAWEI/HONOR Smart Phone , MKY-AL10HUAWEI/HONOR Smart Phone , MKY-L41HUAWEI/HONOR Smart Phone , LPD-TL30HUAWEI/HONOR Smart Phone , LPD-AL30HUAWEI/HONOR Smart Phone, LPD-AL10HUAWEI/HONOR Smart Phone , MNE-TL30HUAWEI/HONOR Smart Phone , MNE-AL30HUAWEI/HONOR Smart Phone , MNE-TL10HUAWEI/HONOR Smart Phone , MNE-AL10|
|HUAWEI_DRA_AL00|Android_SDK:_27_(8.1.0)|101927 - Host Subsystem67572 - Controller Subsystem96540 - Profile Subsystem104712 - Profile Subsystem|DRA-LX2, DRA-LX2DRA-TL00, DRA-TL00DRA-AL00, DRA-AL00DUA-AL00, DUA-AL00DUA-TL00, DUA-TL00DRA-L01, DRA-L01DRA-L21, DRA-L21DRA-LX3, DRA-LX3DUA-L22, DUA-L22DUA-LX3, DUA-LX3BG2-W09, BG2-W09Smart Phone, HUAWEI, DRA-LX5Smart Phone, HONOR, DUA-L32HUAWEI/HONOR Smart Phone, DUA-LX5|
|HUAWEI_INE-LX2|Android_SDK:_28_(9)|101927 - Host Subsystem86634 - Controller Subsystem107026 - Profile Subsystem|COL-AL10, COL-AL10COL-AL00, COL-AL00COL-TL10, COL-TL10COL-TL00, COL-TL00COL-L29, COL-L29Smart Phone,Honor, COR-TL00Smart Phone,Honor, COR-AL00Smart Phone,Honor, COR-AL10Smart Phone,Honor, COR-L29Smart Phone, HUAWEI, PAR-AL00Smart Phone, HUAWEI, PAR-TL00Smart Phone, HUAWEI, PAR-LX1Smart Phone, HUAWEI, PAR-LX9Smart Phone, HUAWEI, PAR-LX1MSmart Phone, HUAWEI, PAR-TL20Smart Phone, HUAWEI, INE-AL00Smart Phone, HUAWEI, INE-TL00Smart Phone, HUAWEI, SNE-AL00Smart Phone, HUAWEI, INE-LX1Smart Phone, HUAWEI, INE-LX2Smart Phone, HUAWEI, SNE-LX1Smart Phone, HUAWEI, SNE-LX2Smart Phone, HUAWEI, SNE-LX3Smart Phone, HUAWEI, JKM-LX1Smart Phone, HUAWEI, JKM-LX2Smart Phone, HUAWEI, JKM-LX3Smart Phone, HUAWEI, JKM-TL00Smart Phone, HUAWEI, JKM-AL00Smart Phone, HUAWEI, JKM-AL00aSmart Phone, HUAWEI, JKM-AL00bSmart Phone, HONOR, JSN-AL00Smart Phone, HONOR, JSN-AL00aSmart Phone, HONOR, JSN-TL00Smart Phone, HONOR, JSN-L21Smart Phone, HONOR, JSN-L22Smart Phone, HONOR, JSN-L42Smart Phone, HONOR, JSN-L23Smart Phone, HUAWEI, INE-LX2rSmart Phone, HUAWEI, INE-LX1rSmart Phone, HONOR, POT-LX1AFSmart Phone, HONOR, POT-LX1Smart Phone, HONOR, POT-LX3Smart Phone, HONOR, POT-LX2JSmart Phone, HUAWEI, VCE-TL00Smart Phone, HUAWEI, VCE-AL00Smart Phone, HONOR, POT-L72JSmart Phone, HONOR, POT-L62JSmart Phone, HONOR, HRY-AL00Smart Phone, HONOR, HRY-AL00aSmart Phone, HONOR, HRY-TL00Smart Phone, HONOR, HRY-LX1Smart Phone, HONOR, HRY-LX1MEBSmart Phone, HONOR, HRY-LX2Smart Phone, HUAWEI, POT-LX1Smart Phone, HUAWEI, POT-LX1AFSmart Phone, HUAWEI, POT-LX3Smart Phone, HUAWEI, POT-LX2JSmart Phone, HUAWEI, POT-L62JSmart Phone, HUAWEI, POT-L72JSmart Phone, HUAWEI, VCE-L22Smart Phone, HUAWEI, POT-TL00aSmart Phone, HUAWEI, POT-AL00Smart Phone, HUAWEI, POT-AL00aSmart Phone, HUAWEI, POT-LX1TSmart Phone, HUAWEI, MAR-TL00Smart Phone, HUAWEI, MAR-AL00Smart Phone, HUAWEI, MAR-LX2Smart Phone, HUAWEI, MAR-LX1ASmart Phone, HUAWEI, MAR-LX1MSmart Phone, HUAWEI, MAR-LX3ASmart Phone, HUAWEI, MAR-LX2JSmart Phone, HONOR, HRY-AL00TaSmart Phone, HONOR, HRY-AL00TSmart Phone, HONOR, HRY-TL00TSmart Phone, HONOR, HRY-LX1TSmart Phone, HONOR, ASK-AL00xSmart Phone, HONOR, ASK-AL00axSmart Phone, HONOR, ASK-TL00xSmart Phone, HONOR, ASK-TL00axSmart Phone, HONOR, ASK-LX1xSmart Phone, HONOR, ASK-LX2xSmart Phone, HONOR, ASK-LX2xSmart Phone, HUAWEI, ATR-AL00xSmart Phone, HUAWEI, ATR-AL00axSmart Phone, HUAWEI, ATR-TL00xSmart Phone, HUAWEI, ATR-TL00axSmart Phone, HUAWEI, ATR-LX1xSmart Phone, HUAWEI, ATR-LX2xSmart Phone, HUAWEI, ATR-LX3xSmart Phone, HUAWEI, STK-LX1aSmart Phone, HUAWEI, STK-LX1Smart Phone, HUAWEI, STK-L21Smart Phone, HUAWEI, STK-L21aSmart Phone, HUAWEI, STK-L22Smart Phone, HUAWEI, STK-L22aSmart Phone, HUAWEI, STK-LX3Smart Phone, HUAWEI, STK-LX3aSmart Phone, HUAWEI, STK-AL00Smart Phone, HUAWEI, STK-AL00aSmart Phone, HUAWEI, STK-TL00Smart Phone, HUAWEI, STK-TL00aSmart Phone, HUAWEI, STK-L23BAKSmart Phone, HUAWEI, GLK-TL00Smart Phone, HUAWEI, GLK-AL00Smart Phone, HUAWEI, GLK-LX1UrSmart Phone, HUAWEI, GLK-LX1USmart Phone, HUAWEI, GLK-LX1VrSmart Phone, HUAWEI, GLK-LX2rSmart Phone, HUAWEI, GLK-LX2Smart Phone, HUAWEI, GLK-LX1rSmart Phone, HUAWEI, GLK-LX1Smart Phone, HUAWEI, GLK-LX3rSmart Phone, HUAWEI, GLK-LX3Smart Phone, HUAWEI, MAR-LX1AmSmart Phone, HUAWEI, MAR-LX2mSmart Phone, HUAWEI, MAR-LX1MmSmart Phone, HUAWEI, MAR-LX3AmSmart Phone, HUAWEI, HWV33Smart Phone, HUAWEI, MAR-LX2JmSmart Phone, HUAWEI, MAR-LX1ASmart Phone, HUAWEI, MAR-LX1MSmart Phone, HUAWEI, MAR-LX3ASmart Phone, HUAWEI, MAR-LX2JSmart Phone, HUAWEI, AQM-AL00TSmart Phone, HUAWEI, AQM-AL00TaSmart Phone, HUAWEI, AQM-AL00Smart Phone, HUAWEI, AQM-AL00aSmart Phone, HUAWEI, AQM-TL00Smart Phone, HUAWEI, AQM-TL00aSmart Phone, HUAWEI, AQM-LX1MEBaSmart Phone, HUAWEI, AQM-LX1MEBSmart Phone, HUAWEI, AQM-LX2Smart Phone, HUAWEI, AQM-LX2aSmart Phone, HUAWEI, AQM-LX1Smart Phone, HUAWEI, AQM-LX1AFSmart Phone, HUAWEI, AQM-LX1aSmart Phone, HUAWEI, AQM-LX1AFaSmart Phone, HUAWEI, AQM-LX3Smart Phone, HUAWEI, AQM-LX3aSmart Phone, HUAWEI, LRA-AL00aSmart Phone, HUAWEI, LRA-AL00Smart Phone, HUAWEI, LRA-TL00Smart Phone, HUAWEI, LRA-TL00aSmart Phone, HUAWEI, LRA-LX1TSmart Phone, HUAWEI, LRA-LX1Smart Phone, HUAWEI, LRA-LX1AFSmart Phone, HUAWEI, LRA-LX3Smart Phone, HUAWEI, LRA-LX2JSmart Phone, HUAWEI, LRA-LX1TaSmart Phone, HUAWEI, LRA-LX1aSmart Phone, HUAWEI, LRA-LX1AFaSmart Phone, HUAWEI, LRA-LX3aSmart Phone, HUAWEI, LRA-LX2JaSmart Phone, HUAWEI, LRA-LX2Smart Phone, HUAWEI, LRA-LX2aSmart Phone, HUAWEI, GLK-LX1VmSmart Phone, HUAWEI, GLK-LX1UmSmart Phone, HUAWEI, GLK-LX2mSmart Phone, HUAWEI, GLK-LX1mSmart Phone, HUAWEI, GLK-LX3mPlay, COR-TL10Smart Phone, HUAWEI, MAR-TL00mSmart Phone, HUAWEI, MAR-AL00mSmart Phone, HUAWEI, GLK-AL00mSmart Phone, HUAWEI, GLK-TL00mSmart Phone, HONOR, HRY-AL10TaSmart Phone, HONOR, HRY-AL10Smart Phone, HONOR, HRY-AL10TSmart Phone, HONOR, HRY-TL00aSmart Phone, HONOR, HRY-TL00TaSmart Phone, HONOR, HRY-LX2TSmart Phone, HONOR, HRY-LX3Smart Phone, HONOR, HRY-LX3TSmart Phone, HUAWEI, POT-AL10aSmart Phone, HUAWEI, POT-AL10Smart Phone, HUAWEI, POT-AL20aSmart Phone, HUAWEI, POT-AL20Smart Phone, HUAWEI, POT-TL10aSmart Phone, HUAWEI, POT-TL10Smart Phone, HUAWEI, POT-LX2Smart Phone, HUAWEI, POT-LX2TSmart Phone, HUAWEI, POT-LX3TSmart Phone, HONOR, JAT-AL00Smart Phone, HONOR, JAT-TL00Smart Phone, HONOR, JAT-L29Smart Phone, HONOR, JAT-LX1Smart Phone, HONOR, JAT-LX3Smart Phone, HONOR, JAT-L41Smart Phone, HONOR, JAT-L29XSmart Phone, HONOR, JAT-LX1XSmart Phone, HONOR, JAT-L41XSmart Phone, HONOR, JAT-AL00Smart Phone, HONOR, JAT-TL00Smart Phone, HONOR, JAT-L29Smart Phone, HONOR, JAT-LX1Smart Phone, HONOR, JAT-LX3Smart Phone, HONOR, JAT-L41Smart Phone, HONOR, JAT-L29XSmart Phone, HONOR, JAT-LX1XSmart Phone, HONOR, JAT-L41XSmart Phone, HUAWEI, MRD-LX2Smart Phone, HUAWEI, MRD-LX3Smart Phone, HUAWEI, MRD-LX1Smart Phone, HUAWEI, MRD-LX1NSmart Phone, HUAWEI, MRD-LX1FSmart Phone, HUAWEI, MRD-TL00Smart Phone, HUAWEI, MRD-AL00Smart Phone, HUAWEI, MRD-LX3XSmart Phone, HUAWEI, MRD-LX2XSmart Phone, HUAWEI, MRD-LX1XSmart Phone, HUAWEI, MRD-LX1FXSmart Phone, HUAWEI, MAR-TL00mSmart Phone, HUAWEI, MAR-AL00mSmart Phone, HUAWEI, GLK-AL00mSmart Phone, HUAWEI, GLK-TL00mSmart Phone, HUAWEI, GOG-AL00Smart Phone, HUAWEI, GOG-AL10Smart Phone, HUAWEI, GOG-TL00Smart Phone, HUAWEI, GOG-TL10Smart Phone, HUAWEI, GOG-TL10Smart Phone, HUAWEI, GOG-LX2Smart Phone, HUAWEI, GOG-LX2ASmart Phone, HUAWEI, GOG-LX2BSmart Phone, HUAWEI, GOG-LX1MSmart Phone, HUAWEI, GOG-LX1MASmart Phone, HUAWEI, GOG-LX1MBSmart Phone, HUAWEI, GOG-LX1Smart Phone, HUAWEI, GOG-LX1ASmart Phone, HUAWEI, GOG-LX1BSmart Phone, HUAWEI, GOG-LX3Smart Phone, HUAWEI, GOG-LX3ASmart Phone, HUAWEI, GOG-LX3BHUAWEI/HONOR, JAT-AL00HUAWEI/HONOR, JAT-TL00HUAWEI/HONOR, JAT-L29HUAWEI/HONOR, JAT-LX1HUAWEI/HONOR, JAT-LX3HUAWEI/HONOR, JAT-L41HUAWEI/HONOR, JAT-L29XHUAWEI/HONOR, JAT-LX1XHUAWEI/HONOR, JAT-L41XHUAWEI/HONOR, MRD-LX3HUAWEI/HONOR, MRD-LX2HUAWEI/HONOR, MRD-LX1HUAWEI/HONOR, MRD-LX1NHUAWEI/HONOR, MRD-LX1FHUAWEI/HONOR, MRD-TL00HUAWEI/HONOR, MRD-AL00HUAWEI/HONOR, MRD-LX3XHUAWEI/HONOR, MRD-LX2XHUAWEI/HONOR, MRD-LX1XHUAWEI/HONOR, MRD-LX1FXHUAWEI/HONOR, KSA-LX9HUAWEI/HONOR, KSA-LX9XHUAWEI/HONOR, KSA-LX2HUAWEI/HONOR, KSA-LX3HUAWEI/HONOR, KSA-AL00HUAWEI/HONOR, KSA-TL00HUAWEI/HONOR, AMN-LX9XHUAWEI/HONOR, AMN-LX9HUAWEI/HONOR, AMN-LX1HUAWEI/HONOR, AMN-LX2HUAWEI/HONOR, AMN-LX3HUAWEI/HONOR, AMN-LX3XHUAWEI/HONOR, MED-LX3HUAWEI/HONOR, MED-LX2HUAWEI/HONOR, MED-LX1HUAWEI/HONOR, MED-LX1NHUAWEI/HONOR, MED-LX1FHUAWEI/HONOR, MED-TL00HUAWEI/HONOR, MED-AL00HUAWEI/HONOR, MOA-TL00HUAWEI/HONOR, MOA-AL00HUAWEI/HONOR, MOA-L29HUAWEI/HONOR, MOA-LX1HUAWEI/HONOR, MOA-LX3HUAWEI/HONOR, MOA-L41HUAWEI/HONOR, PKA-AL00HUAWEI/HONOR, PKA-TL00HUAWEI/HONOR, PKA-LX1HUAWEI/HONOR, PKA-LX2HUAWEI/HONOR, PKA-LX3HUAWEI/HONOR, PKA-LX9HUAWEI/HONOR, KEM-AL00HUAWEI/HONOR, KEM-TL00HUAWEI/HONOR, KEM-LX1HUAWEI/HONOR, KEM-LX2HUAWEI/HONOR, KEM-LX3HUAWEI/HONOR, KEM-LX9HUAWEI/HONOR, PEK-AL00HUAWEI/HONOR, PEK-AL10HUAWEI/HONOR, PEK-AL00aHUAWEI/HONOR, PEK-AL10aHUAWEI/HONOR, MKY-LX3HUAWEI/HONOR, JGA-AL00HUAWEI/HONOR, MKY-LX2HUAWEI/HONOR, MKY-LX1HUAWEI/HONOR, MKY-LX1NHUAWEI/HONOR, MKY-LX1FHUAWEI/HONOR, MKY-TL00HUAWEI/HONOR, MKY-AL00HUAWEI/HONOR, LPD-TL00HUAWEI/HONOR, LPD-AL00HUAWEI/HONOR, LPD-L29HUAWEI/HONOR, LPD-LX1HUAWEI/HONOR, LPD-LX3HUAWEI/HONOR, MNE-TL00HUAWEI/HONOR, MNE-AL00HUAWEI/HONOR, MNE-L29HUAWEI/HONOR, KNA-AL00HUAWEI/HONOR, KNA-TL00HUAWEI/HONOR, KNA-LX1HUAWEI/HONOR, KNA-LX2HUAWEI/HONOR, KNA-LX3HUAWEI/HONOR, KNA-LX9HUAWEI/HONOR, JGA-LX3HUAWEI/HONOR, JGA-LX2HUAWEI/HONOR, JGA-LX1HUAWEI/HONOR, JGA-LX1NHUAWEI/HONOR, JGA-LX1FHUAWEI/HONOR, JGA-TL00HUAWEI/HONOR, LPD-L41HUAWEI/HONOR, MNE-LX1HUAWEI/HONOR, MNE-LX3HUAWEI/HONOR, MNE-L41HUAWEI/HONOR, JDN2-L59HUAWEI/HONOR, JDN2-W59HNHUAWEI/HONOR, JDN2-AL50HNHUAWEI/HONOR, JDN2-AL50HUAWEI/HONOR, JDN2-W59HUAWEI/HONOR, WS8200HUAWEI/HONOR, WS8100HUAWEI/HONOR, WS8300HUAWEI/HONOR, WS8400HUAWEI/HONOR, WS8500HUAWEI/HONOR, WS8600HUAWEI/HONOR, WS8700HUAWEI/HONOR, WS8800HUAWEI/HONOR, WS8900HUAWEI/HONOR, WS8200HUAWEI/HONOR, WS8100HUAWEI/HONOR, WS8300HUAWEI/HONOR, WS8400HUAWEI/HONOR, WS8500HUAWEI/HONOR, WS8600HUAWEI/HONOR, WS8700HUAWEI/HONOR, WS8800HUAWEI/HONOR, WS8900HUAWEI/HONOR, MED-LX2HUAWEI/HONOR, MED-LX3HUAWEI/HONOR, MED-LX1HUAWEI/HONOR, MED-LX1NHUAWEI/HONOR, MED-LX1FHUAWEI/HONOR, MED-TL00HUAWEI/HONOR, MED-AL00HUAWEI/HONOR, MOA-TL00HUAWEI/HONOR, MOA-AL00HUAWEI/HONOR, MOA-L29HUAWEI/HONOR, MOA-LX1HUAWEI/HONOR, MOA-LX3HUAWEI/HONOR, MOA-L41HUAWEI/HONOR, PKA-AL00HUAWEI/HONOR, PKA-TL00HUAWEI/HONOR, PKA-LX1HUAWEI/HONOR, PKA-LX2HUAWEI/HONOR, PKA-LX3HUAWEI/HONOR, PKA-LX9HUAWEI/HONOR, KEM-AL00HUAWEI/HONOR, KEM-TL00HUAWEI/HONOR, KEM-LX1HUAWEI/HONOR, KEM-LX2HUAWEI/HONOR, KEM-LX3HUAWEI/HONOR, KEM-LX9HUAWEI/HONOR, PEK-AL00HUAWEI/HONOR, PEK-AL10HUAWEI/HONOR, PEK-AL00aHUAWEI/HONOR, PEK-AL10aHUAWEI/HONOR, KNA-AL00HUAWEI/HONOR, KNA-TL00HUAWEI/HONOR, KNA-LX1HUAWEI/HONOR, KNA-LX2HUAWEI/HONOR, KNA-LX3HUAWEI/HONOR, KNA-LX9HUAWEI/HONOR, GOG-AL10HUAWEI/HONOR, GOG-AL00HUAWEI/HONOR, GOG-TL00HUAWEI/HONOR, GOG-TL10HUAWEI/HONOR, GOG-LX2HUAWEI/HONOR, GOG-LX2AHUAWEI/HONOR, GOG-LX2BHUAWEI/HONOR, GOG-LX1MHUAWEI/HONOR, GOG-LX1MAHUAWEI/HONOR, GOG-LX1MBHUAWEI/HONOR, GOG-LX1HUAWEI/HONOR, GOG-LX1AHUAWEI/HONOR, GOG-LX1BHUAWEI/HONOR, GOG-LX3HUAWEI/HONOR, GOG-LX3AHUAWEI/HONOR, GOG-LX3BHUAWEI/HONOR, AQM- L41AHUAWEI/HONOR, MRD-LX1NXHUAWEI/HONOR, JAT-LX3XHUAWEI/HONOR, MED-LX9HUAWEI/HONOR, MOA-LX2HUAWEI/HONOR, MOA-LX9HUAWEI/HONOR, JGA-LX9HUAWEI/HONOR, MKY-LX9HUAWEI/HONOR, LPD-LX2HUAWEI/HONOR, LPD-LX9HUAWEI/HONOR, MNE-LX2HUAWEI/HONOR, MNE-LX9HUAWEI/HONOR, JFN-AN00HUAWEI/HONOR, JFN-AN10HUAWEI/HONOR, JFN-NX1HUAWEI/HONOR, JFN-NX2HUAWEI/HONOR, JFN-NX3HUAWEI/HONOR, JFN-AL00HUAWEI/HONOR, JFN-TL00HUAWEI/HONOR, JFN-LX1HUAWEI/HONOR, JFN-LX2HUAWEI/HONOR, JFN-LX3HUAWEI/HONOR, AQM-LX3aHUAWEI/HONOR, AQM-TL00aHUAWEI/HONOR, AQM-L62JHUAWEI/HONOR, AQM-AL00HUAWEI/HONOR, AQM-AL00aHUAWEI/HONOR, AQM-AL10HUAWEI/HONOR, AQM-AL10aHUAWEI/HONOR, AQM-AL20aHUAWEI/HONOR, AQM-AL20HUAWEI/HONOR, AQM-TL00HUAWEI/HONOR, AQM-TL00aHUAWEI/HONOR, AQM-TL10HUAWEI/HONOR, AQM-LX1HUAWEI/HONOR, AQM-LX1THUAWEI/HONOR, AQM-LX1AFHUAWEI/HONOR, AQM-L41AHUAWEI/HONOR, AQM-LX1BHUAWEI/HONOR, AQM-LX3HUAWEI/HONOR, AQM-LX1MEHUAWEI/HONOR, AQM-LX2HUAWEI/HONOR, AQM-LX2JHUAWEI/HONOR, AQM-LX62JHUAWEI/HONOR, AQM-LX3THUAWEI/HONOR, LRA-TL00aHUAWEI/HONOR, LRA-LX3TaHUAWEI/HONOR, LRA-AL00HUAWEI/HONOR, LRA-AL00aHUAWEI/HONOR, LRA-AL10HUAWEI/HONOR, LRA-AL10aHUAWEI/HONOR, LRA-TL00HUAWEI/HONOR, LRA-TL10HUAWEI/HONOR, LRA-TL10aHUAWEI/HONOR, LRA-AL20HUAWEI/HONOR, LRA-AL20aHUAWEI/HONOR, LRA-LX1HUAWEI/HONOR, LRA-LX1MEHUAWEI/HONOR, LRA-LX2HUAWEI/HONOR, LRA-LX2MEHUAWEI/HONOR, LRA-LX1THUAWEI/HONOR, LRA-LX2THUAWEI/HONOR, LRA-LX3THuawei / Honor , CV52Huawei / Honor, CV51Huawei / Honor , CV53Huawei / Honor , CV54Huawei / Honor, CV55Huawei / Honor , CV56HUAWEI/HONOR, JNY-AL10HUAWEI/HONOR, JNY-AL00HUAWEI/HONOR, JNY-TL00HUAWEI/HONOR, JNY-TL10HUAWEI/HONOR, JNY-LX2HUAWEI/HONOR, JNY-LX2AHUAWEI/HONOR, JNY-LX2BHUAWEI/HONOR, JNY-LX1MHUAWEI/HONOR, JNY-LX1MAHUAWEI/HONOR, JNY-LX1MBHUAWEI/HONOR, JNY-LX1HUAWEI/HONOR, JNY-LX1AHUAWEI/HONOR, JNY-LX1BHUAWEI/HONOR, JNY-LX3HUAWEI/HONOR, JNY-LX3AHUAWEI/HONOR, JNY-LX3BHUAWEI/HONOR, JNY-LX2JHUAWEI/HONOR, JNY-LX2JAHUAWEI/HONOR, JNY-LX2JBHUAWEI/HONOR, MAS-AL00HUAWEI/HONOR, MAS-AL10HUAWEI/HONOR, MAS-TL00HUAWEI/HONOR, MAS-TL10HUAWEI/HONOR, LRA-L41ATHUAWEI/HONOR, LRA-L41THUAWEI/HONOR, LRA-LX1BHUAWEI/HONOR, LRA-LX1BTHUAWEI/HONOR, LRA-LX3HUAWEI/HONOR, LRA-LX2JHUAWEI/HONOR, LRA-L62JHUAWEI/HONOR, MED-TL20HUAWEI/HONOR, MED-AL20HUAWEI/HONOR, MOA-TL20HUAWEI/HONOR, MOA-AL20HUAWEI/HONOR, JGA-TL20HUAWEI/HONOR, JGA-AL20HUAWEI/HONOR, MKY-TL20HUAWEI/HONOR, MKY-AL20HUAWEI/HONOR, LPD-TL20HUAWEI/HONOR, LPD-AL20HUAWEI/HONOR, MNE-TL20HUAWEI/HONOR, MNE-AL20HUAWEI/HONOR, MED-AL10HUAWEI/HONOR , MED-TL10HUAWEI/HONOR, MOA-TL10HUAWEI/HONOR, MOA-AL10HUAWEI/HONOR, PKA-AL20HUAWEI/HONOR, PKA-AL10HUAWEI/HONOR, PKA-TL10HUAWEI/HONOR, PKA-TL20HUAWEI/HONOR, KEM-AL20HUAWEI/HONOR, KEM-AL10HUAWEI/HONOR, KEM-TL10HUAWEI/HONOR, KEM-TL20HUAWEI/HONOR, PEK-AL20HUAWEI/HONOR, KNA-AL20HUAWEI/HONOR, KNA-AL10HUAWEI/HONOR, KNA-TL10HUAWEI/HONOR, KNA-TL20HUAWEI/HONOR, MKY-TL10HUAWEI/HONOR, JGA-TL10HUAWEI/HONOR, LPD-TL10HUAWEI/HONOR, OVL-TL10Smart Phone, HUAWEI/HONOR, BKK-AL30Smart Phone, HUAWEI/HONOR, BKK-AL20Smart Phone, HUAWEI/HONOR, DUB-AL10Smart Phone, HUAWEI/HONOR, DUB-AL10aSmart Phone, HUAWEI/HONOR, DUB-AL30HUAWEI/HONOR, AQM-LX1BTHUAWEI/HONOR, AQM-L41ATHUAWEI/HONOR, AQM-LX1METHUAWEI/HONOR, AQM-LX2THUAWEI/HONOR(1), LRA-L41AHUAWEI/HONOR, AMN-TL00HUAWEI/HONOR, AMN-AL00HUAWEI/HONOR, AMN-AL10HUAWEI/HONOR, KSA-AL10HUAWEI/HONOR, AMN-TL10HUAWEI/HONOR Smart Phone, MAR-LX1BHUAWEI/HONOR Smart Phone, MAR-LX2BHUAWEI/HONOR Smart Phone, MAR-LX3BmHUAWEI/HONOR Smart Phone, POT-AL10NOVA Smart Phone, MAR-LX1HHUAWEI/HONOR Smart Phone , JGA-AL30HUAWEI/HONOR Smart Phone, JGA-TL30HUAWEI/HONOR Smart Phone , JGA-AL10HUAWEI/HONOR Smart Phone , JGA-L41HUAWEI/HONOR Smart Phone , MKY-TL30HUAWEI/HONOR Smart Phone , MKY-AL30HUAWEI/HONOR Smart Phone , MKY-AL10HUAWEI/HONOR Smart Phone , MKY-L41HUAWEI/HONOR Smart Phone , LPD-TL30HUAWEI/HONOR Smart Phone , LPD-AL30HUAWEI/HONOR Smart Phone, LPD-AL10HUAWEI/HONOR Smart Phone , MNE-TL30HUAWEI/HONOR Smart Phone , MNE-AL30HUAWEI/HONOR Smart Phone , MNE-TL10HUAWEI/HONOR Smart Phone , MNE-AL10|
|HUAWEI_WAS_AL00|Android_SDK:_26_(8.0.0)|80373 - End Product|, HUAWEI VNS-L31, HUAWEI VNS-L21, HUAWEI VNS-L22, HUAWEI VNS-L23, HUAWEI VNS-L53, NEM-AL10, NEM-TL00, NEM-TL00H, NEM-UL10, HUAWEI NMO-L21, NMO-L21, HUAWEI NMO-L31, NMO-L31, NEM-L21, NEM-L51, HUAWEI NMO-L22, NMO-L22, NEM-L22, HUAWEI NMO-L23, NMO-L23BTV-DL09, BTV-DL09BTV-W09, BTV-W09BLL-L21, BLL-L21BLL-L22, BLL-L22BLL-L23, BLL-L23BLN-AL10, BLN-AL10BLN-L21, BLN-L21BLN-L22, BLN-L22BLN-L24, BLN-L24BLN-TL00, BLN-TL00BLN-TL10, BLN-TL10VEN-L22, VEN-L22d-01J, d-01JBLN-AL20, BLN-AL20PRA-LX1, PRA-LX1PRA-LA1, PRA-LA1PRA-LX2, PRA-LX2PRA-LX3, PRA-LX3PRA-AL00, PRA-AL00PRA-AL00X, PRA-AL00XPRA-TL10, PRA-TL10WAS-L03T, WAS-L03TWAS-LX1, WAS-LX1WAS-LX1A, WAS-LX1AWAS-LX2, WAS-LX2WAS-LX2J, WAS-LX2JWAS-LX3, WAS-LX3WAS-AL00, WAS-AL00WAS-TL10, WAS-TL10BLN-AL30, BLN-AL30BLN-AL40, BLN-AL40608HW, 608HWBND-AL10, BND-AL10BND-TL10, BND-TL10BND-L21, BND-L21BND-L24, BND-L24BND-AL00, BND-AL00BND-L31, BND-L31BND-L34, BND-L34|
|HUAWEI_MAR-LX2|Android_SDK:_28_(9)|101927 - Host Subsystem86634 - Controller Subsystem107026 - Profile Subsystem|COL-AL10, COL-AL10COL-AL00, COL-AL00COL-TL10, COL-TL10COL-TL00, COL-TL00COL-L29, COL-L29Smart Phone,Honor, COR-TL00Smart Phone,Honor, COR-AL00Smart Phone,Honor, COR-AL10Smart Phone,Honor, COR-L29Smart Phone, HUAWEI, PAR-AL00Smart Phone, HUAWEI, PAR-TL00Smart Phone, HUAWEI, PAR-LX1Smart Phone, HUAWEI, PAR-LX9Smart Phone, HUAWEI, PAR-LX1MSmart Phone, HUAWEI, PAR-TL20Smart Phone, HUAWEI, INE-AL00Smart Phone, HUAWEI, INE-TL00Smart Phone, HUAWEI, SNE-AL00Smart Phone, HUAWEI, INE-LX1Smart Phone, HUAWEI, INE-LX2Smart Phone, HUAWEI, SNE-LX1Smart Phone, HUAWEI, SNE-LX2Smart Phone, HUAWEI, SNE-LX3Smart Phone, HUAWEI, JKM-LX1Smart Phone, HUAWEI, JKM-LX2Smart Phone, HUAWEI, JKM-LX3Smart Phone, HUAWEI, JKM-TL00Smart Phone, HUAWEI, JKM-AL00Smart Phone, HUAWEI, JKM-AL00aSmart Phone, HUAWEI, JKM-AL00bSmart Phone, HONOR, JSN-AL00Smart Phone, HONOR, JSN-AL00aSmart Phone, HONOR, JSN-TL00Smart Phone, HONOR, JSN-L21Smart Phone, HONOR, JSN-L22Smart Phone, HONOR, JSN-L42Smart Phone, HONOR, JSN-L23Smart Phone, HUAWEI, INE-LX2rSmart Phone, HUAWEI, INE-LX1rSmart Phone, HONOR, POT-LX1AFSmart Phone, HONOR, POT-LX1Smart Phone, HONOR, POT-LX3Smart Phone, HONOR, POT-LX2JSmart Phone, HUAWEI, VCE-TL00Smart Phone, HUAWEI, VCE-AL00Smart Phone, HONOR, POT-L72JSmart Phone, HONOR, POT-L62JSmart Phone, HONOR, HRY-AL00Smart Phone, HONOR, HRY-AL00aSmart Phone, HONOR, HRY-TL00Smart Phone, HONOR, HRY-LX1Smart Phone, HONOR, HRY-LX1MEBSmart Phone, HONOR, HRY-LX2Smart Phone, HUAWEI, POT-LX1Smart Phone, HUAWEI, POT-LX1AFSmart Phone, HUAWEI, POT-LX3Smart Phone, HUAWEI, POT-LX2JSmart Phone, HUAWEI, POT-L62JSmart Phone, HUAWEI, POT-L72JSmart Phone, HUAWEI, VCE-L22Smart Phone, HUAWEI, POT-TL00aSmart Phone, HUAWEI, POT-AL00Smart Phone, HUAWEI, POT-AL00aSmart Phone, HUAWEI, POT-LX1TSmart Phone, HUAWEI, MAR-TL00Smart Phone, HUAWEI, MAR-AL00Smart Phone, HUAWEI, MAR-LX2Smart Phone, HUAWEI, MAR-LX1ASmart Phone, HUAWEI, MAR-LX1MSmart Phone, HUAWEI, MAR-LX3ASmart Phone, HUAWEI, MAR-LX2JSmart Phone, HONOR, HRY-AL00TaSmart Phone, HONOR, HRY-AL00TSmart Phone, HONOR, HRY-TL00TSmart Phone, HONOR, HRY-LX1TSmart Phone, HONOR, ASK-AL00xSmart Phone, HONOR, ASK-AL00axSmart Phone, HONOR, ASK-TL00xSmart Phone, HONOR, ASK-TL00axSmart Phone, HONOR, ASK-LX1xSmart Phone, HONOR, ASK-LX2xSmart Phone, HONOR, ASK-LX2xSmart Phone, HUAWEI, ATR-AL00xSmart Phone, HUAWEI, ATR-AL00axSmart Phone, HUAWEI, ATR-TL00xSmart Phone, HUAWEI, ATR-TL00axSmart Phone, HUAWEI, ATR-LX1xSmart Phone, HUAWEI, ATR-LX2xSmart Phone, HUAWEI, ATR-LX3xSmart Phone, HUAWEI, STK-LX1aSmart Phone, HUAWEI, STK-LX1Smart Phone, HUAWEI, STK-L21Smart Phone, HUAWEI, STK-L21aSmart Phone, HUAWEI, STK-L22Smart Phone, HUAWEI, STK-L22aSmart Phone, HUAWEI, STK-LX3Smart Phone, HUAWEI, STK-LX3aSmart Phone, HUAWEI, STK-AL00Smart Phone, HUAWEI, STK-AL00aSmart Phone, HUAWEI, STK-TL00Smart Phone, HUAWEI, STK-TL00aSmart Phone, HUAWEI, STK-L23BAKSmart Phone, HUAWEI, GLK-TL00Smart Phone, HUAWEI, GLK-AL00Smart Phone, HUAWEI, GLK-LX1UrSmart Phone, HUAWEI, GLK-LX1USmart Phone, HUAWEI, GLK-LX1VrSmart Phone, HUAWEI, GLK-LX2rSmart Phone, HUAWEI, GLK-LX2Smart Phone, HUAWEI, GLK-LX1rSmart Phone, HUAWEI, GLK-LX1Smart Phone, HUAWEI, GLK-LX3rSmart Phone, HUAWEI, GLK-LX3Smart Phone, HUAWEI, MAR-LX1AmSmart Phone, HUAWEI, MAR-LX2mSmart Phone, HUAWEI, MAR-LX1MmSmart Phone, HUAWEI, MAR-LX3AmSmart Phone, HUAWEI, HWV33Smart Phone, HUAWEI, MAR-LX2JmSmart Phone, HUAWEI, MAR-LX1ASmart Phone, HUAWEI, MAR-LX1MSmart Phone, HUAWEI, MAR-LX3ASmart Phone, HUAWEI, MAR-LX2JSmart Phone, HUAWEI, AQM-AL00TSmart Phone, HUAWEI, AQM-AL00TaSmart Phone, HUAWEI, AQM-AL00Smart Phone, HUAWEI, AQM-AL00aSmart Phone, HUAWEI, AQM-TL00Smart Phone, HUAWEI, AQM-TL00aSmart Phone, HUAWEI, AQM-LX1MEBaSmart Phone, HUAWEI, AQM-LX1MEBSmart Phone, HUAWEI, AQM-LX2Smart Phone, HUAWEI, AQM-LX2aSmart Phone, HUAWEI, AQM-LX1Smart Phone, HUAWEI, AQM-LX1AFSmart Phone, HUAWEI, AQM-LX1aSmart Phone, HUAWEI, AQM-LX1AFaSmart Phone, HUAWEI, AQM-LX3Smart Phone, HUAWEI, AQM-LX3aSmart Phone, HUAWEI, LRA-AL00aSmart Phone, HUAWEI, LRA-AL00Smart Phone, HUAWEI, LRA-TL00Smart Phone, HUAWEI, LRA-TL00aSmart Phone, HUAWEI, LRA-LX1TSmart Phone, HUAWEI, LRA-LX1Smart Phone, HUAWEI, LRA-LX1AFSmart Phone, HUAWEI, LRA-LX3Smart Phone, HUAWEI, LRA-LX2JSmart Phone, HUAWEI, LRA-LX1TaSmart Phone, HUAWEI, LRA-LX1aSmart Phone, HUAWEI, LRA-LX1AFaSmart Phone, HUAWEI, LRA-LX3aSmart Phone, HUAWEI, LRA-LX2JaSmart Phone, HUAWEI, LRA-LX2Smart Phone, HUAWEI, LRA-LX2aSmart Phone, HUAWEI, GLK-LX1VmSmart Phone, HUAWEI, GLK-LX1UmSmart Phone, HUAWEI, GLK-LX2mSmart Phone, HUAWEI, GLK-LX1mSmart Phone, HUAWEI, GLK-LX3mPlay, COR-TL10Smart Phone, HUAWEI, MAR-TL00mSmart Phone, HUAWEI, MAR-AL00mSmart Phone, HUAWEI, GLK-AL00mSmart Phone, HUAWEI, GLK-TL00mSmart Phone, HONOR, HRY-AL10TaSmart Phone, HONOR, HRY-AL10Smart Phone, HONOR, HRY-AL10TSmart Phone, HONOR, HRY-TL00aSmart Phone, HONOR, HRY-TL00TaSmart Phone, HONOR, HRY-LX2TSmart Phone, HONOR, HRY-LX3Smart Phone, HONOR, HRY-LX3TSmart Phone, HUAWEI, POT-AL10aSmart Phone, HUAWEI, POT-AL10Smart Phone, HUAWEI, POT-AL20aSmart Phone, HUAWEI, POT-AL20Smart Phone, HUAWEI, POT-TL10aSmart Phone, HUAWEI, POT-TL10Smart Phone, HUAWEI, POT-LX2Smart Phone, HUAWEI, POT-LX2TSmart Phone, HUAWEI, POT-LX3TSmart Phone, HONOR, JAT-AL00Smart Phone, HONOR, JAT-TL00Smart Phone, HONOR, JAT-L29Smart Phone, HONOR, JAT-LX1Smart Phone, HONOR, JAT-LX3Smart Phone, HONOR, JAT-L41Smart Phone, HONOR, JAT-L29XSmart Phone, HONOR, JAT-LX1XSmart Phone, HONOR, JAT-L41XSmart Phone, HONOR, JAT-AL00Smart Phone, HONOR, JAT-TL00Smart Phone, HONOR, JAT-L29Smart Phone, HONOR, JAT-LX1Smart Phone, HONOR, JAT-LX3Smart Phone, HONOR, JAT-L41Smart Phone, HONOR, JAT-L29XSmart Phone, HONOR, JAT-LX1XSmart Phone, HONOR, JAT-L41XSmart Phone, HUAWEI, MRD-LX2Smart Phone, HUAWEI, MRD-LX3Smart Phone, HUAWEI, MRD-LX1Smart Phone, HUAWEI, MRD-LX1NSmart Phone, HUAWEI, MRD-LX1FSmart Phone, HUAWEI, MRD-TL00Smart Phone, HUAWEI, MRD-AL00Smart Phone, HUAWEI, MRD-LX3XSmart Phone, HUAWEI, MRD-LX2XSmart Phone, HUAWEI, MRD-LX1XSmart Phone, HUAWEI, MRD-LX1FXSmart Phone, HUAWEI, MAR-TL00mSmart Phone, HUAWEI, MAR-AL00mSmart Phone, HUAWEI, GLK-AL00mSmart Phone, HUAWEI, GLK-TL00mSmart Phone, HUAWEI, GOG-AL00Smart Phone, HUAWEI, GOG-AL10Smart Phone, HUAWEI, GOG-TL00Smart Phone, HUAWEI, GOG-TL10Smart Phone, HUAWEI, GOG-TL10Smart Phone, HUAWEI, GOG-LX2Smart Phone, HUAWEI, GOG-LX2ASmart Phone, HUAWEI, GOG-LX2BSmart Phone, HUAWEI, GOG-LX1MSmart Phone, HUAWEI, GOG-LX1MASmart Phone, HUAWEI, GOG-LX1MBSmart Phone, HUAWEI, GOG-LX1Smart Phone, HUAWEI, GOG-LX1ASmart Phone, HUAWEI, GOG-LX1BSmart Phone, HUAWEI, GOG-LX3Smart Phone, HUAWEI, GOG-LX3ASmart Phone, HUAWEI, GOG-LX3BHUAWEI/HONOR, JAT-AL00HUAWEI/HONOR, JAT-TL00HUAWEI/HONOR, JAT-L29HUAWEI/HONOR, JAT-LX1HUAWEI/HONOR, JAT-LX3HUAWEI/HONOR, JAT-L41HUAWEI/HONOR, JAT-L29XHUAWEI/HONOR, JAT-LX1XHUAWEI/HONOR, JAT-L41XHUAWEI/HONOR, MRD-LX3HUAWEI/HONOR, MRD-LX2HUAWEI/HONOR, MRD-LX1HUAWEI/HONOR, MRD-LX1NHUAWEI/HONOR, MRD-LX1FHUAWEI/HONOR, MRD-TL00HUAWEI/HONOR, MRD-AL00HUAWEI/HONOR, MRD-LX3XHUAWEI/HONOR, MRD-LX2XHUAWEI/HONOR, MRD-LX1XHUAWEI/HONOR, MRD-LX1FXHUAWEI/HONOR, KSA-LX9HUAWEI/HONOR, KSA-LX9XHUAWEI/HONOR, KSA-LX2HUAWEI/HONOR, KSA-LX3HUAWEI/HONOR, KSA-AL00HUAWEI/HONOR, KSA-TL00HUAWEI/HONOR, AMN-LX9XHUAWEI/HONOR, AMN-LX9HUAWEI/HONOR, AMN-LX1HUAWEI/HONOR, AMN-LX2HUAWEI/HONOR, AMN-LX3HUAWEI/HONOR, AMN-LX3XHUAWEI/HONOR, MED-LX3HUAWEI/HONOR, MED-LX2HUAWEI/HONOR, MED-LX1HUAWEI/HONOR, MED-LX1NHUAWEI/HONOR, MED-LX1FHUAWEI/HONOR, MED-TL00HUAWEI/HONOR, MED-AL00HUAWEI/HONOR, MOA-TL00HUAWEI/HONOR, MOA-AL00HUAWEI/HONOR, MOA-L29HUAWEI/HONOR, MOA-LX1HUAWEI/HONOR, MOA-LX3HUAWEI/HONOR, MOA-L41HUAWEI/HONOR, PKA-AL00HUAWEI/HONOR, PKA-TL00HUAWEI/HONOR, PKA-LX1HUAWEI/HONOR, PKA-LX2HUAWEI/HONOR, PKA-LX3HUAWEI/HONOR, PKA-LX9HUAWEI/HONOR, KEM-AL00HUAWEI/HONOR, KEM-TL00HUAWEI/HONOR, KEM-LX1HUAWEI/HONOR, KEM-LX2HUAWEI/HONOR, KEM-LX3HUAWEI/HONOR, KEM-LX9HUAWEI/HONOR, PEK-AL00HUAWEI/HONOR, PEK-AL10HUAWEI/HONOR, PEK-AL00aHUAWEI/HONOR, PEK-AL10aHUAWEI/HONOR, MKY-LX3HUAWEI/HONOR, JGA-AL00HUAWEI/HONOR, MKY-LX2HUAWEI/HONOR, MKY-LX1HUAWEI/HONOR, MKY-LX1NHUAWEI/HONOR, MKY-LX1FHUAWEI/HONOR, MKY-TL00HUAWEI/HONOR, MKY-AL00HUAWEI/HONOR, LPD-TL00HUAWEI/HONOR, LPD-AL00HUAWEI/HONOR, LPD-L29HUAWEI/HONOR, LPD-LX1HUAWEI/HONOR, LPD-LX3HUAWEI/HONOR, MNE-TL00HUAWEI/HONOR, MNE-AL00HUAWEI/HONOR, MNE-L29HUAWEI/HONOR, KNA-AL00HUAWEI/HONOR, KNA-TL00HUAWEI/HONOR, KNA-LX1HUAWEI/HONOR, KNA-LX2HUAWEI/HONOR, KNA-LX3HUAWEI/HONOR, KNA-LX9HUAWEI/HONOR, JGA-LX3HUAWEI/HONOR, JGA-LX2HUAWEI/HONOR, JGA-LX1HUAWEI/HONOR, JGA-LX1NHUAWEI/HONOR, JGA-LX1FHUAWEI/HONOR, JGA-TL00HUAWEI/HONOR, LPD-L41HUAWEI/HONOR, MNE-LX1HUAWEI/HONOR, MNE-LX3HUAWEI/HONOR, MNE-L41HUAWEI/HONOR, JDN2-L59HUAWEI/HONOR, JDN2-W59HNHUAWEI/HONOR, JDN2-AL50HNHUAWEI/HONOR, JDN2-AL50HUAWEI/HONOR, JDN2-W59HUAWEI/HONOR, WS8200HUAWEI/HONOR, WS8100HUAWEI/HONOR, WS8300HUAWEI/HONOR, WS8400HUAWEI/HONOR, WS8500HUAWEI/HONOR, WS8600HUAWEI/HONOR, WS8700HUAWEI/HONOR, WS8800HUAWEI/HONOR, WS8900HUAWEI/HONOR, WS8200HUAWEI/HONOR, WS8100HUAWEI/HONOR, WS8300HUAWEI/HONOR, WS8400HUAWEI/HONOR, WS8500HUAWEI/HONOR, WS8600HUAWEI/HONOR, WS8700HUAWEI/HONOR, WS8800HUAWEI/HONOR, WS8900HUAWEI/HONOR, MED-LX2HUAWEI/HONOR, MED-LX3HUAWEI/HONOR, MED-LX1HUAWEI/HONOR, MED-LX1NHUAWEI/HONOR, MED-LX1FHUAWEI/HONOR, MED-TL00HUAWEI/HONOR, MED-AL00HUAWEI/HONOR, MOA-TL00HUAWEI/HONOR, MOA-AL00HUAWEI/HONOR, MOA-L29HUAWEI/HONOR, MOA-LX1HUAWEI/HONOR, MOA-LX3HUAWEI/HONOR, MOA-L41HUAWEI/HONOR, PKA-AL00HUAWEI/HONOR, PKA-TL00HUAWEI/HONOR, PKA-LX1HUAWEI/HONOR, PKA-LX2HUAWEI/HONOR, PKA-LX3HUAWEI/HONOR, PKA-LX9HUAWEI/HONOR, KEM-AL00HUAWEI/HONOR, KEM-TL00HUAWEI/HONOR, KEM-LX1HUAWEI/HONOR, KEM-LX2HUAWEI/HONOR, KEM-LX3HUAWEI/HONOR, KEM-LX9HUAWEI/HONOR, PEK-AL00HUAWEI/HONOR, PEK-AL10HUAWEI/HONOR, PEK-AL00aHUAWEI/HONOR, PEK-AL10aHUAWEI/HONOR, KNA-AL00HUAWEI/HONOR, KNA-TL00HUAWEI/HONOR, KNA-LX1HUAWEI/HONOR, KNA-LX2HUAWEI/HONOR, KNA-LX3HUAWEI/HONOR, KNA-LX9HUAWEI/HONOR, GOG-AL10HUAWEI/HONOR, GOG-AL00HUAWEI/HONOR, GOG-TL00HUAWEI/HONOR, GOG-TL10HUAWEI/HONOR, GOG-LX2HUAWEI/HONOR, GOG-LX2AHUAWEI/HONOR, GOG-LX2BHUAWEI/HONOR, GOG-LX1MHUAWEI/HONOR, GOG-LX1MAHUAWEI/HONOR, GOG-LX1MBHUAWEI/HONOR, GOG-LX1HUAWEI/HONOR, GOG-LX1AHUAWEI/HONOR, GOG-LX1BHUAWEI/HONOR, GOG-LX3HUAWEI/HONOR, GOG-LX3AHUAWEI/HONOR, GOG-LX3BHUAWEI/HONOR, AQM- L41AHUAWEI/HONOR, MRD-LX1NXHUAWEI/HONOR, JAT-LX3XHUAWEI/HONOR, MED-LX9HUAWEI/HONOR, MOA-LX2HUAWEI/HONOR, MOA-LX9HUAWEI/HONOR, JGA-LX9HUAWEI/HONOR, MKY-LX9HUAWEI/HONOR, LPD-LX2HUAWEI/HONOR, LPD-LX9HUAWEI/HONOR, MNE-LX2HUAWEI/HONOR, MNE-LX9HUAWEI/HONOR, JFN-AN00HUAWEI/HONOR, JFN-AN10HUAWEI/HONOR, JFN-NX1HUAWEI/HONOR, JFN-NX2HUAWEI/HONOR, JFN-NX3HUAWEI/HONOR, JFN-AL00HUAWEI/HONOR, JFN-TL00HUAWEI/HONOR, JFN-LX1HUAWEI/HONOR, JFN-LX2HUAWEI/HONOR, JFN-LX3HUAWEI/HONOR, AQM-LX3aHUAWEI/HONOR, AQM-TL00aHUAWEI/HONOR, AQM-L62JHUAWEI/HONOR, AQM-AL00HUAWEI/HONOR, AQM-AL00aHUAWEI/HONOR, AQM-AL10HUAWEI/HONOR, AQM-AL10aHUAWEI/HONOR, AQM-AL20aHUAWEI/HONOR, AQM-AL20HUAWEI/HONOR, AQM-TL00HUAWEI/HONOR, AQM-TL00aHUAWEI/HONOR, AQM-TL10HUAWEI/HONOR, AQM-LX1HUAWEI/HONOR, AQM-LX1THUAWEI/HONOR, AQM-LX1AFHUAWEI/HONOR, AQM-L41AHUAWEI/HONOR, AQM-LX1BHUAWEI/HONOR, AQM-LX3HUAWEI/HONOR, AQM-LX1MEHUAWEI/HONOR, AQM-LX2HUAWEI/HONOR, AQM-LX2JHUAWEI/HONOR, AQM-LX62JHUAWEI/HONOR, AQM-LX3THUAWEI/HONOR, LRA-TL00aHUAWEI/HONOR, LRA-LX3TaHUAWEI/HONOR, LRA-AL00HUAWEI/HONOR, LRA-AL00aHUAWEI/HONOR, LRA-AL10HUAWEI/HONOR, LRA-AL10aHUAWEI/HONOR, LRA-TL00HUAWEI/HONOR, LRA-TL10HUAWEI/HONOR, LRA-TL10aHUAWEI/HONOR, LRA-AL20HUAWEI/HONOR, LRA-AL20aHUAWEI/HONOR, LRA-LX1HUAWEI/HONOR, LRA-LX1MEHUAWEI/HONOR, LRA-LX2HUAWEI/HONOR, LRA-LX2MEHUAWEI/HONOR, LRA-LX1THUAWEI/HONOR, LRA-LX2THUAWEI/HONOR, LRA-LX3THuawei / Honor , CV52Huawei / Honor, CV51Huawei / Honor , CV53Huawei / Honor , CV54Huawei / Honor, CV55Huawei / Honor , CV56HUAWEI/HONOR, JNY-AL10HUAWEI/HONOR, JNY-AL00HUAWEI/HONOR, JNY-TL00HUAWEI/HONOR, JNY-TL10HUAWEI/HONOR, JNY-LX2HUAWEI/HONOR, JNY-LX2AHUAWEI/HONOR, JNY-LX2BHUAWEI/HONOR, JNY-LX1MHUAWEI/HONOR, JNY-LX1MAHUAWEI/HONOR, JNY-LX1MBHUAWEI/HONOR, JNY-LX1HUAWEI/HONOR, JNY-LX1AHUAWEI/HONOR, JNY-LX1BHUAWEI/HONOR, JNY-LX3HUAWEI/HONOR, JNY-LX3AHUAWEI/HONOR, JNY-LX3BHUAWEI/HONOR, JNY-LX2JHUAWEI/HONOR, JNY-LX2JAHUAWEI/HONOR, JNY-LX2JBHUAWEI/HONOR, MAS-AL00HUAWEI/HONOR, MAS-AL10HUAWEI/HONOR, MAS-TL00HUAWEI/HONOR, MAS-TL10HUAWEI/HONOR, LRA-L41ATHUAWEI/HONOR, LRA-L41THUAWEI/HONOR, LRA-LX1BHUAWEI/HONOR, LRA-LX1BTHUAWEI/HONOR, LRA-LX3HUAWEI/HONOR, LRA-LX2JHUAWEI/HONOR, LRA-L62JHUAWEI/HONOR, MED-TL20HUAWEI/HONOR, MED-AL20HUAWEI/HONOR, MOA-TL20HUAWEI/HONOR, MOA-AL20HUAWEI/HONOR, JGA-TL20HUAWEI/HONOR, JGA-AL20HUAWEI/HONOR, MKY-TL20HUAWEI/HONOR, MKY-AL20HUAWEI/HONOR, LPD-TL20HUAWEI/HONOR, LPD-AL20HUAWEI/HONOR, MNE-TL20HUAWEI/HONOR, MNE-AL20HUAWEI/HONOR, MED-AL10HUAWEI/HONOR , MED-TL10HUAWEI/HONOR, MOA-TL10HUAWEI/HONOR, MOA-AL10HUAWEI/HONOR, PKA-AL20HUAWEI/HONOR, PKA-AL10HUAWEI/HONOR, PKA-TL10HUAWEI/HONOR, PKA-TL20HUAWEI/HONOR, KEM-AL20HUAWEI/HONOR, KEM-AL10HUAWEI/HONOR, KEM-TL10HUAWEI/HONOR, KEM-TL20HUAWEI/HONOR, PEK-AL20HUAWEI/HONOR, KNA-AL20HUAWEI/HONOR, KNA-AL10HUAWEI/HONOR, KNA-TL10HUAWEI/HONOR, KNA-TL20HUAWEI/HONOR, MKY-TL10HUAWEI/HONOR, JGA-TL10HUAWEI/HONOR, LPD-TL10HUAWEI/HONOR, OVL-TL10Smart Phone, HUAWEI/HONOR, BKK-AL30Smart Phone, HUAWEI/HONOR, BKK-AL20Smart Phone, HUAWEI/HONOR, DUB-AL10Smart Phone, HUAWEI/HONOR, DUB-AL10aSmart Phone, HUAWEI/HONOR, DUB-AL30HUAWEI/HONOR, AQM-LX1BTHUAWEI/HONOR, AQM-L41ATHUAWEI/HONOR, AQM-LX1METHUAWEI/HONOR, AQM-LX2THUAWEI/HONOR(1), LRA-L41AHUAWEI/HONOR, AMN-TL00HUAWEI/HONOR, AMN-AL00HUAWEI/HONOR, AMN-AL10HUAWEI/HONOR, KSA-AL10HUAWEI/HONOR, AMN-TL10HUAWEI/HONOR Smart Phone, MAR-LX1BHUAWEI/HONOR Smart Phone, MAR-LX2BHUAWEI/HONOR Smart Phone, MAR-LX3BmHUAWEI/HONOR Smart Phone, POT-AL10NOVA Smart Phone, MAR-LX1HHUAWEI/HONOR Smart Phone , JGA-AL30HUAWEI/HONOR Smart Phone, JGA-TL30HUAWEI/HONOR Smart Phone , JGA-AL10HUAWEI/HONOR Smart Phone , JGA-L41HUAWEI/HONOR Smart Phone , MKY-TL30HUAWEI/HONOR Smart Phone , MKY-AL30HUAWEI/HONOR Smart Phone , MKY-AL10HUAWEI/HONOR Smart Phone , MKY-L41HUAWEI/HONOR Smart Phone , LPD-TL30HUAWEI/HONOR Smart Phone , LPD-AL30HUAWEI/HONOR Smart Phone, LPD-AL10HUAWEI/HONOR Smart Phone , MNE-TL30HUAWEI/HONOR Smart Phone , MNE-AL30HUAWEI/HONOR Smart Phone , MNE-TL10HUAWEI/HONOR Smart Phone , MNE-AL10|
|HUAWEI_DUB_LX2|Android_SDK:_27_(8.1.0)|104653 - Controller Subsystem101927 - Host Subsystem96540 - Profile Subsystem104712 - Profile Subsystem|LDN-L01, LDN-L01LDN-L21, LDN-L21LDN-LX2, LDN-LX2LDN-LX3, LDN-LX3LDN-TL10, LDN-TL10LND-AL30, LND-AL30LND-AL40, LND-AL40LND-L29, LND-L29LND-TL30, LND-TL30LND-AL50, LND-AL50LND-TL40, LND-TL40LDN-AL10, LDN-AL10LND-TL50, LND-TL50LDN-AL00, LDN-AL00LDN-AL20, LDN-AL20LDN-TL00, LDN-TL00LDN-TL20, LDN-TL20AUM-AL20, AUM-AL20AUM-AL00, AUM-AL00AUM-TL00, AUM-TL00AUM-TL20, AUM-TL20ATU-AL10, ATU-AL10ATU-TL10, ATU-TL10ATU-L11, ATU-L11ATU-L21, ATU-L21ATU-L31, ATU-L31ATU-L22, ATU-L22ATU-L42, ATU-L42ATU-LX3, ATU-LX3AUM-L29, AUM-L29AUM-L41, AUM-L41AUM-L33, AUM-L33Smart Phone, HONOR, BKK-AL10Smart Phone, HONOR, BKK-AL00Smart Phone, HONOR, BKK-TL00Smart Phone, HONOR, BKK-L21Smart Phone, HUAWEI, DUB-AL00Smart Phone, HUAWEI, DUB-AL20Smart Phone, HUAWEI, DUB-TL00Smart Phone, HUAWEI, DUB-TL20Smart Phone, HUAWEI, DUB-LX1Smart Phone, HUAWEI, DUB-LX2Smart Phone, HUAWEI, DUB-LX3Smart Phone, HONOR, BKK-LX2Smart Phone, HUAWEI, DUB-TL00aSmart Phone, HUAWEI, DUB-AL00aSmart Phone, HONOR, BKK-AL20Smart Phone, HUAWEI, DUB-AL10aSmart Phone, HUAWEI, DUB-AL10Smart Phone, HUAWEI/HONOR, DUB-AL30Smart Phone, HUAWEI/HONOR, BKK-AL30|
|LGE_LG-H818|Android_SDK:_23_(6.0)|66928 - End Product|LG-PFMLG-VS986LG-F500LLG-F500SLG-F500KLGLS991LG-US991LG-H818LG-PFM_SubsetLG-H815PLG-H815ARLG-H815TRLG-H815LLG-H815KLG-H818NLG-H818PLG-H815LG-VS986WLG-AS986LG-AS991LG-H819LG-H815TLG-VS986BLG-VS986LDLG-VS986LELG-H815PX|
|Xiaomi_Mi_10_Pro|Android_SDK:_29_(10)|146349 - End Product|Mi 10, M2001J2GMi 10, M2001J2EMi 10, M2001J2CMi 10, M2001J2IMi 10 Pro, M2001J1EMi 10 Pro, M2001J1CMi 10 Pro, M2001J1GMi 10 Ultra, M2007J1SC|
|Nexus 5|Android_SDK:_23_(6.0.1)|Not Available to Silicon Labs| |
|OPPO_CPH1923|Android_SDK:_28_(9)|Not Available to Silicon Labs| |
|OPPO_CPH1912|Android_SDK:_27_(8.1.0)|128457 - End Product|OPPO Mobile Phone, CPH1920AX5s, CPH1920A5s, CPH1910A5s, CPH1909A5s, CPH1912A7n, PCDT00A7n, PCDM00A9, PCAT10A9, PCAM10A9x, PCET00A9x, PCEM00F11, CPH1911F11, CPH1913F11, CPH1915F11, CPH1916|
|OppO_CPH1905|Android_SDK:_27_(8.1.0)|119078 - End Product|OPPO Mobile Phone, CPH1903A7, CPH1901AX7 A7, CPH1903A7, PBFT00A7, PBFM00A7, CPH1905|
|OPPO_CPH1987|Android_SDK:_28_(9)|Not Available to Silicon Labs|0|
|OPPO_CPH1917|Android_SDK:_29_(10)|128024 - End Product|OPPO Mobile Phone , CPH1917Reno, PCAM00Reno, CPH1917Reno, PCAT00K3, PCGM00K3, CPH1955K3, PCGT00|
|HUAWEI_ELS_NX9|Android_SDK:_29_(10)|138868 - Host Subsystem137431 - Controller Subsystem140076 - Profile Subsystem|[https://launchstudio.bluetooth.com/ListingDetails/96444](https://launchstudio.bluetooth.com/ListingDetails/96444)|
|Xiaomi_Redmi_5_Plus|Android_SDK:_27_(8.1.0)|107188 - Controller Subsystem86918 - Host Subsystem|XiaoMi Redmi 5 Plus, MEG7XiaoMi Redmi 5 Plus, MEE7XiaoMi Redmi 5 Plus, MET7|
|Xiaomi_Redmi_6_Pro|Android_SDK:_27_(8.1.0)|112808 - End Product|Redmi Note 5, M1803E7SGRedmi Note 5, M1803E7SHRedmi Note 6 Pro, M1806E7THRedmi Note 6 Pro, M1806E7TG|
|Xiaomi_Redmi_7|Android_SDK:_28_(9)|127108 - End Product|Xiaomi Redmi 7, M1810F6LGXiaomi Redmi 7, M1810F6LHXiaomi Redmi 7, M1810F6G|
|Xiaomi_Redmi_K20_Pro_Premium_Edition|Android_SDK:_29_(10)|134727 - Controller Subsystem114535 - Host Subsystem|MI 9T Pro, M1903F11G|
|Xiaomi_Redmi_K30_Pro|Android_SDK:_29_(10)|147004 - End Product|POCO F2 Pro, M2004J11GRedmi K30 Pro 5G, M2001J11ERedmi K30 Pro 5G/Redmi K30 Pro 5G Zoom Edition, M2001J11IRedmi K30 Pro 5G, M2001J11C|
|Xiaomi_Redmi_Note_8|Android_SDK:_28_(9)|137555 - End Product|Redmi Note8, M1908C3JGRedmi Note8, M1908C3JH|
|Xiaomi_Redmi_Note_5|Android_SDK:_28_(9)|112808 - End Product|Redmi Note 5, M1803E7SGRedmi Note 5, M1803E7SHRedmi Note 6 Pro, M1806E7THRedmi Note 6 Pro, M1806E7TG|
|Samsung_SM-G988B|Android_SDK:_29_(10)|158725 - End Product156360 - Profile Subsystem156361 - Profile Subsystem156364 - Profile Subsystem156367 - Profile Subsystem156366 - Profile Subsystem156362 - Profile Subsystem156363 - Profile Subsystem|Galaxy S20 Ultra 5G, SM-G988B_DS|
|Samsung_SM-A105G|Android_SDK:_29_(10)|126589 - Host Subsystem100088 - Controller Subsystem124964 - Profile Subsystem|Galaxy A10, SM-A105FGalaxy A10, SM-A105F_DSGalaxy A10, SM-A105M_DSGalaxy A10, SM-A105G_DSGalaxy A10, SM-A105GGalaxy A10, SM-A105MGalaxy A10, SM-A105NGalaxy A10, SM-A105FN_DS|
|Samsung_SM-A107F|Android_SDK:_28_(9)|135247 - End Product|Galaxy A10s, SM-A107F_DSGalaxy A10s, SM-A107M_DSGalaxy A10s, SM-A107FGalaxy A10s, SM-A107MGalaxy M01s, SM-M017F_DS|
|Samsung_SM-A305F|Android_SDK:_28_(9)|123890 - Host Subsystem100088 - Controller Subsystem124964 - Profile Subsystem|Galaxy-A30, SM-A305FGalaxy-A30, SM-A305GGalaxy-A30, SM-A305GNGalaxy-A30, SM-A305NGalaxy-A30, SM-A305F_DSGalaxy-A30, SM-A305FN_DSGalaxy-A30, SM-A305GN_DSGalaxy-A30, SM-A305GT_DSGalaxy-A30, SM-A305G_DSGalaxy-A30, SM-A305FNGalaxy-A30, SM-A305YN|
|Samsung_SM-A505F|Android_SDK:_28_(9)|123895 - End Product124964 - Profile Subsystem|Galaxy-A50 , SM-A505FNGalaxy-A50, SM-A505GT_DSGalaxy-A50, SM-A505GN_DSGalaxy-A50, SM-A505G_DSGalaxy-A50, SM-A505FN_DSGalaxy-A50, SM-A505FM_DSGalaxy-A50, SM-A505F_DSGalaxy-A50, SM-A505GGalaxy-A50, SM-A505XGalaxy-A50, SM-A505GNGalaxy-A50, SM-A505FGalaxy-A50, SM-A505UGalaxy-A50, SM-A505FNGalaxy-A50, SM-A505YNGalaxy-A50, SM-A505WGalaxy-A50, SM-A505NGalaxy-A50, SM-S506DLGalaxy-A50, SM-A505U1|
|SM-A515F|Android_SDK:_29_(10)|141913 - End Product141230 - Profile Subsystem141221 - Profile Subsystem124964 - Profile Subsystem141223 - Profile Subsystem141224 - Profile Subsystem141225 - Profile Subsystem141226 - Profile Subsystem141234 - Profile Subsystem141232 - Profile Subsystem141233 - Profile Subsystem|Galaxy-A51, SM-A515F_NGalaxy-A51, SM-A515FGalaxy-A51, SM-A515F_DSGalaxy-A51, SM-A515F_DSMGalaxy-A51, SM-A515F_DSNGalaxy-A51, SM-A515F_DSTGalaxy-A51, SM-A515X|
|Samsung_SM-A605G|Android_SDK:_26_(8.0.0)|110962 - End Product|Galaxy-A6-Plus , SM-A605FNGalaxy-A6-Plus , SM-A605FN_DSGalaxy-A6-Plus, SM-A605F_DSGalaxy-A6-Plus, SM-A605G_DSGalaxy-A6-Plus, SM-A605GN_DSGalaxy-A6-Plus, SM-A6050Galaxy-A6-Plus, SM-A6058Galaxy-A6-Plus, SM-A605GGalaxy-A6-Plus, SM-A605FGalaxy-A6-Plus, SM-A605GNGalaxy-A6-Plus, SM-A605XGalaxy-A6-Plus, SM-A605XCGalaxy-A6-Plus, SM-A605FNGalaxy-A6-Plus , SM-A605K|
|Samsung_SM-A750GN|Android_SDK:_26_(8.0.0)|117674 - Host Subsystem100088 - Controller Subsystem|Galaxy A7 2018, SM-A750FNGalaxy A7 2018, SM-A750NGalaxy-A7-2018, SM-A750F_DSGalaxy-A7-2018, SM-A750FN_DSGalaxy-A7-2018, SM-A750G_DSGalaxy-A7-2018, SM-A750GN_DSGalaxy-A7-2018, SM-A750GNGalaxy-A7-2018, SM-A750GGalaxy-A7-2018, SM-A750FGalaxy-A7-2018, SM-A750X|
|Samsung_SM-A705F|Android_SDK:_28_(9)|126131 - End Product124964 - Profile Subsystem|Galaxy-A70 , SM-A705FNGalaxy-A70, SM-A705GMGalaxy-A70, SM-A705FN_DSMGalaxy-A70, SM-A705XGalaxy-A70, SM-A7050Galaxy-A70, SM-A705FN_DSGalaxy-A70, SM-A705XCGalaxy-A70, SM-A705WGalaxy-A70, SM-A705MNGalaxy-A70, SM-A705FGalaxy-A70, SM-A705F_DSGalaxy-A70, SM-A705MN_DSGalaxy-A70, SM-A705GM_DSGalaxy-A70, SM-A705YN|
|Samsung_SM-A805F|Android_SDK:_28_(9)|129305 - End Product124964 - Profile Subsystem|Samsung Mobile Phone, SM-A805FGalaxy A80, SM-A805F_DSGalaxy A80, SM-A805FGalaxy A80, SM-A805F_DSMGalaxy A80, SM-A805NGalaxy A80, SM-A805XGalaxy A80, SM-A805XCGalaxy A80, SM-A8050|
|Samsung_SM-A920F|Android_SDK:_29_(10)|124417 - End Product124964 - Profile Subsystem|Galaxy A9 2018, SM-A920FGalaxy A9 2018, SM-A920NGalaxy A9 2018, SM-A920F_DS|
|Samsung_SM-J510FN|Android_SDK:_25_(7.1.1)|100952 - End Product|SM-J510FN, SM-J510FNSM-J510H_DS, SM-J510H_DSGalaxy-J5, SM-J510H_DSGalaxy-J5, SM-J510FN|
|Samsung_SM-J710F|Android_SDK:_23_(6.0.1)|100611 - End Product|SM-J710FN, SM-J710FNSM-J710MN, SM-J710MNSM-J710F_DS, SM-J710F_DSSM-J710F, SM-J710FSM-J710FQ, SM-J710FQSM-J710FN_DS, SM-J710FN_DSSM-J710GN, SM-J710GNSM-J710K, SM-J710K|
|Samsung_SM-M205G|Android_SDK:_28_(9)|121921 - Host Subsystem100088 - Controller Subsystem|Galaxy-M20, SM-M205FGalaxy-M20, SM-M205F_DSGalaxy-M20, SM-M205FN_DSGalaxy-M20, SM-M205G_DSGalaxy-M20, SM-M205M_DSGalaxy-M20, SM-M205M|
|Samsung_SM-N950F|Android_SDK:_28_(9)|124394 - End Product124964 - Profile Subsystem|Galaxy Note 8, SM-N950F|
|Samsung_SM-N960F|Android_SDK:_29_(10)|123909 - Profile Subsystem116457 - End Product|Samsung Mobile Phone , SM-N960F|
|Samsung_SM-G975F|Android_SDK:_29_(10)|121766 - End Product|Samsung Mobile Phone , SM-G405F_DSSamsung Mobile Phone, SM-G405XSamsung Mobile Phone, SM-G405FSamsung Mobile Phone, SM-G405XNSamsung Mobile Phone, SM-G405NGalaxy S10+, SM-G975XGalaxy S10+, SM-G975F_DSGalaxy S10+, SM-G975FGalaxy S10+, SM-G975XNGalaxy S10+, SM-G975N|
|SM-G970F|Android_SDK:_29_(10)|122960 - End Product|Samsung Mobile Phone, SM-G400FSamsung Mobile Phone, SM-G400NSamsung Mobile Phone, SM-G400XNSamsung Mobile Phone, SM-G400XSamsung Mobile Phone, SM-G400F_DSGalaxy S10e, SM-G970NGalaxy S10e, SM-G970FGalaxy S10e, SM-G970XNGalaxy S10e, SM-G970XGalaxy S10e, SM-G970F_DS|
|Samsung_SM-G930F|Android_SDK:_26_(8.0.0)|110193 - End Product|Samsung Galaxy S7, SM-G930FSamsung Galaxy S7, SM-G930LSamsung Galaxy S7, SM-G930SSamsung Galaxy S7, SM-G930KSamsung Galaxy S7, SM-G930W8|
|Samsung_SM-G935F|Android_SDK:_26_(8.0.0)|110511 - End Product|Galaxy S7 Edge, SM-G935FGalaxy S7 Edge, SM-G935KGalaxy S7 Edge, SM-G935LGalaxy S7 Edge, SM-G935SGalaxy S7 Edge, SM-G935W8|
|Samsung_SM-G950F|Android_SDK:_26_(8.0.0)|123982 - End Product|Galaxy S8, SM-G950F|
|Samsung_SM-G955F|Android_SDK:_26_(8.0.0)|124224 - End Product|Galaxy S8+, SM-G955F|
|LGE_VS995|Android_SDK:_24_(7.0)|85177 - End Product|LG-VS995, LG-VS995LG-H910, LG-H910LG-LS997, LG-LS997LG-H990T, LG-H990TLG-H910PR, LG-H910PRLG-H915, LG-H915LG-US996, LG-US996LG-H918, LG-H918LG-VS995S, LG-VS995SLG V20, LG-H910|
|LGE_LG-H931|Android_SDK:_28_(9)|96522 - End Product|LG-VS996, LG-VS996LG-AS998, LG-AS998LG-US998, LG-US998LG-H931, LG-H931LG-LS998, LG-LS998LG-H933, LG-H933LGM-V300L, LGM-V300LLGM-V300S, LGM-V300SLGM-V300K, LGM-V300KLG-H930, LG-H930LG-H930DS, LG-H930DSLG-H930K, LG-H930KLG-H930G, LG-H930GLG-H932, LG-H932LG-H932PR, LG-H932PRLG-H930D, LG-H930DLG V30, LG-H931|
|Xiaomi_MI_9|Android_SDK:_28_(9)|123912 - End Product|XiaoMi MI 9, M1902F1G|
|Xiaomi_Mi_9T|Android_SDK:_29_(10)|130653 - Controller Subsystem114535 - Host Subsystem|MI 9T, M1903F10G|
|Xiaomi_Mi_A2_Lite|Android_SDK:_27_(8.1.0)|116717 - End Product|Xiaomi MI A2 LITE, M1805D1SG|
|Xiaomi_MI_6|Android_SDK:_28_(9)|98293 - End Product|Xiaomi Mi 6, MCE16Xiaomi Mi 6, MCT1Xiaomi MIX 2, MDE5Xiaomi MIX 2, MDT5Xiaomi Note 3, MCE8Xiaomi Note 3, MCT8|
|Xiaomi_MI_6X|Android_SDK:_27_(8.1.0)|116110 - End Product|Xiaomi MI A2, M1804D2SG|
|Xiaomi_MI_8|Android_SDK:_28_(9)|115812 - End Product|MI MIX2S, M1803D5XAMI 8, M1803E1APOCOPHONE F1, M1805E10A|
|Xiaomi_Mi9_Pro_5G|Android_SDK:_28_(9)|146631 - End Product|Redmi Note 9S, M2003J6A1GRedmi Note 9S, M2003J6A1RRedmi Note 9 Pro, M2003J6A1IRedmi Note 9 Pro Max, M2003J6B1IRedmi Note 9 Pro, M2003J6B2GPOCO M2 Pro, M2003J6CI|
|Xiaomi_MI_9_SE|Android_SDK:_28_(9)|127288 - Controller Subsystem114535 - Host Sybsystem|MI 9 SE, M1903F2G|
|Xiaomi_MI_MAX_3|Android_SDK:_27_(8.1.0)|116759 - End Product|MI MAX3, M1804E4AMI 8 Lite, M1808D2TG|
|Xiaomi_MI_8_Lite|Android_SDK:_27_(8.1.0)|116759 - End Product|MI MAX3, M1804E4AMI 8 Lite, M1808D2TG|
|Xiaomi_Mi_A2|Android_SDK:_28_(9)|116110 - End Product|Xiaomi MI A2, M1804D2SG|
|Xiaomi_Mi_A3|Android_SDK:_29_(10)|136133 - End Product|Xiaomi Mi A3, M1906F9SH|
|Xiaomi_Mi_MIX_3_5G|Android_SDK:_28_(9)|121613 - End Product|Xiaomi MIX3, M1810E5A|
|Xiaomi_MIX_2S|Android_SDK:_28_(9)|115812 - End Product|MI MIX2S, M1803D5XAMI 8, M1803E1APOCOPHONE F1, M1805E10A|
|Xiaomi_Redmi_7A|Android_SDK:_28_(9)|134589 - End Product|Xiaomi Redmi 7A, M1903C3EGXiaomi Redmi 7A, M1903C3EH|
|Redmi Note 7|Android_SDK:_29_(10)|123919 - End Product|Redmi Note7, M1901F7GRedmi Note7, M1901F7H|
|iPhone 8 Plus|iOS 14.2|99179 - Host Subsystem96809 - Controller Subsystem62504 - Profile Subsystem|iPhone 8, A1863Apple TV 4K, A1842iPhone 8, A1905iPhone 8, A1906iPhone 8 Plus, A1864iPhone X, A1865iPhone 8 Plus, A1897iPhone X, A1901iPhone 8 Plus, A1898iPhone X, A1902iPhone 8, A1907iPhone 8 Plus, A1899iPhone X, A1903HomePod, A1639|
|iPhone 5S|iOS 12.4.8|Not Available to Silicon Labs|0|
|iPhone 6|iOS 12.4.8|48083 - Profile Subsystem59997 - Controller Subsystem53915 - Host Subsystem|A1586, A1549, A1589|
|iPhone X|IOS 13.6.1|99179 - Host Subsystem96809 - Controller Subsystem62504 - Profile Subsystem|iPhone 8, A1863Apple TV 4K, A1842iPhone 8, A1905iPhone 8, A1906iPhone 8 Plus, A1864iPhone X, A1865iPhone 8 Plus, A1897iPhone X, A1901iPhone 8 Plus, A1898iPhone X, A1902iPhone 8, A1907iPhone 8 Plus, A1899iPhone X, A1903HomePod, A1639|
|iPhone 7 Plus|iOS 14.2|64104 - Host Subsystem62504 - Profile Subsystem86656 - Controller Subsystem|iPhone 7 Plus, A1661iPhone 7 Plus, A1785iPhone 7 Plus, A1786iPhone 7 Plus, A1784|
|iPhone  Xs|IOS 13.5.1|115456 - Controller Subsystem102170 - Profile Subsystem99179 - Host Subsystem|iPhone, A1921 A2101 A2102 A2104 A2103iPhone XR, A1984 A2105 A2106 A2108 A2107iPhone Xs, A1920 A2097 A2098 A2100 A2099iPhone Xs Max, A1921 A2101 A2102 A2104 A2103iPad Pro 11", A1980 A2013 A1934 A1979iPad Pro 12.9", A1876 A2014 A1895 A1893iPad mini, A2133 A2126 A2124 A2125iPad, A2152 A2153 A2123 A2154iPad mini 5, A2133 A2126 A2124 A2125iPad Air (3rd generation), A2152 A2153 A2123 A2154|
|iPhone 8|iOS 13.5.1|99179 - Host Subsystem96809 - Controller Subsystem62504 - Profile Subsystem|iPhone 8, A1863Apple TV 4K, A1842iPhone 8, A1905iPhone 8, A1906iPhone 8 Plus, A1864iPhone X, A1865iPhone 8 Plus, A1897iPhone X, A1901iPhone 8 Plus, A1898iPhone X, A1902iPhone 8, A1907iPhone 8 Plus, A1899iPhone X, A1903HomePod, A1639|
|iPhone 6 Plus|iOS 12.4.8|Not Available to Silicon Labs| |
|iPhone 7|iOS 13.7|64104 - Host Subsystem62504 - Profile Subsystem86655 - Controller Subsystem|iPhone 7, A1660iPhone 7, A1779iPhone 7, A1780iPhone 7, A1778|
|iPhone 6S|iOS 13.7|Not Available to Silicon Labs| |
|iPhone SE (2nd generation)|iOS 13.5.1|Not Available to Silicon Labs| |
|iPhone 11 Pro|iOS 14.2|136497 - Controller Subsystem137333 - Profile Subsystem137332 - Host Subsystem|iPhone 11 Pro, A2160iPhone 11 Pro Max, A2161iPhone 11 Pro, A2217iPhone 11 Pro, A2215iPhone 11 Pro, A2216iPhone 11 Pro Max, A2218iPhone 11 Pro Max, A2220iPhone 11 Pro Max, A2219iPhone 11, A2111iPhone 11, A2221iPhone 11, A2223iPhone 11, A2222iPad Pro 12.9-inch, A2232iPad Pro 12.9-inch, A2069iPad Pro 12.9-inch, A2233iPad Pro 12.9-inch, A2229iPad Pro 11-inch, A2068iPad Pro 11-inch, A2230iPad Pro 11-inch, A2231iPad Pro 11-inch, A2228|
|iPad mini (5th generation)|iOS 13.4.1|115456 - Controller Subsystem102170 - Profile Subsystem99179 - Host Subsystem|iPhone, A1921 A2101 A2102 A2104 A2103iPhone XR, A1984 A2105 A2106 A2108 A2107iPhone Xs, A1920 A2097 A2098 A2100 A2099iPhone Xs Max, A1921 A2101 A2102 A2104 A2103iPad Pro 11", A1980 A2013 A1934 A1979iPad Pro 12.9", A1876 A2014 A1895 A1893iPad mini, A2133 A2126 A2124 A2125iPad, A2152 A2153 A2123 A2154iPad mini 5, A2133 A2126 A2124 A2125iPad Air (3rd generation), A2152 A2153 A2123 A2154|
|iPad (7th generation)|iOS 13.4.1|Not Available to Silicon Labs| |
|iPad Air(3rd generation)|iOS 13.3.1|Not Available to Silicon Labs| |
|iPAD 11 Pro|iOS 13.5.1|137333 (Profile Subsystem)137332 (Host Subsystem)|iPhone 11 Pro, A2160iPhone 11 Pro Max, A2161iPhone 11 Pro, A2217iPhone 11 Pro, A2215iPhone 11 Pro, A2216iPhone 11 Pro Max, A2218iPhone 11 Pro Max, A2220iPhone 11 Pro Max, A2219iPhone 11, A2111iPhone 11, A2221iPhone 11, A2223iPhone 11, A2222iPad Pro 12.9-inch, A2232iPad Pro 12.9-inch, A2069iPad Pro 12.9-inch, A2233iPad Pro 12.9-inch, A2229iPad Pro 11-inch, A2068iPad Pro 11-inch, A2230iPad Pro 11-inch, A2231iPad Pro 11-inch, A2228|
|iPhone XS Max|iOS 12.3|115456 - Controller Subsystem102170 - Profile Subsystem99179 - Host Subsystem|iPhone, A1921 A2101 A2102 A2104 A2103iPhone XR, A1984 A2105 A2106 A2108 A2107iPhone Xs, A1920 A2097 A2098 A2100 A2099iPhone Xs Max, A1921 A2101 A2102 A2104 A2103iPad Pro 11", A1980 A2013 A1934 A1979iPad Pro 12.9", A1876 A2014 A1895 A1893iPad mini, A2133 A2126 A2124 A2125iPad, A2152 A2153 A2123 A2154iPad mini 5, A2133 A2126 A2124 A2125iPad Air (3rd generation), A2152 A2153 A2123 A2154|

##### References

- [https://www.bluetooth.com/develop-with-bluetooth/qualification-listing/](https://www.bluetooth.com/develop-with-bluetooth/qualification-listing/)

### Non-Volatile Data Storage

#### Non-Volatile Data Storage

This section offers an introduction to non-volatile data storage and describes how to use NVM3 data storage.

- [**Non-Volatile Data Storage Fundamentals**](/bluetooth/11.0.0/non-volatile-data-storage-fundamentals): Introduces non-volatile data storage using flash and the three different storage implementations offered for Silicon Labs microcontrollers and SoCs: Simulated EEPROM, PS Store, and NVM3.
- [**Using Third Generation Non-Volatile Memory (NVM3) Data Storage**](/bluetooth/11.0.0/using-third-generation-nonvolatile-memory): Explains how NVM3 can be used as non-volatile data storage in various protocol implementations.

#### Non-Volatile Data Storage Fundamentals

##### Non-Volatile Data Storage Fundamentals

> **Note: This section replaces _UG103.07: Non-Volatile Data Storage Fundamentals_. Further updates to this user guide will be provided here**.

This guide provides a general introduction to non-volatile data storage using flash, with a focus on the three different dynamic data storage implementations offered for Silicon Labs microcontrollers and radio SoCs (Systems on Chip). It offers a comparison of the three implementations and provides recommendations on when to use each. Additional detail on using the various data storage implementations may be found in the following documents:

- [Using Tokens for Non-Volatile Data Storage](https://docs.silabs.com/gecko-platform/latest/using-tokens-for-non-volatile-storage/index.html)
- _AN703: Using Simulated EEPROM Version 1 and Version 2 for the EFR32 SoC Series 1 Platform_
- [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](https://docs.silabs.com/gecko-platform/latest/using-third-generation-nonvolatile-memory/)

Silicon Labs’ _Fundamentals_ series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs Bluetooth, and associated development tools. These guides can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

##### Introduction

Non-volatile memory (NVM) is memory that persists even when the device is power-cycled. On Silicon Labs microcontrollers and radio SoCs, the NVM is implemented as flash memory. In many applications the flash is not only used to store the application code but also to store data objects that are written and read frequently by the application. As flash memory can only be erased a limited number of times, several methods exist to efficiently read and write non-volatile data without wearing out the flash.

Some data is considered manufacturing data that is written only once at manufacturing time. This document is concerned with dynamic data that changes frequently over the life of the product.

This document provides an introduction to the main design options for dynamic data storage in microcontrollers and radio SoCs, along with guidelines on what factors affect flash lifetime. In addition it introduces the main flash data storage implementations offered by Silicon Labs:

- NVM3
- Simulated EEPROM version 1 (SimEEv1) and version 2 (SimEEv2)
- Persistent Store (PS Store)

##### Implementations of Non-Volatile Data Storage

This chapter introduces some of the challenges and design options when implementing non-volatile data storage in flash memory. It describes at a high level how non-volatile data storage is implemented in flash memory in PS Store, SimEEv1/v2, and NVM3.

###### Basic Implementations

One of the characteristics of flash memory is that it is writable in smaller pieces, usually 32-bit words, while it can only be erased in larger chunks, usually pages of several kilobytes. When using flash as data storage, the most straightforward implementation option would be to store each data object in its own flash page, as shown in the following figure. This way each object can be erased and re-written without influencing the other data objects. Usually the data objects are much smaller than the page size, and this solution is not an effective way of using the available flash space.

![One Object Per Page](/non-volatile-data-storage-fundamentals/0.1/images/one-object-per-page.png)

To avoid wasting flash space we can store several data objects in one flash page, as shown in the following figure. This solution then introduces a challenge when we want to write a new value to one of the data objects. In that case the page must be erased before all objects are written back to the page again, including the object we changed. As flash memory can only endure a limited amount of flash erases before the flash cells are worn out, this solution results in a very limited device lifetime.

![Multiple Objects in One Flash Page](/non-volatile-data-storage-fundamentals/0.1/images/multiple-objects-in-one-flash-page.png)

To avoid erasing the flash page for every object write, we can instead write new versions of each object to new empty locations in the flash page. This is a simple form of wear-levelling that reduces the number of page erases. However, this requires that we store some identification information along with the object data that tells us what object the data belongs to, so we know how to find the latest version of the data object. This is illustrated in the following figure, where a key is added to each version of the object data to identify what object the data belongs to. When accessing an object we then need to search through the flash page for the most recent version of the object. In this case the newest version is the one with the highest address, as we start writing from the lowest address of the page.

![Object Versions With Keys](/non-volatile-data-storage-fundamentals/0.1/images/object-versions-with-keys.png)

###### Handling Resets and Power Failures

As we fill up the flash page with new versions of the data objects, eventually no room is left to write new object data. At this point we need to erase the page and start over by writing only the latest versions of each object to the flash page. In many applications, however, power failures or resets can happen at any time, and we should not risk losing data if this occurs. If a reset occurs after the flash page is being erased, but before the data objects are written back, then we will lose this data. To handle this case we introduce a second page, to which we copy the latest version of the data objects, before erasing the original page, as shown in the following figure Then we can start filling the second page with data. When the second page is full we move the latest data back to the first page and so on. This mechanism, where the storage is alternated between two flash pages, is how PS Store operates.

![Latest Data Copied to New Page Before Erase](/non-volatile-data-storage-fundamentals/0.1/images/latest-data-copied-to-new-page-before-erase.png)

###### Introducing Virtual Pages

In some applications we write to data objects frequently, and the flash pages therefore also need to be erased frequently. As the data objects in the implementation so far are only spread across two flash pages, each page will frequently get erased and the flash lifetime will be limited. To increase the lifetime we can use more flash pages to store the data objects. In this example, instead of two physical pages, we operate with two virtual pages (A and B) that each consist of several physical flash pages. The virtual pages are erased and written to as if they were one larger flash page. The difference is simply that each virtual page is bigger and we can write more data before we need to erase the virtual page, hence the lifetime is extended. In addition to increasing flash lifetime, using several flash pages per virtual page allows you to store more or larger objects. SimEEv1 uses this design, with each virtual page consisting of two flash pages, A and B, as shown in the following figure.

![Virtual Pages](/non-volatile-data-storage-fundamentals/0.1/images/virtual-pages.png)

In some applications the time it takes to write a non-volatile data object must be minimized so as to not interfere with the timing of other critical operations. If an object write is triggered when a virtual page is full, the latest version of all objects must first be copied to the new virtual page before writing the new object version in question to the new page. All objects must be copied over immediately to allow the first page to be quickly erased so we can move data there in case of a failure. Copying all objects at once increases the worst-case object write time.

To reduce the write times, a third virtual page can be introduced that is always kept erased. Instead of copying over the latest version of every object when the first page is full, we can instead copy over only some of the objects. The rest of the objects are copied over as a part of subsequent write operations. This way we spread the copy process to the new page over more write operations, hence each write operation takes less time to complete. With this approach we have live object data spread out across two virtual pages and the third page is always kept erased, so we have somewhere to move the data to in case of a failure. SimEEv2 uses this implementation with 3 virtual pages where each virtual page consists of 6 flash pages.

###### Basic Storage

Basic storage is defined as the size of all the latest version of all objects, including any overhead stored with them. Except for NVM3, every time a flash page or virtual page is erased we must first move the basic storage over to a new page. The basic storage size is important, as it determines how much flash space is left over in a page to store any new versions of the object data. If the basic storage takes up almost the entire page, we can only write a few new object versions before we need to move to a new page and erase the old one. This leads to frequent page erases and a short flash lifetime.

NVM3 only copies unique objects that are stored in the page that will be erased. If newer versions of the object exist in other pages, the object will not be copied.

###### FIFO Model

The flash data storage implementations can be modelled as a First-In First-Out (FIFO) buffer (see the following figure), where we write new versions to the input of the FIFO. As the FIFO fills up, we need to free up space by erasing one or more pages at the end of the FIFO. Before we erase a page, we need to copy any object versions for which no newer version of the same object exists in the rest of the flash pages. Other object data can be discarded, because newer versions exist. To maximize flash lifetime we want to copy as few object versions as possible, so that most of the writes to the flash memory are new versions of the objects. If the FIFO is implemented over a large flash space, it is more likely that the new version of the object has been written and that object versions at the end of the FIFO can be discarded. In this case the flash page can be erased with few or no object versions copied.

![FIFO Buffer](/non-volatile-data-storage-fundamentals/0.1/images/fifo-buffer.png)

A drawback of using a few virtual pages is that the available memory for the FIFO is limited to only the virtual pages that can hold live data. For implementations using two virtual pages, like SimEEv1, this means only half the storage space is used for the FIFO, while for SimEEv2 two thirds of the storage space is used for the FIFO.

To allow a higher portion of the storage space to be used for the FIFO, we can instead implement the FIFO as a circular buffer over the entire flash storage space allocated, as shown in the following figure. In this implementation we always need to keep enough erased pages in front of the leading edge of the buffer to write the largest-sized object in case of a failure. When the FIFO fills up to reach the critical number of erased flash pages, we copy over any object versions that have not been superseded and erase the page at the back of the FIFO. This means that, instead of keeping a full virtual page erased, we only need to keep enough space erased to fit the largest-sized object. We can use the rest of the space for the FIFO. NVM3 is implemented as a circular buffer implemented over the entire storage space, thus increasing flash lifetime compared to implementations using smaller virtual pages.

![Circular Buffer](/non-volatile-data-storage-fundamentals/0.1/images/circular-buffer.png)

###### Counter Objects

For some types of data, the storage format can be optimized for the flash medium. EFR32 Series 0 and 1 can write each word two times, allowing for half word updates.  Series 2 devices allow just one write per word.

For example, counter values are usually incremented by 1 or some other low value every time they are written. Normally this means that we would have to write the entire counter value in addition to identification bytes every time the counter is incremented. We can optimize this by only storing a start value in addition to the identification value the first time a counter is written. Then we reserve a number of the words following the initial value for writing increments. The flash words in Silicon Labs devices EFR32 Series 0 and 1 can write words twice between each erase by keeping a 1 in the bits that are not to be changed.

As an example, assume we are writing two 16 bit values, 0xAAAA and 0x5555. To safely write them in the same flash word this method can be used:

- Write 0xFFFFAAAA (word in flash becomes 0xFFFFAAAA)
- Write 0x5555FFFF (word in flash becomes 0x5555AAAA)

Note that there is a maximum of two writes to the same word between each erase due to a physical limitation of the flash.

To find the current counter value, we start with the initial value and add the increment values in the halfwords following the initial value. This means that we only need to write one halfword for each increment, instead of the whole counter value and identification value. NVM3 and SimEEv1/v2 support counter objects.

###### Indexed Objects

When storing data such as arrays in flash, we often only update one index at a time. If we store the whole array as one regular object, we must write the whole array to flash even if just one index is updated. Instead of storing the entire array in one object, we can divide each data array over multiple objects and only update the objects holding the changed array indexes. While it is possible to split arrays into multiple objects manually for all the Silicon Labs storage implementations, SimEEv1/v2 allow all of the indexes to share one object key. The index entry into the array to be looked up is then provided as a separate parameter.

NVM3 does not support reading and writing parts of an object. If the application wants to access indexes individually, each index must be accessed using a unique key.

##### Dynamic Data Storage Implementations

This chapter introduces some of the dynamic data storage implementations offered by Silicon Labs, including SimEEv1 and SimEEv2, PS Store, and NVM3.

###### SimEEv1/v2

SimEEv1/v2 can be used with EmberZNet PRO and Silicon Labs Connect (installed with the Flex SDK). SimEEv1 uses two virtual pages with a fixed total size of 8 kB, while SimEEv2 uses three virtual pages with a fixed total size of 36 kB.

One characteristic of SimEEv1/v2 is that all objects are defined with size and type at compile time, hence a new object cannot be created or deleted at runtime.

Silicon Labs provides a plugin for upgrading SimEEv1 data to SimEEv2.

Information about the SimEEv1/v2 implementations is found in _AN703: Using Simulated EEPROM Version 1 and Version 2 for the EFR32 Series 1 SoC Platform_.

###### PS Store

PS Store can be used with Bluetooth devices on all platforms except for EFR32 Series 2. PS Store API commands are used to manage user data in PS keys in the flash memory of the Bluetooth device. User data stored within the flash memory is persistent across reset and power cycling of the device. The persistent store size is 2048 bytes and uses two flash pages for storage. As Bluetooth bondings are also stored in this area, the space available for user data also depends on the number of bondings the device has at the time. The size of a Bluetooth bonding is around 150 bytes. With its simple implementation and few storage flash pages, PS Store is the smallest of Silicon Labs' non-volatile storage options. PS Store allows objects to be created and deleted at runtime.

Information about the PS Store APIs may be found in the _Bluetooth API Software Reference Manual_.

###### NVM3

The third generation Non-Volatile Memory (NVM3) data storage driver is an alternative to SimEEv1/v2 and PS Store. The NVM3 driver provides a means to write and read data objects (key/value pairs) stored in flash. Wear-leveling is applied to reduce erase and write cycles and maximize flash lifetime. The driver is resilient to power loss and reset events, ensuring that objects retrieved from the driver are always in a valid state. Because NVM3 can be used with several protocols, such as Bluetooth and EmberZNet PRO, it allows a single data storage instance to be shared in Dynamic Multiprotocol (DMP) applications.

Some of the main features of NVM3 are as follows:

- Key/value pair data storage in flash
- Runtime creation and deletion of objects
- Persistence across power loss and reset events
- Wear-leveling to maximize flash lifetime
- Object sizes from 0 to 4096 bytes
- Configurable flash storage size (minimum 3 flash pages)
- Cache with configurable size for fast object access
- Data and counter object types
- Compatibility layers with token and PS Store APIs provided
- Single shared storage instance in multiprotocol applications
- Repack API to allow application to run clean-up page erases during periods with low CPU load

Detailed information on NVM3 is documented in the EMDRV->NVM3 section of the [Gecko HAL & Driver API Reference Guide](http://devtools.silabs.com/dl/documentation/doxygen/). Users who are accessing NVM3 through its native API should refer to this API reference guide for information. Users who are developing dynamic multiprotocol applications should refer to [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](https://docs.silabs.com/gecko-platform/latest/using-third-generation-nonvolatile-memory/).

##### Comparing Non-Volatile Data Storage Implementations

The following table presents an overview of the main features of the various Silicon Labs Non-Volatile Data Storage implementations.

|Feature|NVM3|SimEEv1|SimEEv2|PS Store|
|---|---|---|---|---|
|Compatible devices|EFM32, EFR32|EFR32 Series 1|EFR32 Series 1|EFR32 Series 1|
|Compatible radio protocols|EmberZNet, Connect, Z-Wave, OpenThread, Bluetooth|EmberZNet, Connect|EmberZNet, Connect|Bluetooth|
|Flash used for storage|3 or more flash pages|8 KB|36 KB|4 KB|
|Virtual pages|NA|2|3|NA|
|Max basic storage (Sum of all object data with overhead)|Variable (see [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](https://docs.silabs.com/gecko-platform/latest/using-third-generation-nonvolatile-memory/) for details)|2 KB|8 KB|2 KB|
|Max number of objects|Limited by basic storage|254|254|Limited by basic storage|
|Max object size (bytes)|Configurable 208-4096|254|254|56|
|Object creation/deletion|Runtime|Compile time|Compile time|Runtime|
|Compiled flash size excluding data storage|9.1 KB|3.5 KB|5.4 KB|1.6 KB|
|Counter object support|Yes|Yes|Yes|No|
|Indexed object support|Partial (note 1)|Yes|Yes|No|
|Overhead per object (bytes)|4 (size <= 128 bytes); 8 (size > 128 bytes)|2|6|10|
|Counter object size including overhead (bytes)|212|60|56|NA|
|Counter increments before rewrite|100 (EFR32 Series 1); 50 (EFR32 Series 2)|25|25|NA|

Note 1: When using NVM3, indexed objects are implemented by storing each index in a separate NVM3 object.

###### Flash Lifetime

All Silicon Labs Flash Data Storage implementations use some form of wear-levelling to prolong flash lifetime. The effectiveness of the wear-levelling depends on the implementation, the type of data stored, and how often it is updated. The main factors that affect wear-levelling and thereby flash lifetime are:

- Size of flash used for data storage: More flash area gives longer flash lifetime. For NVM3, the number of flash pages used for data storage can be configured, while the rest of the implementations use fixed storage sizes.
- Stored overhead per object: When writing data to the object storage, some overhead bytes are added to identify the data. Implementation with less overhead means the data objects take up less space in flash, and gives longer flash lifetime.
- Alignment to minimum object size: Objects are stored in multiples of the smallest object size. If the data size does not align with this size, padding bytes are added, which adds to the stored data and reduces flash lifetime. For instance, when storing 16-bit objects, NVM3 and PS Store add two extra bytes of padding in addition to the overhead bytes. SimEEv1/v2 are able to store 16-bit data objects without padding.
- Remaining storage after basic storage: For implementations using virtual pages, when switching to a new virtual page one instance of each object is written to the page. The rest of the virtual page can then be used to store new writes of the objects. If a lot of space is used to store one instance of each object, little space is left in the virtual page to use for wear-levelling the subsequent object writes. The flash lifetime will therefore be reduced when the total amount of object data is large relative to the virtual page size. Even for NVM3, where virtual pages are not used, the flash lifetime is limited by the available space of the total NVM3 storage.

To help monitor the actual flash wear, NVM3 and SimEEv1/v2 include function calls for reporting the number of page erases of the data storage flash pages. These erase counters can be read during accelerated lifetime testing of a product to verify if the flash wears at an acceptable rate.

#### Using Third Generation Non-Volatile Memory (NVM3) Data Storage

##### Using Third Generation Non-Volatile Memory (NVM3) Data Storage

> **Note: This section replaces _AN1135: Using Third Generation Non-Volatile Memory (NVM3) Data Storage_. Further updates to this application note will be provided here**.

The NVM3 driver provides a means to write and read data objects (key/value pairs) stored in flash. Wear-leveling is applied to reduce erase and write cycles and maximize flash lifetime. The driver is resilient to power loss and reset events, ensuring that objects retrieved from the driver are always in a valid state. A single NVM3 instance can be shared among several wireless stacks and application code, making it well-suited for multiprotocol applications. This application note explains how NVM3 can be used as non-volatile data storage in Zigbee (EmberZNet), Open Thread, Z-Wave, Bluetooth, Connect, and WiseConnect applications.

Version 3.x of the Gecko SDK Suite, used with Simplicity Studio 5, introduced a new component-based project architecture that replaced AppBuilder. Eventually all wireless protocols will move to the component-based architecture. This document addresses both this new approach to NVM3 configuration as well as the AppBuilder configuration still in use.

###### Key Points

- Key/value pair data object storage in flash
- Wear-leveling to maximize flash lifetime
- Resilient to power and reset events
- Shared by Zigbee, Connect, OpenThread, Z-Wave, and Bluetooth stacks
- Compatible with PS Store and Token APIs through wrappers
- Data upgradable from Simulated EEPROM version 2 to NVM3

##### Overview

The third generation Non-Volatile Memory (NVM3) data storage driver is for storing persistent data in flash.

NVM3 is designed to work on all Silicon Labs wireless stacks running on EFR32, Series-3, and Si91x devices, as well as MCU applications running on EFM32.

Some of the main features of NVM3 are:

- Key/value pair data storage in flash
- Runtime object creation and deletion
- Persistence across power loss and reset events
- Wear-leveling to maximize flash lifetime
- Object sizes configurable up to 4096 bytes
- Configurable flash storage size (minimum 3 flash pages)
- Cache with configurable size for fast object access
- Data and counter object types
- Compatibility layers included for several Silicon Labs persistent storage APIs
- Single shared storage instance in multiprotocol applications
- Repack API to allow application to run clean-up page erases during periods with low CPU load

NVM3 is described in detail in the NVM3 Documentation on [https://docs.silabs.com/](https://docs.silabs.com/). The rest of this document assumes you are familiar with that content.

While the NVM3 API can be used directly, NVM3 is also used as the underlying storage mechanism for several other persistent storage APIs provided by Silicon Labs:

- Token API used in Zigbee EmberZNet and Connect applications
- Persistent Storage API used in Silicon Labs Bluetooth applications

##### NVM3 Default Instance

Several NVM3 instances can be created on a device and live independently of each other, but to save memory it is usually desirable to use only one NVM3 instance as each instance adds some overhead. For applications based on Silicon Labs wireless stacks, a common default instance is used. This allows Dynamic Multiprotocol (DMP) applications that combine several wireless stacks to share the same NVM3 instance.

The number of flash pages used for the NVM3 default instance is configurable, but this setting must match if an application includes several stacks that all use the default instance.

> **IMPORTANT**: When creating an application that includes an NVM3 instance for a device that already contains an NVM3 instance in flash, the number of flash pages configured for the NVM3 instance must match the number of flash pages for the NVM3 instance already found on the device. Therefore it is not possible to change the size of an NVM3 instance once it has been installed on a device, without first erasing the flash pages holding the NVM3 instance and the NVM3 objects stored there.

NVM3 has a cache to speed up access to NVM3 objects. The cache size must be set to a value greater than or equal to the number of objects found in NVM3. This includes the number of NVM3 objects created through the native NVM3 API and any objects created through higher level APIs such as the Token API. The cache must also be large enough to hold any deleted NVM3 objects. The `nvm3_countObjects()` and `nvm3_countDeletedObjects()` functions can be used to find the number of live and deleted objects in NVM3 at any given point. Silicon Labs recommends checking these functions after initialization of all NVM3 objects, both through the native NVM3 API and higher level APIs such as the token API, to figure out the correct size of the NVM3 default cache size.

###### NVM3 Default Instance Key Space

NVM3 uses a 20-bit key to identify each object. To avoid using the same key for more than one object, the NVM3 key space for the default NVM3 instance has been divided into several domains as outlined in the following table. For example, NVM3 objects defined in the Zigbee EmberZNet stack should use NVM3 keys in the range 0x10000 to 0x1FFFF, while user application tokens should use keys below 0x10000. Note that any user defined NVM3 objects should be placed below 0x10000.

|**Domain**|**NVM3 Key**|
|---|---|
|User|0x00000 - 0x0FFFF|
|Zigbee EmberZNet stack|0x10000 - 0x1FFFF|
|OpenThread stack|0x20000 - 0x2FFFF|
|Connect stack|0x30000 - 0x3FFFF|
|Bluetooth stack|0x40000 - 0x4FFFF|
|Z-Wave stack|0x50000 - 0x5FFFF|
|Bluetooth mesh stack|0x60000 - 0x6FFFF|
|Reserved|0x70000 - 0x7FFFF|
|Apple HomeKit|0x80000 - 0x80FFF|
|Zigbee Cluster Library (ZCL)|0x81000 - 0x81FFF|
|dotdot|0x82000 - 0x82FFF|
|Platform CLI SM|0x83000 - 0x830FF|
|Platform Crypto|0x83100 - 0x870FF|
|Bootloader|0x87100 - 0x871FF|
|Matter|0x87200 - 0x87FFF|
|AWS Late Provision|0x88000 - 0x88FFF|
|KNX IoT|0x89000 - 0x897FF|
|Antenna Calibration (Platform)|0x89800 - 0x8987F|
|Antenna Calibration (RAIL)|0x89880 - 0x898FF|
|Trackers|0x89900 - 0x899FF|
|Reserved|0x89A00 - 0x8DFFF|
|Static device tokens - override|0x8E000 - 0x8EFFF|
|Static secure tokens - override|0x8F000 - 0x8FFFF|
|Wi-SUN|0x90000 - 0x9FFFF|
|Sidewalk|0xA0000 - 0xAFFFF|
|Wi-Fi|0xB0000 - 0xBFFFF|
|Reserved|0xC0000 - 0xFFFFF|

##### NVM3 in the Simplicity Studio 5 Project Configurator

The Simplicity Studio 5 Project Configurator, used with Silicon Labs Bluetooth v3.x, Connect v3.x, EmberZNet Zigbee v7.x, and OpenThread SDK applications, includes an NVM3 Core component. A separate component is also provided for the NVM3 default instance, which will initialize this instance.

![screenshot](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image1.png)

For Si91x devices, the NVM3 default instance can be configured under NVM3 for Si91x.

![screenshot](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image4.png)

The **NVM3 Default Instance** component provides the following configurations:

- **Cache Size**: Number of objects to cache. To reduce access times, this number should be equal to or higher than the number of live and deleted objects stored in NVM3 at any time.
- **Max Object Size**: Size of largest allowed NVM3 object in bytes. Must be between 208 and 4096 bytes.
- **User Repack Headroom**: Headroom determining how many bytes below the forced repack limit the user repack limit is placed. The default value is 0, which means that the forced and the user repack limits are the same.
- **Default Instance Size**: Size of the NVM3 storage region in flash. This must be set to match an integer number of flash pages, 3 pages at minimum.

If the **NVM3 Default Instance** component is included in a project, the default instance will be initialized automatically during `sl\_system\_init()` if the **System Init** component is included in the project.

##### Using NVM3 with Silicon Labs Connect

This chapter applies to Connect in the Proprietary Flex SDK v3.x used with the Project Configurator in Simplicity Studio 5. Connect in Proprietary Flex SDK v2.x uses AppBuilder in Simplicity Studio 4. AppBuilder use is described in [Using NVM3 in AppBuilder-Based Applications](08-using-nvm3-in-appbuilder-based-applications).

For Silicon Labs Connect v3.x applications, a **Token Manager** component is available under Platform > Driver in the Simplicity Studio Project Configurator Software Component view. While the token manager provides the [Token API](10-nvm3-api-options), an additional component must be selected for the token storage backend, either **Token Manager using Sim EEPROM 1**, **Token Manager using Sim EEPROM 2**, or **Token Manager using NVM3.** If NVM3 is chosen as the storage backend, **NVM3** and the **NVM3 Default Instance** components are included in the project.

##### Using NVM3 with Silicon Labs OpenThread Applications

This section applies to the Silicon Labs OpenThread SDK v1.x used with the Simplicity Project Configurator in Simplicity Studio 5. All OpenThread sample applications in the GSDK by default are configured to use NVM3 to store data in non-volatile memory. When doing so, these applications:

- Use the common default NVM3 instance.
- Include the NVM3 Core and the NVM3 Default Instance components in the project.
- Use the native NVM3 API to access the NVM3 object

The NVM3 key space used by the OpenThread stack is 0x20000 to 0x2FFFF.

##### Using NVM3 with Zigbee EmberZNet v7.x and Higher

This chapter applies to the Silicon Labs Zigbee EmberZNet SDK v7.x and higher used with the Simplicity Project Configurator in Simplicity Studio 5. Zigbee EmberZNet 6.x and lower use AppBuilder. AppBuilder use is described in [Using NVM3 in AppBuilder-Based Applications](08-using-nvm3-in-appbuilder-based-applications).

All Zigbee sample applications in the GSDK by default are configured to use NVM3 to store data in non-volatile memory. When doing so, these applications:

- Use the common default NVM3 instance
- Include the NVM3 Core and the NVM3 Default Instance components in the project
- Use the native NVM3 API to access the NVM3 object

If you have non-volatile data stored in the older SimEE format and need to preserve the data when migrating your Zigbee application to EmberZNet v7.x or higher, then the Token Manager component is available to help manage the data storage. For more information, see the Token Manager component's description.

The NVM3 key space used by the Zigbee stack is 0x10000 to 0x1FFFF.

##### Using NVM3 with Silicon Labs Bluetooth Applications

Traditionally the Bluetooth stack uses its own proprietary solution to store data in non-volatile memory, called **Persistent Store (PS Store)**. PS Store stores both data handled by the stack (such as temporary Bluetooth address, bonding keys, and so on) and user data (such as the device state) that has to be preserved on resetting the device. To learn more about PS Store, read the related section of the [Bluetooth API Reference Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/).

Some of the sample applications in the Bluetooth SDK are still configured to use PS Store, while others are already configured to use NVM3. This means that:

- On Series 1 devices sample apps are configured to use PS Store, except Bluetooth Mesh NCP sample projects, where NVM3 is used by default.
- On Series 2 devices all sample apps are configured to use NVM3.

While Series 2 devices support NVM3 only, on Series 1 devices both PS Store and NVM3 can be used. This section describes how to configure NVM3 in the Bluetooth SDK, and how to switch between PS Store and NVM3 if needed.

###### Configuring NVM3 in the Bluetooth SDK

**With Simplicity Studio 5 and Bluetooth SDK v3.x**

NVM3 can be configured with the Project Configurator as described in [NVM3 in the Simplicity Studio 5 Project Configurator](03-nvm3-in-the-simplicity-studio-5-project-configurator).

**With Simplicity Studio 4 and Bluetooth SDK v2.x**

The Project Configurator is not available to configure NVM3 parameters. Therefore, the parameters have to be defined manually. To overwrite the default parameters:

1. Open the project settings.
2. Find the defined symbols:  
   - If you use GCC as your compiler, go to C/C++ Build>Settings>GNU ARM C Compiler>Symbols>Defined Symbols  
   - If you use IAR as your compiler, go to C/C++ Build>Settings>IAR C/C++ compiler for ARM>Preprocessor>Defined Symbols
3. Add any of the following defines to overwrite the default parameters:  
   - NVM3_DEFAULT_NVM_SIZE  
   - NVM3_DEFAULT_CACHE_SIZE  
   - NVM3_DEFAULT_MAX_OBJECT_SIZE  
   - NVM3_DEFAULT_REPACK_HEADROOM

You can find the description of each parameter in [NVM3 in the Simplicity Studio 5 Project Configurator](03-nvm3-in-the-simplicity-studio-5-project-configurator). Be careful when providing the size of NVM3, as it must be a multiple of the flash page size. Note: On Series 1 devices the flash page size is typically 2 kB, while on Series 2 devices the flash page size is typically 8 kB. Check the Wireless Gecko Reference Manual for your device. The NVM size must be at least 3 flash pages.

###### Switching from PS Store to NVM3

Beginning with Bluetooth SDK v2.13.0, both PS Store and NVM3 are supported as non-volatile memory solutions on Series 1 devices. Most sample applications are configured to use PS Store by default, but for some applications (where larger non-volatile memory is needed) NVM3 may be a better solution.

> **Note**: PS Store and NVM3 are not compatible with each other, therefore upgrading an already existing application from PS Store to NVM3 will result in losing all data stored on the device. If you have an application running in the field, it may be wiser to stay with PS Store. If you still want to upgrade, see [Using the Gecko Bootloader with the Silicon Labs Bluetooth Application](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/) for details.

> **Note**: PS Store uses only 2 flash pages (=4 kB on an EFR32BG1/12/13 device). Therefore, changing to NVM3 will affect the available space in flash. You must be particularly careful when you upgrade the firmware not to overwrite the NVM3 area with the application.

**With Simplicity Studio 5 and Bluetooth SDK v3.x**

To change your project configuration from PS Store to NVM3, simply install the **NVM3 Default Instance** component in the Project Configurator as discussed in [NVM3 in the Simplicity Studio 5 Project Configurator](03-nvm3-in-the-simplicity-studio-5-project-configurator). This will automatically uninstall the (otherwise hidden) PS Store component.

**With Simplicity Studio 4 and Bluetooth SDK v2.x**

To change your project configuration from PS Store to NVM3, use the following procedure.

1. Copy the following folder with all of its content:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\platform\emdrv\nvm3` under the `/platform/emdrv` folder of your project.
2. Remove the following files from the project:  
   - `/platform/emdrv/nvm3/src/nvm3_hal_extflash.c`  
   - `/platform/emdrv/nvm3/src/nvm3_default_extflash.c` (NVM3 use with external flash is deprecated)
3. If you use Apploader in your project, also copy the NVM3 version of Apploader from:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\lib\<device>\<compiler>\binapploader_nvm3.o`  
   into the `/protocol/bluetooth/lib/<device>/<compiler>` folder of your project.
4. **If you use GCC as a compiler:**  
   1. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Compiler > Includes`.  
   2. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` to the include directory.  
   3. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Linker > Miscellaneous`.  
   4. Remove `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/libpsstore.a}`.  
   5. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a}`.  
   **If you use IAR as a compiler:**  
   1. Go to `Project > Properties > C/C++ Build > Settings > IAR C/C++ Compiler for ARM > Preprocessor`.  
   2. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` to the include directory.  
   3. Go to `Project > Properties > C/C++ Build > Settings > IAR Linker for ARM > Library`.  
   4. Remove `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/\<device\>/\<compiler\>/libpsstore.a}`.  
   5. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_iar.a}`.
5. If you use Apploader, also modify:  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/\<device\>/\<compiler\>/binapploader.o}`  
   to  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/\<device\>/\<compiler\>/binapploader_nvm3.o}`
6. Configure NVM3 as described in [Configuring NVM3 in the Bluetooth SDK](#configuring-nvm3-in-the-bluetooth-sdk).

###### Switching from NVM3 to PS Store

It may happen that, for a reason such as backward compatibility, you have to change the configuration from NVM3 to PS Store.

**With Simplicity Studio 5 and Bluetooth SDK v3.x**

To change your project configuration from NVM3 to PS Store, simply uninstall the NVM3 Default Instance component. This will automatically install the (otherwise hidden) PS Store component. Note, that this can only be done on series 1 devices, as series 2 devices do not support PS Store. **Also, it is not possible with Bluetooth Mesh Stack in use**.

**With Simplicity Studio 4 and Bluetooth SDK v2.x**

To change your project configuration from NVM3 to PS Store, use the following procedure:

1. Remove the /platform/emdrv/nvm3 folder from your project.
2. Copy the PS Store library from:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\lib\<device>\<compiler>\libpsstore.a`  
   into the `/protocol/bluetooth/lib/<device>/<compiler>` folder of your project.
3. If you use Apploader in your project, also copy the PS Store version of Apploader from:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\lib\<device>\<compiler>\binapploader.o`  
   into the `/protocol/bluetooth/lib/<device>/<compiler>` folder of your project.  
   > **Note**: PS Store is not supported on Series 2 devices (EFR32xG2x), therefore there is only an NVM3 version of the Apploader for these devices.
4. **If you use GCC as your compiler**  
   1. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Compiler > Includes`.  
   2. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` from the include directory.  
   3. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Linker > Miscellaneous`.  
   4. Add `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/libpsstore.a}`.  
   5. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a}`.  
   **If you use IAR as your compiler**  
   1. Go to `Project > Properties > C/C++ Build > Settings > IAR C/C++ Compiler for ARM > Preprocessor`.  
   2. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` from the include directories.  
   3. Go to `Project > Properties > C/C++ Build > Settings > IAR Linker for ARM > Library`.  
   4. Add `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/libpsstore.a}`.  
   5. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_iar.a}`.
5. If you use Apploader, also change:  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/binapploader_nvm3.o}`  
   to  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/binapploader.o}`.

##### Using NVM3 in AppBuilder-Based Applications

This section explains how NVM3 can be used for non-volatile storage in AppBuilder-based applications like EmberZNet 6.10.x and lower, EmberZNet-based DMP applications in GSDK 3.2 and lower, and Connect applications in Gecko SDK Suite 2.7 and lower.

###### NVM Library Plugin

To use NVM3 with an AppBuilder-based example application, the NVM3 Library plugin should be included in the project. All PS Store and SimEE plugins should be deselected.

![NVM3 Library Plugin in AppBuilder](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image2.png)

The **NVM3 Library** plugin offers four plugin options:

- **Flash Pages**: Number of flash pages to use for NVM3 data storage. Must be 3 or higher. Default is 18 (36KB) for EFR32 Series-1 devices and 4 (32KB) for EFR32 Series-2 devices
- **Cache Size**: Number of objects to cache. To reduce access times, this number should be equal to or higher than the number of objects, including tokens and deleted objects, stored in NVM3 at any time.
- **Max Object Size**: Size of largest allowed NVM3 object in bytes. Must be between 208 and 4096 bytes. Note that the token API can only be used to access objects of 254 bytes or smaller. When accessing larger objects, the native NVM3 API must be used.
- **User Repack Headroom**: Headroom determining how many bytes below the forced repack limit the user repack limit is placed. The default value is 0, which means that the forced and the user repack limits are the same.

When the NVM3 Library plugin is used the **Simulated EEPROM version 2 to NVM3 Upgrade Library** or **Simulated EEPROM version 2 to NVM3 Upgrade Stub Library** must be included, as described in [SimEEv2 to NVM3 Upgrade Plugin](#simeev2-to-nvm3-upgrade-plugin).

###### SimEEv2 to NVM3 Upgrade Plugin

An AppBuilder plugin (**Simulated EEPROM version 2 to NVM3 Upgrade Library**) is provided for EmberZNet applications that upgrade tokens stored in SimEEv2 to NVM3. For tokens to be successfully upgraded to NVM3, CREATOR_* and NVM3KEY_* defines must be added for all tokens as described in [Token API](10-nvm3-api-options). The upgrade plugin will replace the SimEEv2 storage in-place with an NVM3 storage instance. The plugin does this by compacting the SimEEv2 storage down to 12 kB, and then creates an NVM3 instance in the remaining 24 kB of the original 36 kB SimEEv2 storage space. After the token data has been copied over from SimEEv2 to NVM3, the SimEEv2 storage is erased and the NVM3 instance is resized to use the entire 36 kB storage space. Apart from the code space needed for the upgrade library code, the upgrade does not require any additional flash space to the 36 kB storage area. The upgrade plugin requires that the existing SimEEv2 storage space and new NVM3 storage space are located at the same address and have the same size.

The **Simulated EEPROM version 2 to NVM3 Upgrade Library** plugin should be included to enable the upgrade as shown in the figure below. If no SimEEv2 token data is found, the upgrade plugin will look for NVM3 data, and if neither is found it will create a new NVM3 instance with tokens set to their default values. For applications that do not need to upgrade any SimEEv2 tokens, the **Simulated EEPROM version 2 to NVM3 Upgrade Stub** plugin should be included instead.

![SimEEv2 to NVM3 Upgrade Library and Stub Plugins in AppBuilder](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image3.png)

##### Using NVM3 with Z-Wave Applications

For details on using NVM3 with Z-Wave applications, see [https://www.silabs.com/documents/public/user-guides/INS14259.pdf](https://www.silabs.com/documents/public/user-guides/INS14259.pdf), section 7.4.

##### NVM3 API Options

This chapter describes the three different APIs available to access NVM3 objects.

- Token API
- Persistent Store API
- Native NVM3 API

###### Token API

The token API is used to access data stored in SimEEv1 and SimEEv2 with the EmberZNet and Connect stacks, as well as multiprotocol applications. Information on how to define and access tokens can be found in [Using Tokens for Non-Volatile Data Storage](https://docs.silabs.com/gecko-platform/latest/using-tokens-for-non-volatile-storage/), and users should read this document before using the token API. When selecting the NVM3 Library plugin instead of one the SimEE plugins, the NVM3 default instance is used to store the token data instead of SimEE. The same token API can still be used to access tokens stored in NVM3, but the token definition needs some modifications to work with NVM3, as described below.

When defining a token to be used with SimEE, a creator code must be defined as an identifier for the token. Similarly, when defining a token to be used with NVM3, an NVM3 key must be defined for the token. A token definition that is compatible with both NVM3 and SimEE would include both an NVM3 key and a creator code and look like this:

```sh
#define CREATOR_name 16bit_value
#define NVM3KEY_name 20bit_value
#ifdef DEFINETYPES
  typedef data_type type #endif
#ifdef DEFINETOKENS
DEFINE_*_TOKEN(name, type, ... ,defaults) #endif
```

Select a 20-bit NVM3 key for the token, according to the domains in [NVM Default Instance Key Space](02-nvm3-default-instance#nvm3-default-instance-key-space). Each token must have a unique NVM3 key, except for indexed tokens, where more NVM3 keys must be reserved as outlined in [Special Considerations for Indexed Tokens](#special-considerations-for-indexed-tokens).

###### Deleting Tokens (heading level 7)

As tokens are created at compile time, they cannot be created or deleted at run time. NVM3 objects are, however, created and deleted at run time, and the token initialization function creates NVM3 objects for each defined token if they do not already exist. The token initialization generally does not delete NVM3 objects found that do not have a corresponding token associated with them. Therefore, if a token is no longer included in an application, the application should manually delete the associated NVM3 object by using the NVM3 Native API described in [Native NVM3 API](#native-nvm3-api). For indexed tokens, however, the token initialization checks if indexed tokens have more or less indexes than the number of NVM3 objects found in the indexed token's NVK3KEY range. If there are fewer indexes, the token initialization deletes the extra NVM3 objects. If the number of indexes has been increased, new NVM3 objects will be created to hold these indexes.

When NVM3 objects are deleted, the actual object data remains in NVM3 but is marked as deleted. The deleted object data remains in NVM3 and consumes cache space until NVM3 repacks have erased the page(s) holding all versions of these objects.

###### Special Considerations for Indexed Tokens (heading level 7)

NVM3 does not have native support for indexed tokens. Therefore an extra requirement is imposed on the NVM3 key selection for indexed tokens. With NVM3, indexed tokens are implemented by storing each index in a separate object, starting with index 0 stored at the defined NVM3KEY_name key value and the last index (127) stored with key NVM3KEY_name + 127. Because of this implementation, 128 NVM3 keys must be reserved for each indexed token. The user still only defines one NVM3KEY_name key value, but no other tokens should be defined with key values in the 127 values following this defined key. Even if the token is defined with fewer than 128 indices, all 128 indices should be reserved as the token might be expanded with more indices later on.

The example below shows two indexed tokens defined in the user key domain:

```sh
// This key is used for an indexed token and the subsequent 0x7F keys are also reserved #define
NVM3KEY_MY_INDEXED_TOKEN_A 0x00000
// This key is used for an indexed token and the subsequent 0x7F keys are also reserved #define
NVM3KEY_MY_INDEXED_TOKEN_B 0x00080
```

The table below provides indexed token NVM3 key selections in the example.

|**NVM3KEY**|**NVM3 Objects Contents**|
|---|---|
|0x00000|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 0|
|0x00001|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 1|
|0x00002|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 2|
|…| |
|0x0007F|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 127|
|0x00080|Reserved for TOKEN_MY_INDEXED_TOKEN_B index 0|
|0x00081|Reserved for TOKEN_MY_INDEXED_TOKEN_B index 1|
|…| |
|0x000FF|Reserved for TOKEN_MY_INDEXED_TOKEN_B index 127|

###### Bluetooth NVM API

The Bluetooth NVM API that was originally designed for PS Store can be used in the same way when using NVM3 as when using PS Store. The Bluetooth stack will automatically translate its NVM API calls to PS Store API calls or to NVM3 API calls in the background, depending on what components the project uses. The same applies for Zigbee + Bluetooth DMP projects, where NVM3 is applied as the storage mechanism, but the Bluetooth NVM API can still be used. The Bluetooth API is documented in the Bluetooth API Reference Manual. In Bluetooth SDK v2.x it can be found under the _Flash_ class (commands starting with `gecko_cmd_flash_`), while in Bluetooth SDK v3.x it can be found under the _NVM_ class (commands starting with `sl_bt_nvm`).

16-bit keys are used with the Bluetooth NVM API, which are then mapped to a 20-bit NVM3 key when NVM3 is used as storage mechanism. The four most significant bits are set to 0x4 to place these objects in the Bluetooth domain of the NVM3 default instance key space. As the Bluetooth NVM API is fixed to use only the Bluetooth domain, any objects to be placed in other domains, for example the User domain, must be created and accessed using the native NVM3 API.

If you want to use the Bluetooth NVM API and the native NVM3 API in the same app, then:

1. Call `gecko_init(pconfig)` to initialize the Bluetooth stack and open its own NVM3 instance. This is done in all Bluetooth sample apps.
2. Open NVM3 by calling the `nvm3_open()` function with the default (!) parameters to open your NVM3 instance:  
   `nvm3_open(nvm3_defaultHandle, nvm3_defaultInit);`

User data can now be saved to:

- PS key range 0x4000 - 0x407F. All other PS keys (0x0000-0xFFFF) are reserved for the stack (for example for storing bonding data).
- NVM3 key range 0x00000-0x0FFFF (NVM3 user data area), and 0x44000-0x4407F (PS Store user data area).

For example, the following API calls will have the same effect (writing to the same area):

- `nvm3_writeData(nvm3_defaultHandle,0x44000,(void\*)data,len);`
- `gecko_cmd_flash_ps_save(0x4000,len,data); //in Bluetooth SDK v2.x`
- `sl_bt_nvm_save(0x4000,len,data); //in Bluetooth SDK v3.x`

Similarly, you can read the same data with the following API calls:

- `nvm3_readData(nvm3_defaultHandle,0x44000,(void\*)read_buffer,maxlen);`
- `gecko_cmd_flash_ps_load(0x4000); //in Bluetooth SDK v2.x`
- `sl_bt_nvm_load(0x4000,maxlen,&read_len,(uint8_t\*)read_buffer); //in Bluetooth SDK v3.x`

###### Native NVM3 API

For code accessing NVM3 objects that does not need to be compatible with the token or PS Store APIs, using the native NVM3 API to access NVM3 data is recommended to reduce code size and allow using the full feature set of NVM3. Any PS Store object or token can also be accessed through the native NVM3 API using the same NVM3 key. Complete documentation of this API is found online in the Drivers section of the [Gecko Platform Developer Documentation](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3). If you are using an earlier version of the GSDK, search that page's version history for the corresponding release.

##### Simplicity Commander and NVM3

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple CLI (Command Line Interface) that is also scriptable. Simplicity Commander supports reading out the NVM3 data area from a device and parsing the NVM3 data to extract stored values. This can be useful in a debugging scenario where you may need to find out the stored state of an application that has been running for some time.

More information on how to use the Simplicity Commander with NVM3 can be found in [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

##### Securing NVM3 Data on External Flash Devices

Series-3 devices do not have on-die NVM. Since off-chip memory such as external flash is vulnerable to persistent attacks, data objects are securely stored and retrieved from the external flash using AES-GCM authenticated encryption. On Series-3 devices, the NVM3 AES-128 symmetric key is used to encrypt the data, ensuring it cannot be read in plain text from the external flash. The NVM3 AES-128 symmetric key is a device-generated, non-exportable key stored in the Secure Engine MTP. The NVM3 symmetric key is invalidated or erased during a device erase. Any attempt to load previously recorded NVM3 data (encrypted with the older key) into flash will result in invalid reads and must be avoided. In the case of a device erase, it is essential to reinitialize the NVM3 instance and add the objects again. For details about DFA and DPA countermeasures and the AES engines being used, refer to [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/).

###### Impact of External Flash and Security on Repack Timings

For Series-3 devices using external flash, repack operations may take longer due to the increased latency of accessing external flash over the bus. Additionally, with security features such as authenticated encryption (AES-GCM) enabled, the repack timings may be further impacted due to the cryptographic overhead. It is recommended to schedule repack operations during periods of low CPU and bus activity to minimize the impact on application performance.

##### Best Practices and Optimizations for NVM3

###### Right Sizing the NVM3 Storage Region in Flash

To minimize repacks and reduce flash wear, it is important to configure the NVM3 region size appropriately. The size of the NVM3 region should be based on:

- The number of objects stored in NVM3.
- The size of each object, including metadata overhead.
- The frequency of object updates and deletions.
- The flash page size of the device.

With the addition of security on Series 3 devices, storing a data object incurs a size overhead of 8 bytes. Ensure that the NVM3 region has sufficient space to accommodate active objects, deleted objects, and spare pages for repack operations. A larger NVM3 region reduces the frequency of repacks, thereby extending the flash lifetime. The "Maximum allowed basic storage" section at [Storage Capacity](https://docs.silabs.com/gecko-platform/latest/platform-driver/nvm3#storage-capacity) can help with configuring the appropriate number of flash pages and right-sizing the NVM3 storage in flash.

###### Right Sizing the Cache

The NVM3 cache size should be configured to match the number of live and deleted objects in the NVM3 region. This ensures faster access to objects and reduces the overhead of searching for objects in flash. Users can query the cache size and memory information using the `nvm3_getMemInfo()` API. This API provides details about the current memory state, including available memory, cache status, and additional cache requirements. Properly sizing the cache improves performance and reduces object lookup latency.

###### Low Memory Notification Callback

Users can use the `nvm3_registerCallback()` API to register a callback function, which is triggered when the NVM3 instance detects low memory conditions or a cache overflow. The callback allows the application to handle conditions such as freeing up memory by triggering repack. It is recommended that the callback be registered before calling any NVM3 APIs. Additionally, users can deregister the callback using the `nvm3_deregisterCallback()` API.

###### NVM3 Optimizations

Enabling NVM3 optimization improves the NVM3 initialization and object lookup time. NVM3 optimization can be enabled or disabled from Simplicity Studio UC for Series-2 and Series-3 devices. The optimization support has implications on code size. With optimization support enabled, the code size increases by approximately 1248 bytes. NVM3 optimization is enabled by default for Series-3 devices and disabled for Series-2 devices.

By following these best practices and leveraging the available APIs and optimizations, users can maximize the efficiency and reliability of the NVM3 storage system while maintaining high performance for their applications.

##### Repack Management in NVM3

###### What is a Repack Operation?

A **repack** operation in NVM3 reclaims memory in non-volatile memory (NVM) by copying valid objects to new pages and erasing old pages with obsolete or deleted data. This operation is essential for maintaining available storage and ensuring the NVM3 instance can continue to store new or updated objects.

###### Why is Repack Needed? (heading level 7)

As the NVM3 fills up with new and updated objects, old versions and deleted objects accumulate, consuming memory. When there is insufficient free memory to store additional objects, a repack operation is required to release this memory by removing outdated data.

###### When is Repack Triggered?

Repack can be triggered in two ways:

- **Forced repack**  
  NVM3 automatically initiates a repack during a write operation if free memory falls below a critical threshold (forced threshold). This threshold represents the minimum limit and cannot be modified by the user. Forced repacks are performed internally using the `repackUntilGood` API. When a forced repack occurs, write operations may take longer, potentially impacting application timing.
- **User repack**  
  Applications can manually trigger a repack by calling `nvm3_repack()`. The function will execute the repack only if the available free memory drops below the user threshold. This threshold is configurable through the `repackHeadroom` parameter and is evaluated by `nvm3_repackNeeded()`. The function `nvm3_repackNeeded()` can be used to check whether a repack is required, and `nvm3_repack()` will proceed only if this function returns `true`. For time-sensitive applications, it is recommended to trigger a user repack during periods of low activity.

###### The Role of Repack Headroom

The **repack headroom** parameter (`repackHeadroom` in `nvm3_Init_t`) specifies the gap between the user-defined repack threshold and the forced repack threshold. This allows applications to reserve additional memory before a forced repack occurs, giving more control over when repacks happen.

- **Default Value**  
  By default, `repackHeadroom` is configured to 0, making the user threshold equal to the forced threshold plus the maximum configured object size.
- **Increasing Headroom**  
  Configuring a higher `repackHeadroom` value means user or manually triggered repacks will occur earlier, reserving more memory and reducing the risk of forced repacks during critical operations. However, this can increase the frequency of user repacks and thus flash wear.

###### Best Practices for Repack Configuration

- **Call `nvm3_repack()` proactively**  
  Before writing large objects or performing a batch of writes, check `nvm3_repackNeeded()` and call `nvm3_repack()` if needed. This avoids forced repacks during time-critical operations.
- **Tune `repackHeadroom`**  
  Configure `repackHeadroom` according to the application's tolerance for repack latency (the amount of delay it can accept when a repack occurs during a write) and the available NVM3 memory. A smaller value allows more objects to be stored before a repack is needed but increases the risk of a forced repack during a write, adding latency. A larger value causes repacks to occur earlier, which lowers the risk of a forced repack but results in more frequent user repacks.  
  Repack headroom can be configured using `NVM3_DEFAULT_REPACK_HEADROOM` macro or through the Studio UI to reserve a specific amount of memory in advance, helping to avoid forced repacks during time-critical operations.  
  For example, if the application writes 512 bytes of data (including object overhead) during bootup, which is a time-sensitive operation, configure the repack headroom to 512 bytes to ensure that a forced repack does not occur during boot. Proactively check for repack before the next bootup.  
  ```c  
  // Example: Configure repack headroom to 512 bytes to ensure sufficient memory for a critical write  
  #define NVM3_DEFAULT_REPACK_HEADROOM  512  
    
  // Proactively check and perform a repack if needed  
  if (nvm3_repackNeeded(nvm3_defaultHandle)) {  
    nvm3_repack(nvm3_defaultHandle);  
  }  
  ```
- **Monitor Available Memory:**  
  Use `nvm3_getMemInfo()` to monitor available memory and repack proactively if memory is running low.  
  ```c  
  // Example: Monitor available memory and trigger a repack  
  nvm3_MemInfo_t memInfo;  
  nvm3_getMemInfo(nvm3_defaultHandle, &memInfo);  
    
  if (memInfo.nvm3Available < 512) {  // Threshold: 512 bytes  
    nvm3_repack(nvm3_defaultHandle);  
  }  
  ```  
  For more information, see the [NVM3 Memory Info](https://docs.silabs.com/gecko-platform/latest/platform-driver/nvm3-mem-info-t).

###### Avoid Large Max Object Size Unless Needed

The `maxObjectSize` parameter has a significant impact on both the minimum required NVM3 size and the amount of usable storage before a repack is triggered. Basic storage is defined as the total size of all objects, including any overhead stored with the data. The maximum amount of data that can be stored in NVM3 depends on the number of flash pages allocated for storage and the configured maximum object size.

The maximum allowed basic storage for an NVM3 instance can be estimated using the following formula:

```c
allowed_basic_storage =
  total_nvm_size
  - ((total_nvm_size / page_size) * page_header_size)             // per-page bookkeeping
  - 2 * (page_size - page_header_size)                            // repack window
  - (max_object_size + obj_header_size_large)
  - ((page_size == 4096 && max_object_size > 4064) ? 212 : 0);    // extra buffer for 4KB pages
```

where:

- `total_nvm_size` is the total NVM3 region size in bytes
- `page_size` is the flash page size in bytes
- `page_header_size` is the page header size in bytes (20 bytes)
- `max_object_size` is the configured maximum object size in bytes
- `object_header_size_large` is the large object header size in bytes (8 bytes)

This is a theoretical limit. If the basic storage is at this limit, no memory is left for wear-levelling, and page erases will be forced for every object written. Therefore, the NVM3 instance should be configured with enough flash pages so that the maximum allowed basic storage is well above the actual basic storage required by the application.

For detailed tables showing the relationship between flash page count, page size, and max object size, see the [Storage Capacity](https://docs.silabs.com/gecko-platform/latest/platform-driver/nvm3#storage-capacity) section in the NVM3 API documentation.

> **Best Practice**: Configure `maxObjectSize` to the smallest value that still accommodates the largest object. Avoid configuring it unnecessarily high, as this reduces usable memory and increases the frequency of repacks, which can accelerate flash wear.
> 
> **Tip**: If an application only occasionally needs to store a few large objects (e.g., 4096 bytes), these objects can be broken into smaller chunks (such as four 1024-byte objects). Each chunk is written separately and later read back and reassembled into the original object when needed. This approach keeps `maxObjectSize` small, maximizing usable memory and minimizing repack frequency and flash wear for the majority of the data.

###### Impact of Max Object Size on Repack and Usable Storage

The maximum object size (`maxObjectSize`) directly affects the repack thresholds and the amount of usable storage before a repack is needed. A larger `maxObjectSize`:

- Increases the minimum NVM3 size required for operation.
- Reduces the amount of storage available for user data before a repack is triggered.
- May result in more frequent repacks, especially if the stored objects are much smaller than the configured maximum.

### Security

#### Security

Silicon Labs offers a range of security features depending on the part you are using and your application and production needs. As well as the security features available, this section describes security issues specific to Bluetooth Mesh.

- [**IoT Security Fundamentals**](/btmesh/11.0.0/iot-endpoint-security-fundamentals): Introduces the security concepts that must be considered when implementing an Internet of Things (IoT) system. Using the ioXt Alliance's eight security principles as a structure, it clearly delineates the solutions Silicon Labs provides to support endpoint security and what you must do outside of the Silicon Labs framework.
- [**Bluetooth Low Energy Application Security Design Considerations in SDK v3.x**](/btmesh/11.0.0/bluetooth-application-security-design-considerations): Provides details on designing Bluetooth Low Energy applications with security and privacy in mind.
- [**IV Update in a Bluetooth Mesh Network**](/btmesh/11.0.0/btmesh-iv-update): Provides background information on the sequence number and IV index in a Bluetooth mesh network and the IV Update and IV Index Recovery procedures. It then discusses how to implement IV Update functionality in a Bluetooth mesh application.
- [Series 2 and Series 3 Secure Boot with RTSL](/btmesh/11.0.0/series2-secure-boot-with-rtsl): Describes the design of Secure Boot with RTSL (Root of Trust and Secure Loader) on Series 2 and Series 3 devices. It also provides examples of how to implement the Secure Boot process.
- [**Series 2 and Series 3 Secure Debug**](/btmesh/11.0.0/series2-secure-debug): Explains the different debug lock and unlock features available in Series 2 and Series 3 devices and their capabilities.
- [**Production Programming of Series 2 and Series 3 Devices**](/btmesh/11.0.0/prod-programming-series2-and-series3): Demonstrates how to properly program, provision, and configure Series 2 and Series 3 devices in a production environment.
- [**Anti-Tamper Protection Configuration and Use**](/btmesh/11.0.0/efr32-secure-vault-tamper): Describes how to program, provision, and configure the Secure Engine anti-tamper module. The anti-tamper module is only available on Secure Vault High and Series 3 Secure Vault devices.
- [**Authenticating Silicon Labs Devices using Device Certificates**](/btmesh/11.0.0/authenticating-devices-using-device-certificates): How to authenticate an EFR32 Series 2 device with Secure Vault, using secure device certificates and signatures.
- [**Secure Key Storage**](/btmesh/11.0.0/efr32-secure-key-storage): Explains how to securely "wrap" keys in EFR32 Series 2 devices with Secure Vault, so they can be stored in non-volatile storage.
- [**Programming Series 2 Devices Using the DCI and SWD**](/btmesh/11.0.0/efr32-dci-swd-programming): Describes how to provision and configure Series 2 devices through the DCI and SWD.
- [**Integrating Crypto Functionality with PSA Crypto vs. Mbed TLS**](/btmesh/11.0.0/mbedtls-psa-crypto-porting-guide): Describes how to integrate crypto functionality into applications using PSA Crypto compared to Mbed TLS.
- [**Series 2 TrustZone**](/btmesh/11.0.0/series2-trustzone): Provides background and information on implementing TrustZone on series 2 devices.

Bluetooth SIG offers an informational publication on Bluetooth Mesh Security: [**Mesh Security Overview (PDF)**](https://www.bluetooth.com/bluetooth-resources/mesh-security-overview/). It describes the security toolbox provided by the specification and provides recommendations on their use from the protocol specification viewpoint.

#### IoT Endpoint Security Fundamentals

##### IoT Endpoint Security Fundamentals

> **Note: This section replaces _UG103.05: IoT Endpoint Security Fundamentals_. Further updates to this user guide will be provided here**.

This guide introduces the security concepts that must be considered when implementing an Internet of Things (IoT) system. The guide clearly delineates the solutions Silicon Labs provides to support endpoint security and what you must do outside of the Silicon Labs framework. Where appropriate, Silicon Labs’ approach to our own security is offered as an example. This document is designed for product developers and managers.

Silicon Labs’ _Fundamentals_ series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs _Bluetooth®_, and associated development tools. The guides can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

###### Key Points

- Describes what manufacturers must do to have a secure product
- Reviews the tools and solutions Silicon Labs provides to support product security
- Provides references to other general and product-specific information

##### Overview

Securing the IoT is challenging. It is also mission-critical. Threats are continuously evolving, and the demand on product developers to keep up can be burdensome – particularly in low-cost, resource-constrained IoT products. Protecting your product in a connected world is a necessity, as customer data and modern online business models are increasingly targets for costly hacks that jeopardize end-user privacy and corporate brand damage. Silicon Labs is committed to working with the security community, customers, and other experts to bring state-of-the-art technology to help protect your connected portfolio.

##### No Universal Passwords

_The product shall not have a universal password; unique security credentials will be required for operation. Universal passwords allow an attacker to easily gain access to any device. Therefore, products shall either have a unique password or require the user to enter a new password immediately upon first use._

It is your responsibility to ensure that your product enforces the creation of a unique password before activation.

Silicon Labs’ products are designed to be configured by the manufacturer before being delivered to customers, and therefore passwords are outside of our scope. However, Silicon Labs tools are designed to support the various levels of security provided by the protocol in question. Most protocols offer different security levels, with tradeoffs between security level and other features such as ease of network formation. You need to review and decide on the level required by your application. For example:

- The EmberZNet Pro SDK supports a highly secure centralized trust-center-controlled method that replaces a device’s factory-programmed link key with a key that is unique to each device on the network.
- Z-Wave 700 products come with a factory-programmed unique S2 keypair on first power-up, and support SmartStart commissioning through a package QR code containing the public key.
- Bluetooth options range from an unsecured “Just Works” approach to a LE Secure Connections Pairing model. Application designers can implement additional device authentication methods, such as through the companion smartphone app, to help ensure secure pairing even for devices without a user interface.

##### Secured Interfaces

_All product interfaces shall be appropriately secured by the manufacturer._

The interfaces to be secured will vary by product configuration. For example, in an NCP topology the NCP interface must be secured. Debug interfaces should always be locked. Wireless interfaces should be secured by using strong pairing and commissioning methods and by enabling encrypted and authenticated transmissions.

While securing the interfaces is in the end your responsibility, Silicon Labs provides the tools to enable that security.

Series 1, Series 2 and Series 3 devices are designed to support securing debug access. For Series 1 devices, that functionality is provided through writing a Debug Lock word to the device. Unlocking the device erases the main application and the key material stored in the Lockbits page. For Series 2 and 3 devices, securing debug access is done through the device’s Secure Engine. Both allow the developer to lock the debug port itself. See [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or _UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower_ for an overview of securing debug access, and [Series 2 and 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) for details on the Series 2 and 3 implementation. [Testing and Debugging Applications for the Silicon Labs EFR32MG Platforms](https://docs.silabs.com/zigbee/latest/test-debug-apps-efr32mg/) provides an overview of the various application testing stages and the debug access (hardware and software) required in each.

For more information on Wireless interface security in the different protocols, see the following:

- [Zigbee Security](https://docs.silabs.com/zigbee/latest/zigbee-security/)
- [Bluetooth LE Fundamentals](https://docs.silabs.com/bluetooth/latest/bluetooth-le-fundamentals/)
- [UG235.03: Architecture of the Silicon Labs Connect Stack v2.x](https://www.silabs.com/documents/public/user-guides/ug235-03-architecture-of-connect.pdf)
- [Architecture of the Silicon Labs Connect Stack v3.x](https://docs.silabs.com/connect-stack/latest/network-co-processor-applications-connect-v3x/)

##### Proven Cryptography

_Product security shall use strong, proven, updatable cryptography using open, peer-reviewed methods and algorithms._

An important aspect of any IoT device is how secure the device is when it communicates with other devices, gateways, or the cloud. This standard mandates using proven cryptographic methods rather than attempting to implement your own.

Developers commonly secure communications such as TCP/IP connections, Bluetooth, Zigbee, or Z-Wave using the standardized and proven cryptographic methods native to the protocol. However, if a microcontroller sends sensitive information over a simple interface such as a UART to another microcontroller, it is important to realize that data should also be secured to prevent someone from snooping the UART line.

Silicon Labs offers a hardware accelerator module that provides an efficient acceleration of common cryptographic operations and allows these to be used efficiently with low CPU overhead. The cryptographic accelerator module includes hardware accelerators for the Advanced Encryption Standard (AES), optionally ChaCha20/Poly1305, Secure Hash Algorithm SHA-1 and SHA-2 (SHA-224 and SHA-256), and modular multiplication used in ECC (Elliptic Curve Cryptography) and GCM (Galois Counter Mode). The accelerator module can autonomously execute and iterate a sequence of instructions to aid software and speed up complex cryptographic functions like ECC, GCM, and CCM (Counter with CBC-MAC).

In addition to the cryptographic accelerator module, Silicon Labs includes the PSA Crypto and Mbed TLS libraries as part of the Gecko Platform SDK. Mbed TLS is open source software licensed by ARM Limited. It provides an SSL library that makes it easy to use cryptography and SSL/TLS in applications. Mbed TLS supports software implementations of all crypto algorithms that are supported by TLS 1.3 as well as a build API that allows hardware drivers to replace the software implementations when cipher accelerators are supported by the platform. Its modular framework allows for subcomponents like the crypto libraries to be incorporated into a design independently of the SSL/TLS components, saving valuable code space and runtime RAM. Mbed TLS supports SSLv3 up to TLSv1.3 communication by providing the following:

- TCP/IP communication functions: listen, connect, accept, read/write.
- SSL/TLS communication functions: init, handshake, read/write.
- X.509 functions: CRT, CRL and key handling
- Random number generation
- Hashing
- Encryption/decryption

These functions are split up into logical interfaces. They can be used separately to provide any of the above functions or to mix-and-match into an SSL server/client solution that utilizes a X.509 public key infrastructure (PKI). Examples of such implementations are provided with the source code. Components or plugins and APIs provide configuration interfaces accessible through the various SDK installations.

For more information, see the latest MCU and Peripheral Software Documentation for the target part at [https://docs.silabs.com.](https://docs.silabs.com/).

##### Security by Default

_Product security shall be appropriately enabled by default by the manufacturer._

The state in which a product is shipped is up to the manufacturer. This standard mandates that any security features provided with the product be enabled before shipping. Customers should not have to turn security on; rather they should actively have to disable it. For example, Silicon Labs Z-Wave end-nodes and gateway SDKs ship with S2 cryptography and SmartStart network formation enabled by default.

Silicon Labs believes that product security should be considered during product design, and not as an afterthought. Within development environments, all Silicon Labs application security features may be enabled or disabled as appropriate during application development. Security must also be considered during device design and testing. [Bringing Up Custom Devices for the EFR32MG and EFR32FG Families](https://docs.silabs.com/connect-stack/latest/custom-nodes-efr32/) describes the security tokens (keys, certificates, and so on) that can be programmed into a custom device to support various types of security, including that provided by the Gecko Bootloader. See [Signed Software Updates](06-signed-software-updates).

##### Signed Software Updates

_The product shall only support signed software updates. While it is critical that all products be updatable, it is just as critical that these update images be secured. A manufacturer must cryptographically sign update images to prevent tampering during deployment. The product must not use unsigned updates, as they could be fraudulent._

Silicon Labs development tools support building signed upgrade images and securely updating devices in the field, through the Silicon Labs Gecko Bootloader. The Gecko Bootloader can be configured to perform a variety of functions, from device initialization to firmware upgrades. Key features of the bootloader are:

- Usable across Silicon Labs Gecko microcontroller and wireless microcontroller families
- In-field upgradeable
- Configurable
- Enhanced security features, including:
- Secure Boot: When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot, using asymmetric cryptography. This ensures that the application was created and signed by a trusted party.
- Signed upgrade image file: The Gecko Bootloader supports enforcing cryptographic signature verification of the upgrade image file. This allows the bootloader and application to verify that the application or bootloader upgrade comes from a trusted source before starting the upgrade process, ensuring that the image file was created and signed by a trusted party.
- Encrypted upgrade image file: The image file can also be encrypted to prevent eavesdroppers from acquiring the plaintext firmware image.

On Series 1 devices, the Gecko Bootloader has a two-stage design, first stage and main stage, where a minimal first stage bootloader is used to upgrade the main bootloader. The first stage bootloader only contains functionality to read from and write to fixed addresses in internal flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to a fixed location in internal flash and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader firmware upgrade image, by computing a CRC32 checksum before copying the upgrade image to the main bootloader location.

On Series 2 and Series 3 devices, the Gecko Bootloader consists only of the first stage bootloader. The main bootloader is upgradable through the hardware peripheral Secure Engine. The Secure Engine provides functionality to install an image to the base address of flash, by copying from a configurable location in flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to the upgrade location in flash and requests that the Secure Engine install it. The Secure Engine is also capable of verifying the authenticity of the main bootloader update image against a root of trust. The Secure Engine itself is upgradable using the same mechanism.

In summary, Series 2 and Series 3 devices support a hardware root of trust and a Secure Boot process that verifies the authenticity and integrity of Gecko Bootloader, whereas in Series 1 devices, the authenticity and integrity of Gecko Bootloader are assumed trusted and are not explicitly checked.

The Gecko Bootloader can enforce application image security on two levels:

- Secure Boot refers to the verification of the authenticity of the application image in main flash on every boot of the device. When Secure Boot is enabled, the cryptographic signature of the application image in flash is verified on every boot, before the application is allowed to run. Secure Boot is not enabled by default in the example configurations provided by Silicon Labs, but enabling it is highly recommended to ensure the validity and integrity of firmware images.
- Secure Firmware Upgrade refers to the verification of the authenticity of an upgrade image before applying the upgrade and optionally enforcing that upgrade images are encrypted. The Secure Firmware Upgrade process uses symmetric encryption to encrypt the upgrade image, and asymmetric cryptography to sign the upgrade image in order to ensure its integrity and authenticity.

For more information on Silicon Labs’ support for software update security, refer to the following:

- Bootloaders in general: [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).
- The Gecko Bootloader in general: [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or _UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower_

Using the Gecko Bootloader with specific protocols:

[Using the Gecko Bootloader with EmberZNet](https://docs.silabs.com/zigbee/latest/using-gecko-bootloader-with-zigbee/)

[Using the Gecko Bootloader with Silicon Labs Connect](https://docs.silabs.com/connect-stack/latest/using-gecko-bootloader-with-connect/)

[Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/)

[Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)

##### Automatically Applied Updates

_The manufacturer will act quickly to apply timely security updates. Whenever a security vulnerability is detected, the manufacturer will automatically apply a patch to the product. No user intervention will be required._

It is the manufacturer’s responsibility to develop and implement automatic security updates. The design and methodology of such systems, for example through a Cloud-connected infrastructure or by direct intervention by a service representative, is up to you.

Silicon Labs will notify you of any security-related updates, as described in [Vulnerability Reporting Program](08-vulnerability-reporting-program) Your responsibility is to evaluate the level of risk that vulnerability poses for your particular product and to integrate the update into your platform as appropriate so that your end users are protected. Updated components might include the protocol libraries, Secure Engine firmware inside the Series 2 and Series 3 families, or an SDK module such as the Gecko Bootloader that enforces secure OTA updates and secure boot functionality.

Silicon Labs recommends the following:

- Subscribe to security updates through our [Salesforce portal](https://community.silabs.com/s/support-home). To review or change your subscriptions, log in to the portal, click **HOME** to go to the portal home page, and then click the **Manage Notifications** tile. Make sure that **Software/Security Advisory Notices & Product Change Notices (PCNs)** is checked, and that you are subscribed at minimum for your platform and protocol. Click **Save** to save any changes.  
  ![screenshot](/iot-endpoint-security-fundamentals/0.3/images/sld875-image15.png)
- Do not turn off Simplicity Studio’s update notification. Within Simplicity Studio you can download updates and easily access product release notes.

##### Vulnerability Reporting Program

_The manufacturer shall implement a vulnerability reporting program, which will be addressed in a timely manner. All companies that offer Internet-connected devices and services shall provide a public point of contact as part of a vulnerability disclosure policy in order that security researchers and others are able to report issues. Disclosed vulnerabilities should be acted on in a timely manner._

Manufacturers are responsible for implementing their own program. For any individual vulnerability, you will need to weigh the value of transparency with your customers against the risk of malicious use of the information to exploit a vulnerability before it can be addressed. Silicon Labs makes similar decisions about how broadly to report security vulnerabilities discovered in our products.

Silicon Labs customers and security researchers can report security vulnerabilities in Silicon Labs hardware and software products on the Silicon Labs website: [https://www.silabs.com/security/product-security](https://www.silabs.com/security/product-security).

Silicon Labs’ Security Vulnerability Disclosure Policy may be found here: [https://www.silabs.com/security/security-vulnerability-disclosure-policy](https://www.silabs.com/security/security-vulnerability-disclosure-policy).

Silicon Labs has a Product Security Incident Response Team (PSIRT) that is dedicated to the case management of reported security vulnerabilities. The PSIRT works with other Silicon Labs groups including Applications, Developers, Sales, and Marketing to assess reported vulnerabilities, perform technical analysis and determine an appropriate response. The key processes for addressing vulnerabilities include:

- **Triage**: Determines what is needed to reproduce the vulnerability.
- **Technical Analysis and Disposition**: Confirms the validity of the security vulnerability, its scope, and its impact, and provides a resolution or disposition decision. Silicon Labs scores incidents according to CVSS 4.0 (Common Vulnerability Scoring System): low, medium, high, critical.
- **Output**: Communicates with our customers. The level and method of disclosure beyond the reporting entity depends on the severity and scope of the vulnerability.

Silicon Labs’ provides broad vulnerability reporting to customers subscribed through our Salesforce portal (see [Automatically Applied Updates](07-automatically-applied-updates) for information on how to subscribe). A subscribed customer will see Security Advisory notifications something like the following:

![screenshot](/iot-endpoint-security-fundamentals/0.3/images/sld875-image16.jpg)

##### Security Expiration Date

_The manufacturer shall be transparent about the period of time that security updates will be provided. Like a manufacturer’s product warranty, there shall be transparency around the support period of security updates._

Manufacturers should provide details about product support at various stages and publish security expiration dates. Z-Wave’s Protocol Lifecycle provides an example.

![diagram](/iot-endpoint-security-fundamentals/0.3/images/sld875-image17.jpg)

The Lifecycle details in what phases updates will be applied, and to what product branch. For details on the various phases and how the lifecycle is implemented for specific Z-Wave products, see:

[https://www.silabs.com/products/development-tools/software/z-wave/embedded-sdk/life-cycle](https://www.silabs.com/products/development-tools/software/z-wave/embedded-sdk/life-cycle)

##### Next Steps

The Silicon Labs Security web page ([https://www.silabs.com/security)](https://www.silabs.com/security)) contains links to a variety of general security-related resources. You may wish to bookmark the page, as it will be continually updated with new content, new tools, and new flows.

If you are already in development, we strongly recommend that you implement the standards described here as you develop, test, and release your product to customers.

If you are in the early stages of your product design and have not already selected a device or development environment, we recommend that you include security considerations in your decision. Silicon Labs provides information about the security features of our devices and development environments. [Series 2 and Series 3 Device Security Features](11-series-2-and-series-3-device-security-features) highlights the features and their documentation references. In addition, protocol-specific security information is available in the following documents.

- [Zigbee Security](https://docs.silabs.com/zigbee/latest/zigbee-security/) (contents were previously in this document under the title Application Security Fundamentals)
- [Bluetooth® Low Energy Application Security Design Considerations in SDK v3.x and Higher](https://docs.silabs.com/bluetooth/latest/bluetooth-application-security-design-considerations/)
- [Using Silicon Labs Secure Vault Features with OpenThread](https://docs.silabs.com/openthread/latest/using-secure-vault-openthread/)
- [Bluetooth® LE Fundamentals](https://docs.silabs.com/bluetooth/latest/bluetooth-le-fundamentals/) and relevant Knowledge Base Articles (KBAs)
- [Architecture of the Silicon Labs Connect Stack v3.x](https://docs.silabs.com/connect-stack/latest/architecture-of-connect-v3x/)

##### Series 2 and Series 3 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys, and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

On Series 3 devices, the security features are implemented by the Secure Engine and HOSTCRYPTO (if available). The Secure Engine may is hardware-based.

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Security Level (1)**|**SE Support**|**MCU**|**Wireless SoC (2)**|
|---|---|---|---|
|Secure Vault Base (SVB)|N/A|EFM32JG1, EFM32PG1, EFM32JG12, EFM32PG12, EFM32GG11, EFM32GG12, EFM32TG11|EFR32xG1, EFR32xG12, EFR32xG13, EFR32xG14|
|Secure Vault Mid (SVM)|VSE (VSE-SVM)|EFM32PG22C|EFR32xG22C, EFR32xG27C (3)|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|-|EFR32xG21A, EFR32xG21A (Rev C), EFR32MR21A (Rev C), EFR32xG23A, EFR32xG24A, EFR32xG25A, EFR32xG28A|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|EFM32PG23B, EFMPG26B, EFM32PG28B|EFR32xG21B, EFR32Xg21B (Rev C) EFR32xG23B, EFR32xG24B, EFR32xG25B, EFR32xG26B, EFR32xG28B, EFR32xG29B, SixG301|

> Note:
> 
> 1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security.](https://www.silabs.com/security).
> 2. The x is a letter B, F, M, or Z.
> 3. Unlike other VSE-SVM parts, the EFR32xG27C device has a built-in PUF.

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

Silicon Labs strongly recommends installing the latest SE FW image on Series 2 and Series 3 devices and updating to the latest GSDK or SiSDK to mitigate security vulnerabilities. The latest SE FW image can be found in this Windows folder for GSDK v4.x:

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public`

Or

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\simplicity_sdk\util\se_release\public`

Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for guidance on the SE firmware upgrade procedure. The latest SE firmware shipped with Series 2 and Series 3 devices and modules (if available) at the time of this writing are listed in the following table:

|**Series 2 MCU and Wireless SoC VSE - SVM**|**Shipped SE Firmware Version**|
|---|---|
|EFM32PG22C|1.2.12|
|EFR32xG22C|1.2.12|
|EFR32xG22C (Rev D)|1.2.14|
|EFR32xG27C|2.2.1|

|**Series 2 Wireless SoC HSE - SVM**|**Shipped SE Firmware Version**|
|---|---|
|EFR32xG21A|1.2.13|
|EFR32MR21A (Rev C)|1.2.16|
|EFR32xG21A (Rev C)|1.2.16|
|EFR32xG23A|2.1.7|
|EFR32xG24A|2.1.7|
|EFR32xG25A|2.2.1|
|EFR32xG28A|2.2.2|

|**Series 2 MCU and Wireless SoC HSE - SVH**|**Shipped SE Firmware Version**|
|---|---|
|EFR32xG21B|1.2.13|
|EFR32xG21B (Rev C)|1.2.16|
|EFM32PG23B|2.1.7|
|EFR32xG23B|2.1.7|
|EFR32xG24B|2.1.7|
|EFR32xG25B|2.2.1|
|EFM32PG28B|2.2.2|
|EFR32xG28B|2.2.2|

|**Series 3 MCU and Wireless SoC HSE - SVH**|**Shipped SE Firmware Version**|
|---|---|
|SixG301|3.3.2|

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-trustzone/">Series 2 TrustZone</a></p>
            </td>
            <td>
                <p>Describes the basics of TrustZone, secure and privileged programming model, and shows how to upgrade existing application to TrustZone.</p>
            </td>
            <td>
                <p>Series 2 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

|**Document**|**Summary**|**Applicability**|
|---|---|---|
|[Programming Series 2 Devices Using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/)|How to provision and configure Series 2 devices through the DCI and how to program their internal flash memory through the SWD|Series 2|
|[Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS](https://docs.silabs.com/iot-security/latest/mbedtls-psa-crypto-porting-guide/)|How to integrate crypto functionality into applications using Silicon Labs implementation of PSA Crypto compared to Mbed TLS|Series 1, Series 2 and Series 3|

#### Bluetooth LE Application Security Design Considerations in SDK v3.x and Higher

##### Bluetooth® Low Energy

> **Note: This section replaces _AN1302: Bluetooth® Low Energy Application Security Design Considerations in SDK v3.x and Higher_. Further updates to this application note will be provided here**.

This application note provides details on designing Bluetooth Low Energy applications with security and privacy in mind.

###### Key Points

- Overview of Bluetooth Low Energy security and privacy
- Using the security features built into the stack/SDK
- Implementing application layer encryption
- Secure boot

##### Introduction

The Bluetooth specification makes security and privacy features optional. While using these features is not required by the specification, it is highly recommended to take advantage of the highest security features available. The Bluetooth SIG has published the following [Security and Privacy Best Practices Guide](https://www.bluetooth.com/bluetooth-resources/bluetooth-security-and-privacy-best-practices-guide/). This guide contains information for implementers of stacks as well as applications. Silicon Labs suggests following as many of these recommended best practices as possible.

###### Threat Models

Several threats exist when communicating between two parties:

- Passive eavesdropping - an unauthorized third-party intercepts sensitive data.
- Man-in-the-middle (MITM) - an unauthorized third party injects or modifies data.
- Denial-of-Service through Wi-Fi coexistence.
- Tracking - an unauthorized third party can track the location of a moveable device.
- Spoofing – a device mimics the identity of a trusted device.

###### Bluetooth Security Concepts

This section describes some basic concepts and terminology regarding Bluetooth security.

###### Connections, Pairing and Bonding (heading level 7)

A connection is required for reliable data exchange between two Bluetooth Low Energy devices as well as encryption and authentication, which are optional.

Pairing refers to a one-time secure relationship between two devices to establish cryptographic keys and allows data to be exchanged securely for the life of the connection. Loss of the connection results in termination of the pairing.

Bonding refers to a persistent relationship where cryptographic keys are established and stored in non-volatile memory and can exist over multiple connections.

LE Secure Connections refers to a method for exchanging cryptographic keys using the elliptic curve Diffie-Helman (ECDH) technique.

###### Security Modes and Levels (heading level 7)

Security mode 1 is the only mode supported for Bluetooth Low Energy in the Silicon Labs’ stack. The levels are as follows:

- Level 1 - no security
- Level 2 - unauthenticated pairing with encryption
- Level 3 - authenticated pairing with encryption
- Level 4 - authenticated secure connections with strong encryption (ECDH key exchange)

###### GATT Database (heading level 7)

Security in Bluetooth Low Energy is primarily controlled through GATT characteristics, which can have the following properties:

- Encrypted read/write/notify/indicate
- Authenticated read/write/notify/indicate
- Authorized read/write/notify/indicate

A GATT client attempting to access a characteristic must support the properties required by the characteristic.

##### Working with Stack Security Features

###### Securing Connections

Bluetooth Low Energy connections can be secured in one of two ways:

- The peer device initiates an encrypted connection
- The connection is explicitly secured through an API call

###### Protecting GATT characteristics (heading level 7)

Silicon Labs provides a GATT configuration tool that allows users to create a GATT database from a graphical user interface shown in the following figure.

![Bluetooth GATT Configurator](/bluetooth-application-security-design-considerations/0.1/images/sld814-image1.png)

As shown, the properties such as read, write, notify, and so on can be enabled or disabled, and each property can be given the authenticated, *bonded, and encrypted properties individually. It is recommended to use the strongest possible security for all characteristics. It is also recommended to give the minimum level of access to characteristics needed to accomplish the required tasks. If a characteristic does not need to be writable, disable the write property. Note that, when using Bluetooth SIG services and characteristics, there will usually be requirements for each property. Applications should comply with these requirements for interoperability and to maintain qualification status. See [GATT Configurator User’s Guide for Bluetooth LE and Bluetooth Mesh](https://docs.silabs.com/bluetooth/latest/gatt-configurator-users-guide-ble-btmesh/) for general guidance on the Bluetooth GATT Configurator.

Accessing a characteristic using a connection that does not meet the minimum requirements results in an error response being sent from the GATT server to the client. It is recommended to require encryption and authentication on all characteristics, even when the data is not sensitive.

*Bonded: the term bonded here is not a security requirement defined in the core specification like authentication or encryption but is an authorization policy for convenience; that is, the requirement is authorization and one specific implementation could be to require the device to be bonded.

###### Explicitly Securing Connections (heading level 7)

Once a connection is established, two events are raised by the stack that are useful for security purposes. The first is [sl_bt_evt_connection_opened](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-evt-connection-opened). This event contains a bond handle. If the handle is set to 0xFF no bond is present. The other event of interest is [sl_bt_evt_connection_parameters](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-evt-connection-parameters). This event contains the current security mode for the connection. The security modes are described in section [1.2.2 Security Modes and Levels](01-introduction#security-modes-and-levels) above. The default mode is 0. Either the GATT client or server can increase the security level of the connection by calling [sl_bt_sm_increase_security()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-sm#sl-bt-sm-increase-security).

###### Security Configuration (heading level 7)

The security configuration can be set on a device-wide basis by calling [sl_bt_sm_configure()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-sm#sl-bt-sm-configure). This API is used not only to set security requirements such as MITM protection and requiring bonding for encryption but also sets the I/O capabilities for the device. This information is used when bonding, to determine which type of authentication is used during the bonding process. It is recommended to use the strongest possible security configuration and to accurately report the IO capabilities of the device. The security requirements flags are explained below. It is also recommended to require bonding for encryption, since this establishes a persistent security relationship that can prevent spoofing by devices using the same MAC address.

|Security Feature|Description|
|---|---|
|Bonding requires MITM protection|When this flag is set, forming a new bond also requires man-in-the-middle (MITM) protection. This excludes the Just-works association model|
|Encryption requires bonding|Setting this flag requires a bond, rather than just pairing, for a connection to be encrypted|
|Require Secure Connections|Setting this flag requires that LE Secure Connections be used for exchanging cryptographic keys. This may prevent connections with older devices that do not support this feature|
|Bonding Requests Require Confirmation|Setting this flag requires the application to confirm any new bond request. This makes it possible to require user input for forming new bonds|
|Allow only Connections from Bonded Devices|Setting this flag requires that a peer device have an existing bond to successfully form a connection. This flag should be cleared to allow a new device to connect and bond.|
|Prefer authenticated pairing|Setting this flag causes the device to prefer authenticated pairing if both authenticated pairing and JustWorks are available.|
|Require SC OOB Data from both devices|Setting this flag requires secure connections out of band data to be present|
|Reject debug keys|Setting this this flag rejects pairing if the remote device uses debug keys.|

The following table shows the different pairing or bonding methods available based on the I/O capabilities when using secure connections.

|Responder|Initiator - DisplayOnly|Initiator - DisplayYesNo|Initiator - KeyboardOnly|Initiator - NoInputNoOutput|Initiator - KeyboardDisplay|
|---|---|---|---|---|---|
|**DisplayOnly**|Just Works|Just Works|Passkey Entry (R displays, I inputs)|Just Works|Passkey Entry (R displays, I inputs)|
|**DisplayYesNo**|Just Works|Numeric Comparison|Passkey Entry (R displays, I inputs)|Just Works|Numeric Comparison|
|**KeyboardOnly**|Passkey Entry (I displays, R inputs)|Passkey Entry (I displays, R inputs)|Passkey Entry (R and I inputs)|Just Works|Passkey Entry (I displays, R inputs)|
|**NoInputNoOutput**|Just Works|Just Works|Just Works|Just Works|Just Works|
|**KeyboardDisplay**|Passkey Entry (I displays, R inputs)|Numeric Comparison|Passkey Entry (R displays, I inputs)|Just Works|Numeric Comparison|

**Just Works**: This method is used when one or both devices do not have a user interface that allows entering or confirming a passkey. Encryption is enabled so the connection is protected against passive eavesdropping, but MITM protection is not available since no identifying information is available. If this method is used, it is recommended to enable bonding only for short periods of time.

**Passkey Entry**: This method requires a passkey to be entered on one of the devices and displayed on the other. This method allows MITM to be enabled. It is recommended to allow the stack to generate random passkeys.

**Numeric Comparison**: This method requires that both devices display a passkey and give the user some method for confirming that the passkeys match. This is the most secure method and should be used if the I/O capabilities support it.

The logical flow in each pairing association model between the initiator and the responder is documented in [pairing processes](https://docs.silabs.com/bluetooth/latest/bluetooth-security-pairing-processes/).

###### Out of Band Pairing/Bonding (heading level 7)

Out-of-band (OOB) pairing can be used to establish a security relationship by exchanging information through a method other than Bluetooth, such as NFC. Devices that do not have a user interface can use OOB pairing to establish MITM protection through authentication and should do so whenever possible. If OOB data is not available from both devices (or legacy OOB used), the data needs to be kept secret. If OOB data is available from both devices, it does not need to be kept secret.

###### External Bonding Database (heading level 7)

While using the external bonding database, the secure storage of the encryption keys is the responsibility of the application. For SoC case, refer to [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/) about how to import the keys to the secure key storage.

Note that some of the sensitive keys like the Long Term Key (LTK) generated after a pairing process are not always exportable and are totally managed and used by the stack.

For NCP projects the keys are usually stored on the host, so the communication between the target and the host needs to be encrypted. Silicon Labs provides two solutions for that: you can either use the “Secure NCP” feature to encrypt the serial connection, or you can use the NCP over CPC feature, and use a secured CPC channel (for details see [Using the Bluetooth Stack in Network Co-Processor Mode](https://docs.silabs.com/bluetooth/latest/bluetooth-network-coprocessor-mode/)).

When the Bluetooth stack needs bonding data, it will send the request to the user application with a sl_bt_evt_external_bondingdb_data_request event that contains the requested data type. The application must respond to the request by sending data using the command [sl_bt_external_bondingdb_set_data](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-external-bondingdb) for setting the external bonding data.

To enable support for the external bonding database, install the External Bluetooth bonding database software component as shown here:

![External bluetooth bonding database](/bluetooth-application-security-design-considerations/0.1/images/sld814-image2.png)

###### Other Stack Security Features (heading level 7)

**Disconnecting on Failed Bond Creation**. The Bluetooth specification does not require a connection to be closed after a failed bonding attempt, but it is a good idea. A failed bonding may indicate that an attacker is attempting to guess the passkey. An unsuccessful bonding attempt causes the stack to raise the [sl_bt_evt_bonding_failed](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-evt-sm-bonding-failed) event. This event indicates the connection used in the failed attempt as well as a reason for the failure. The status codes are documented in the [Platform API Reference](https://docs.silabs.com/gecko-platform/latest/platform-common/status). The connection can be closed with a call to [sl_bt_connection_close()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-connection#sl-bt-connection-close).

**Disable Bonding Except When Needed**. Leaving bondable mode enabled always is unnecessary and may make it easier for an attacker to establish a trusted relationship with your device. For this reason, it is recommended to limit the length of time that new bonds can be formed, either a short duration after power-up or by requiring some user action such as a button press to enable bondable mode. The bondable mode is set by a call to [sl_bt_set_bondable_mode()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-sm#sl-bt-sm-set-bondable-mode).

**Minimum Key Size for Bonding**. It is possible to set the minimum key size required for bonding using [sl_bt_sm_set_minimum_key_size()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-sm#sl-bt-sm-set-minimum-key-size). It is recommended to use the default, largest setting of 16 bytes.

**Bonding Configuration**. The maximum number of bonds can be set from 1 to 32. The bonding policy determines what happens when the bonding table is full. It is recommended to use policy 0 – new bonding attempts fail. It is better for the application to explicitly delete bonds that are no longer needed. use |[sl_bt_store_bonding_configuration()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-sm#sl-bt-sm-store-bonding-configuration) to set the number of bonds and the bonding policy.

###### Coexistence with Wi-Fi

Designs using PTA for managed coexistence with Wi-Fi should take precautions against attacks against the PTA interface. Such attacks may include Denial-of-service and information disclosure. If the Wi-Fi PTA master is compromised, channel access may never be granted. One possible solution is to disable the PTA interface if channel access is denied for extended periods of time. The coexistence API includes counters to determine the number of times channel access is denied or aborted and is documented in this section of the [Bluetooth API Reference](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-coex). See [Bluetooth Coexistence with Wi-Fi](https://docs.silabs.com/bluetooth/latest/bluetooth-coexistence-with-wifi/) for more detailed information.

##### Privacy and Tracking

This section discusses privacy for mobile Bluetooth Low Energy devices.

Many Bluetooth Low Energy devices will be wearable or other mobile devices. If the device is constantly advertising the same address, it is easy for the device’s location to be tracked.

###### Bluetooth Address Types

The Bluetooth specification defines several address types that are defined below. All Bluetooth addresses are 48 bits in length.

**Identity Address**: a type of address that can be used in forming a new bond. Either public addresses or random static addresses qualify as identity addresses.

**Public address**: A device’s public address is usually derived from the hardware and does not change over time.

**Resolvable private address**: This address type is random but can be resolved by a bonded device in possession of an identity-resolving key (IRK).

**Non-resolvable private address**: This is a completely random address that is only used in non-connectable advertising. The identity address cannot be determined by observers if they only know the non-resolvable private address.

**Random Static address**: All but the two upper-most bits are random. A new random static address may be chosen after a power cycle event.

**Anonymous**: Bluetooth 5.x style extended advertising supports the ability to advertise without any address being sent along with the advertising payload.

###### LE Privacy (heading level 7)

LE Privacy is a feature that was introduced in Bluetooth 4.1. When this feature is enabled, a new resolvable private address is chosen periodically by the stack. LE Privacy can be enabled by calling [sl_bt_gap_set_privacy_mode()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-gap#sl-bt-gap-set-privacy-mode). It is recommended to use this feature on devices where tracking is a concern.

###### Device Privacy (heading level 7)

When a device is in device privacy mode, it is only concerned about its own privacy. It should accept advertising packets from peer devices that contain their Identity Addresses as well as their private address, even if the peer device has distributed its IRK.

###### Network Privacy (heading level 7)

When a device is in network privacy mode, it shall not accept advertising packets containing the Identity Address of peer devices that have distributed their IRK; that is, only resolvable private address (RPA) is accepted for peer devices that have distributed their IRK.

If the Resolvable Private Address Only characteristic is not present in the GAP service of the remote device, it may use its Identity Address over the air.

###### Working with LE Privacy (heading level 7)

###### Address Resolving List (heading level 8)

Silicon Labs Bluetooth stack maintains an address resolving list for devices using LE privacy. Devices can be referred to by the bonding handle or by address. It is documented in the section Address Resolving List of the  [Bluetooth API Reference](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-resolving-list).

- Bonding Handle  
  Adding a device to the address resolving list requires the bonding handle and privacy mode of the device. The privacy mode setting indicates whether the local device uses device privacy or network privacy for the remote device. Removing a device through its bonding handle only requires the bonding handle. Note: deleting the bonding does not remove the device from the address resolving list nor from the filter accept list.
- Address  
  Adding a device to the address resolving list by its address requires the identity address of the device, the type of address, device’s IRK, and the privacy mode. The privacy mode setting indicates whether to use device privacy or network privacy for the peer device. Removing a device from the address resolving list requires the address to be removed and the address type.

###### Filter Accept List and Advertisement Filtering (heading level 8)

Silicon Labs’ Bluetooth stack maintains a filter accept list which can used to filter out advertisements from any device that is not in the list. As with the address resolving list, devices can be added and removed from the filter accept list either by bonding handle or by address. The filtering policy can be set by using the [sl_bt_scanner_set_parameters_and_filter()](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-scanner#sl-bt-scanner-set-parameters-and-filter) API function.

- Bonding Handle  
  Devices can be added to the filter accept list using the [bonding handle](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-accept-list#sl-bt-accept-list-add-device-by-bonding).
- Address  
  Devices can be added to the filter accept list using the [peer address and the address type](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/sl-bt-accept-list#sl-bt-accept-list-add-device-by-address).

> **Note**: Series 1 devices may not support LE Privacy Feature 1.2v as it was introduced with core specification v4.2 onwards.

##### Application Layer Security

Relying entirely on Bluetooth security features also means relying on the security of the peer device’s Bluetooth stack. Doing so introduces additional unknowns. As well as the potential of unpatched vulnerabilities in an unknown stack, the remote device may share the Bluetooth connection with multiple applications. This can lead to compromised integrity and/or confidentiality. The solution to this problem is for the application to form a secure link on top of the Bluetooth connection by establishing an authenticated, shared secret key and encrypting data with that key before sending it over the Bluetooth connection. This section discusses the key components involved in using application layer security: authentication, key agreement, key derivation, and encryption.

###### Secure Identity

A common problem with small IoT devices is that they have no user interface to authenticate the device’s identity, such as entering or confirming a passkey. A device that cannot be authenticated is unable to take advantage of man-in-the-middle (aka machine-in-the-middle) protection. One solution to this problem is to use secure identity certificates to uniquely identify a device. A signed certificate chain, along with the corresponding private signing key, is stored on the device. The device’s certificate chain can be sent over the Bluetooth LE GATT to the peer device to authenticate its identity. More information on secure identity certificates is available in [Authenticating Silicon Labs Devices Using Device Certificates](https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/). The communication flow is illustrated in the following figure.

![Exchanging Certificate Chains to Authenticate Device Identity](/bluetooth-application-security-design-considerations/0.1/images/sld814-image3.png)

###### Key Agreement (heading level 7)

An important step in securing data at the application is for the two peer devices is to establish a shared secret. The accepted method for doing so is by ECDH as mentioned earlier. A brief description is found at [https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman). To perform ECDH over Bluetooth Low Energy, GATT characteristics can be set up to store the public key for each device and then the keys exchanged like any other data. To ensure that keys have come from a trusted source, they can be signed with the sender’s secure identity key. Once the public keys have been exchanged, a shared secret can be computed. A key derivation function is usually applied rather than using the shared secret directly.

![Authenticated Key Agreement](/bluetooth-application-security-design-considerations/0.1/images/sld814-image4.png)

###### Key Derivation Function (heading level 7)

A key derivation function takes a shared secret and transforms it to introduce some additional entropy, or randomness. A typical method for deriving keys is by using a cryptographically-secure hash such as SHA-2/256. Silicon Labs series 2 devices also provide hardware acceleration for other key derivation functions such as PBKDF2 and HKDF. Derived keys with persistent storage should be stored using the most secure method available. Secure Vault High parts can wrap, or encrypt, keys. See [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/)for more information on this topic.

###### Application Layer Encryption

This section describes the encryption of user data before it is passed to the Bluetooth stack to be sent to a peer device.

###### Encrypting and Authenticating Data (heading level 7)

Once a shared secret has been established and symmetric keys derived, sensitive data can be encrypted/decrypted and authenticated. Several cipher modes are accelerated in hardware.

**Counter with Cipher Block Chaining Mode (CCM)**. This cipher mode combines a counter with CBC-MAC to provide several benefits. It is possible to authenticate both encrypted and unencrypted data in the same message, known as authenticated encryption of associated data (AEAD). A unique initialization vector is required for each message sent. A brief description is found at [https://en.wikipedia.org/wiki/CCM_mode](https://en.wikipedia.org/wiki/CCM_mode). When this mode is used, the data, initialization vector and authentication tag can be sent together in a single block

**Galois Counter Mode (GCM)**. This cipher mode is like CCM described above but uses a different method for authenticating data and lends itself to parallelization. A brief description is found at [https://en.wikipedia.org/wiki/Galois/Counter_Mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode). As with CCM, the initialization vector, data and authentication tag can be sent together in a single block.

###### Encryption-Only Cipher Modes (heading level 7)

Encryption-only cipher modes are also supported in Silicon Labs series 2 devices in case authentication is not desired. The reference manual for your chosen device documents all cipher modes accelerated in hardware.

###### Application Layer Encryption Example (heading level 7)

The example accompanying this application note, available on [https://github.com/SiliconLabs/bluetooth_applications](https://github.com/SiliconLabs/bluetooth_applications) , demonstrates a method for implementing application layer encryption with authenticated key exchange using device identity certifications. Two projects are included: one for the client and the other for the server. The communication flow is summarized in the following table.

|Client|Initiator|Server|
|---|---|---|
|**Certificate Chain Exchange**| | |
|Scans for devices advertising Secure Attestation service|@Manually needed Symbol @Manually needed Symbol|Advertises Secure Attestation service|
|Connects to server and requests connection be encrypted with JustWorks pairing|@Manually needed Symbol @Manually needed Symbol|Accepts and encrypts connection|
|Reads Device and Batch certificates from Server|@Manually needed Symbol @Manually needed Symbol|Sends Device and Batch certificates|
|Verifies server’s certificate chain and sends random challenge|@Manually needed Symbol @Manually needed Symbol|Signs random challenge with private device key and returns signature|
|Verifies the server’s signature, saves the public key, and sends Device and Batch certificates|@Manually needed Symbol @Manually needed Symbol|Saves Device and Batch certificate, verifies client’s certificate chain, and sends random challenge|
|Signs random challenge and returns signature|@Manually needed Symbol|Verifies client’s signature, and saves the public key.|
|**ECDH Key Exchange**| | |
|Generates ECDH keypair and signs with private device key| |Generates ECDH keypair and signs with private device key|
|Requests signed ECDH public key from server|@Manually needed Symbol @Manually needed Symbol|Sends signed ECDH public key to client|
|Receives and verifies Server’s signed public key. Sends signed public key to server|@Manually needed Symbol @Manually needed Symbol|Receives and verifies Client’s signed public key|
|**AES Operation**| | |
|Derives AES key using SHA2/256-based function| |Derives AES key using SHA2/256-based function|
|Requests encrypted message from server|@Manually needed Symbol @Manually needed Symbol|Encrypts sample message using AES key and sends to client|
|Decrypts message using AES key| |Idle|

The characteristics used in this communication flow are summarized the following table.

|Attribute Name|Description|
|---|---|
|Device Certificate|The server’s device identity certificate|
|Batch Certificate|The server’s batch certificate|
|Peer Device Certificate|The client’s device identity certificate|
|Peer Batch Certificate|The client’s batch certificate|
|Server public key|Server’s ECDH public key|
|Client public key|Client’s ECDH public key|
|Challenge|Random challenge|
|Response|Signature of the random challenge|
|Test_data|Test data to encrypt|

###### Other Application Security Concerns

Beyond using the security features incorporated into the Bluetooth specification itself, an application can take several steps to implement higher security.

A common type of attack relies on buffer overflows. For this reason, it is highly recommended that applications validate the size of data being received before attempting to store it. Whether a block of data is received through a notification/indication, write or a response to a read request, the size of the data received is always reported by the stack. The size parameter must be used to determine if the application has reserved sufficient space to store it.

###### Secure Boot

The ability to ensure that authentic firmware is running on the device is possibly one of the most valuable security features available. Many attacks rely on the attacker’s ability to gain control of the device by some method such as remote code injection. Silicon Labs’ secure boot with root of trust secure loader (RTSL) provides additional security by verifying the authenticity of the firmware using an [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) digital signature and an immutable public key stored on the device. See [Series 2 and Series 3Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) for specifics on using secure boot.

###### Signed and Encrypted Firmware Updates

One concern with over-the-air (OTA) updates is that the firmware could be stolen by sniffing the Bluetooth connection, since the Silicon Labs AppLoader does not support encrypted connections. The solution is to encrypt the firmware image itself and allow the bootloader on the device to be updated to perform the decryption. Firmware images can also be signed to prevent inauthentic images from being flashed into active memory in the first place. The signature of the update images is verified using the device public signing key.

###### Subscribe to Security Advisories

Silicon Labs recommends that all customers subscribe to security advisories to be aware of the latest threats and mitigations. See [www.silabs.com/security](https://www.silabs.com/security) for instructions.

###### Additional Reading

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/">IoT Endpoint Security Fundamentals</a></p>
            </td>
            <td>
                <p>Introduces the security concepts that must be considered when implementing an Internet of Things (IoT) system</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

#### IV Update in a Bluetooth Mesh Network

##### IV Update in a Bluetooth® Mesh Network

> **NOTE: This section replaces _AN1318: IV Update in a Bluetooth® Mesh Network_. Further updates to this application note will be provided here**.

This application note provides background information on the sequence number and IV index in a Bluetooth mesh network and the IV Update and IV Index Recovery procedures. It then discusses how to implement IV Update functionality in a Bluetooth mesh application.

###### Key Points

- Short introduction to Bluetooth mesh security and replay attacks
- Sequence number and IV index
- IV Update procedure
- IV Index Recovery procedure
- Bluetooth mesh APIs for IV update and recovery

##### Introduction

Security is mandatory in Bluetooth mesh and cannot be switched off or reduced in any way. The network security, application security, and device security are all addressed independently. Security in Bluetooth mesh networking protects against various threats and issues, including:

- Replay attacks, which are prevented by judicious use of sequence numbers.
- Man-in-the-middle attacks, which are protected against by using asymmetrical cryptography, such as the Elliptic Curve Diffie-Hellman (ECDH) key agreement protocol, during provisioning of a new device into the network.
- Trash-can attacks, which exploit discarded devices, by ensuring security keys get refreshed when necessary.

A replay attack is a technique whereby an eavesdropper intercepts and captures one or more messages and simply retransmits them later, with the goal of tricking the recipient into carrying out something which the attacking device is not authorized to do. An example, commonly cited, is that of a car’s keyless entry system being compromised by an attacker, intercepting the authentication sequence between the car’s owner and the car, and later replaying those messages to gain entry to the car and steal it.

Bluetooth mesh has protection against replay attacks. The basis for this protection is the use of two cryptographic values in the mesh network called the Sequence Number (SEQ) and IV Index, respectively. Nodes keep track of the sequence numbers in the messages they receive, and together with the IV index of the network can detect and discard replayed messages.

###### Prerequisites

You should have:

- A general understanding of Bluetooth mesh concepts such as nodes and elements.
- Installed and be familiar with using the following:
- Simplicity Studio v5.0.0 or above
- Bluetooth Mesh SDK v2.0.0 or above

If you need to familiarize yourself with any of these concepts, the following may be useful:

- [Bluetooth Mesh Networking - An Introduction for Developers](https://www.bluetooth.com/wp-content/uploads/2019/03/Mesh-Technology-Overview.pdf)
- [QSG176: Bluetooth® Mesh SDK v2.x Quick-Start Guide](https://www.silabs.com/documents/public/quick-start-guides/qsg176-bluetooth-mesh-sdk-v2x-quick-start-guide.pdf)

##### Sequence Number and IV Index

A Nonce is a number which may only be used once. Each time a message is encrypted, it is given a new nonce value. The nonce has various parts to it, including a sequence number and a value known as the IV Index. To ensure nonce values are unique for each new message encryption, the sequence number inside a nonce must not be allowed to wrap around while IV index remains unchanged.

The sequence number is a 24-bit value that allows an element to transmit 16,777,216 messages before repeating a nonce. If an element transmits a message on average once every second, then these sequence numbers would be exhausted after 194 days. To enable a mesh network to operate for longer periods of time than the sequence number space allows, an additional 4-octet value called the IV (Initialization Vector) Index is defined that is included in the security nonce.

The IV Index is a 32-bit value that is a shared network resource (that is, all nodes in a mesh network share the same IV Index value and use it for all subnets they belong to). Its purpose is to provide entropy (randomness) in the calculation of message Nonce values. At the same frequency of one message every second, the lifetime of the network using the IV Index would measure in billions of years.

Read the Bluetooth Mesh Profile Specification v1.0.1 for further information.

Before the sequence number approaches the maximum value (0xFFFFFF), the element updates the IV Index using the IV Update procedure. The IV Index starts at 0x00000000 and is incremented during the IV Update procedure.

###### Sequence Number Increments

Each element increases the sequence number by one for every Network Protocol Data Unit (PDU) sent out to the network. The sequence number must be stored in non-volatile memory to ensure the sequence numbers that have been used will not be reused. However, writing every sequence number increment to flash memory is likely too many writes and would probably wear out flash memory during the lifetime of a product. The solution for this issue depends on Bluetooth mesh stack implementations.

In our implementation, the stack stores the sequence number in flash memory at a fixed interval when the sequence number is a multiple of a configurable value. Given that a device may lose power unexpectedly during the interval, the stored sequence number may be behind the sequence number actually used last, and using the stored value directly would lead to sequence number reuse. To avoid using the sequence numbers that have been used, the stack increases the stored sequence number by the configured interval value on a reset. The stack won’t increase the sequence number if the increment of the stored sequence number was 0.

The stack will not transmit any Network PDUs from an element if its sequence number has reached the max value 0xFFFFFF. A node should initiate the IV Update procedure whenever it determines it is at risk of exhausting its sequence number values within a maximum of 96 hours, or if it determines that another node is in this situation.

###### IV Update Procedure

The IV Update procedure should be performed before the sequence number is exhausted. The procedure updates the IV index to a new value that will be used for subsequent communication in the mesh network. Once the IV Update procedure completes, the sequence number is reset to 0 on every element of every node in the network.

The IV Update procedure is initiated by any node in a primary subnet. If a node on a primary subnet receives an update on the primary subnet, it propagates the IV update to all other subnets. If a node on a primary subnet receives an IV update on any other subnet, the update is ignored.

The IV Index is shared within a mesh network via Secure Network beacons. IV updates received on a subnet are processed and propagated to that subnet. The propagation happens by the node transmitting Secure Network beacons with the updated IV Index for that particular subnet. A node that receives an IV update may or may not be able to update its IV index depending on the IV Update procedure state and the time since the last IV update.

- When a node is added to a mesh network, it is in the Normal Operation state. During the Normal Operation state, the IV Update Flag in the Secure Network beacon and in the Friend Update message is set to 0.
- After 96 hours of operating in the Normal Operation state, a node may initiate the IV Update procedure by transitioning to the IV Update in Progress state. When a node transitions from the Normal Operation state to the IV Update in Progress state, the IV Index on the node is incremented by one.
- During the IV Update in Progress state, the IV Update Flag in the Secure Network beacon and in the Friend Update message is set to 1.
- A node in the Normal Operation state receives a Secure Network beacon with the IV Update Flag set to 1 and an IV index equal to its current IV index + 1. The node then transitions to the IV Update in Progress state and updates its current IV index.
- After at least 96 hours and before 144 hours of operating in the IV Update in Progress state, the node transitions back to the Normal Operation state and resets its sequence number to 0x000000.
- A node must not start an IV Update procedure more often than once every 192 hours.

Read Section 3.10.5 of the Bluetooth Mesh Profile Specification v1.0.1 for further information.

###### IV Index Recovery Procedure

If a node is absent from a mesh network for a period of time, it may have missed IV index updates and is not able to communicate with other nodes. In this case, the node can scan for a Secure Network beacon, which contains the Network ID and the current IV Index, to recover the IV index. The IV Index Recovery procedure sets the current IV index and the IV Update procedure state of a node from the values in the Secure Network beacon.

- A node in the Normal Operation state receives a Secure Network beacon with an IV index greater than its current IV index + 1. It then may initiate an IV Index Recovery procedure.
- A node in the Normal Operation state receives a Secure Network beacon with the IV Update Flag set to 0 and an IV index equal to its current IV index + 1. It then may update its IV index without going to the IV Update in Progress state, or it may initiate an IV Index Recovery procedure, or it may ignore the Secure Network beacon. The node makes the choice depending on the time since the last IV update.
- After the IV Index Recovery procedure has updated the IV Index, the 96-hour time limits for changing the IV Update procedure state, as defined in the IV Update procedure, do not apply.
- A node must not execute more than one IV Index Recovery procedure within a period of 192 hours.
- A node in the Normal Operation state receives a Secure Network beacon with an IV index less than its current IV index or greater than its current IV index + 42. It ignores the Secure Network beacon. This allows a node to be away from the mesh network for 48 weeks. A node that is away from a network for longer than 48 weeks must be reprovisioned.

Read Section Bluetooth Mesh Profile Specification v1.0.1 for further information.

###### IV Update Procedure Example

A summary of the IV Update procedure is provided in the table below.

|IV Index|IV Update Flag|IV Update Procedure State|IV Index Accepted|IV Index used when transmitting|
|---|---|---|---|---|
|n|0|Normal|n-1, n|n|
|m (m=n+1)|1|In Progress|m-1, m|m-1|
|m|0|Normal|m-1, m|m|

The following example illustrates the transition of the IV Update procedure state and IV index updates in the IV Update procedure. It will help explain the table above. You will also see from this example that the nodes before, during and after the IV Update procedure are able to communicate based on their Tx and Rx IV indices.

1. Node A and B are in the Normal Operation state and have the IV index 80 (n = 80, IV Update Flag = 0).  
   ![Example 1](/btmesh-iv-update/10.0.0/images/sld820-image1.png)
2. Node A initiates the IV Update procedure and then Node B performs the IV Update procedure (m = 81, IV Update Flag = 1).  
   a) Node A transitions to the IV Update in Progress state and increments its IV index by 1.  
   b) Node B receives a Secure Network beacon with IV index = 81 and IV Update Flag = 1, transitions to the IV Update in Progress state and increments its IV index by 1.  
   ![Example 2](/btmesh-iv-update/10.0.0/images/sld820-image2.png)
3. Node A and B transition to the Normal Operation state (m = 81, IV Update Flag = 0).  
   a) Node A transitions to the Normal Operation state.  
   b) Node B receives a Secure Network beacon with IV index = 81 and IV Update Flag = 0 and transitions to the Normal Operation state.  
   ![Example 3](/btmesh-iv-update/10.0.0/images/sld820-image3.png)

##### IV Update Functionality Implementation

The IV Update procedure described in [IV Update Procedure](02-sequence-number-and-iv-index#iv-update-procedure) and the IV Index Recovery procedure described in [IV Index Recovery Procedure](02-sequence-number-and-iv-index#iv-index-recovery-procedure) have been implemented in the Bluetooth mesh stack. However, the stack cannot determine how long the remaining sequence numbers might last. The application should determine when a node may run out of sequence numbers and should initiate the IV Update procedure before sequence numbers are exhausted. If a node is absent from a mesh network for a period of time, the application should enable IV index recovery mode to set the IV Index value autonomously.

Secure network beacons are used to carry required information and are transmitted in the primary network. The nodes in the primary network that need to request IV index updates must enable secure network beacon broadcasting. This is usually configured by the provisioner. Note that some Bluetooth mesh mobile applications may not support configuration of the secure network beacon state. The application can call the `sl_btmesh_test_set_beacon()` API to set the state locally.

The following is a summary of the items that should be included in your system to implement IV Update functionality properly:

- Secure network beacons enabled on nodes.
- Code to track time across resets and set the time since the last IV update at booting.
- Code to determine sequence number exhaustion and trigger an IV index update.
- Code to check the network IV index and handle IV index recovery mode.

See the [Silicon Labs Bluetooth Mesh API Reference Manual](/btmesh/11.0.0/bluetooth-mesh-api) for all the BGAPI information.

###### Tracking Time Across Resets

The stack uses a timer to calculate the duration required to execute an IV Update or IV Index Recovery procedure. The timer is maintained in RAM and is reset whenever the device resets. This may cause an IV Update or IV Index Recovery procedure to execute later than expected. IV updates would not occur if frequent resets or power cycles are encountered in the application.

The application should track time across resets or power cycles. This is usually done by storing the time in flash memory regularly. The application then should call the following API to set the timer in the stack.

- `sl_btmesh_node_set_iv_update_age()`

The stack generates the following event when the IV Update procedure state has changed. If you did not call the `sl_btmesh_test_set_ivupdate_state()` API to change the state forcefully, this event indicates the IV Update procedure is ongoing (the value of the state is 1) or an IV update has completed (the value of the state is 0). The timer in the stack is reset to 0 when an IV update completes. The application should synchronize the time with the timer on this event when the value of the state is 0.

- `sl_btmesh_evt_node_changed_ivupdate_state_id`

###### Determining Sequence Number Exhaustion

As described in [Sequence Number Increments](02-sequence-number-and-iv-index#sequence-number-increments), the stack uses an interval value to determine sequence number storing and to add to the stored sequence number on a reset. The interval value can be configured via the SL_BTMESH_CONFIG_SEQNUM_WRITE_INTERVAL_EXP macro in the sl_btmesh_config.h header file or on the user interface, accessible via `SOFTWARE COMPONENTS > Bluetooth Mesh > Stack > Bluetooth Mesh Stack > Configure > Element sequence number write interval exponent`. You may decrease the value if the device resets or power cycles regularly.

Every element of a node keeps a sequence number counter. The application should call the following APIs to get the number of remaining sequence numbers or the current sequence number of an element.

- `sl_btmesh_node_get_seq_remaining()`
- `sl_btmesh_node_get_element_seqnum()`

The maximum value of the sequence number is 0xFFFFFF. The application should know how often messages are transmitted to the network and therefore be able to determine if any element is about to exhaust its available sequence numbers. The application then should request the stack to initiate the IV Update procedure. The application must ensure the available sequence numbers can run for at least 96 hours when initiating the IV Update procedure. This time period can be extended to a safe period due to regular device resets or irregularity of message transmission.

###### Initiating IV Update

The application should call the following API to request the stack to initiate the IV Update procedure.

- `sl_btmesh_node_request_ivupdate()`

The `sl_btmesh_evt_node_changed_ivupdate_state_id` event is generated when the IV Update procedure has started or completed. The application can use this event to monitor the IV Update procedure state and the current IV index.

###### Recovering IV Index

The application should call the following API to enable the IV index recovery mode.

- `sl_btmesh_node_set_ivrecovery_mode()`

The IV index recovery mode should be enabled when the node may have missed IV index updates and need to perform the IV Index Recovery procedure. In this case, the following event is generated. The application should check the received network IV index and the current IV index that come with the event and enable the IV index recovery mode only when the received network IV index is greater than the current IV index and is equal to or less than the current IV index + 42.

- `sl_btmesh_evt_node_ivrecovery_needed_id`

If a real time clock is available in the device, the application can also check the IV index increment with the time elapsed. The time since the last IV update should be greater than the IV index increment multiplied by 192 hours minus 96 hours.

The `sl_btmesh_evt_node_changed_ivupdate_state_id` event is generated when the IV Index Recovery procedure has completed. The application should disable the IV index recovery mode on this event.

###### IV Update Testing

There are time limits on the IV Update and IV Index Recovery procedures so testing on Bluetooth mesh applications would be inefficient. The IV Update test mode removes these time limits. The application can call the following API to enable the IV Update test mode.

- `sl_btmesh_test_set_ivupdate_test_mode()`

The following APIs may be useful when testing the IV Update functionality.

- `sl_btmesh_test_set_ivupdate_state()`: forces the node to transition to the IV Update in Progress state or to the Normal Operation state.
- `sl_btmesh_test_set_iv_index()`: changes the node's current IV index to any value.
- `sl_btmesh_test_set_beacon()`: enables or disables Secure Network Beacons broadcasting.
- `sl_btmesh_node_set_beacon_reporting()`: enables reporting to monitor secure network beacons. This can be used to diagnose the network IV index and the IV Update procedure state.

###### Btmesh Automatic IV update Component

To enhance the developer experience, Silicon Labs provides a dedicated component for SoC projects to automatically take care of the following:

- Periodic IV Update age backup. Restore on reset.
- Automatic IV Update request, if a sequence number exceeds a threshold.
- Automatic IV Update request, after a configured time in Normal operation.

![screenshot](/btmesh-iv-update/10.0.0/images/sld820-image4.png)

This is a no-code component latching onto the relevant events and handling the IV Update based on the user-defined parameters:

<table>
    <thead>
        <tr>
            <th>Configuration Option</th>
            <th>Description</th>
            <th>Default Value</th>
            <th>Range</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="4">General</th>
        </tr>
        <tr>
            <td>Enable logging</td>
            <td>Enable logging</td>
            <td>1</td>
            <td>0/1</td>
        </tr>
        <tr>
            <td>Automatic transition to IV Update Recovery mode</td>
            <td>Automatic transition to IV Update Recovery mode</td>
            <td>1</td>
            <td>0/1</td>
        </tr>
        <tr>
            <th>Backup of IV Update age</th>
            <th>Backup of IV Update age</th>
            <th>1</th>
            <th>0/1</th>
        </tr>
        <tr>
            <td>NVM key of the iv Update age (hexadecimal)</td>
            <td>NVM key of the iv Update age (hexadecimal)</td>
            <td>0x3000</td>
            <td></td>
        </tr>
        <tr>
            <td>IV Update age backup period in seconds</td>
            <td>IV Update age backup period in seconds</td>
            <td>300</td>
            <td>0-4294967</td>
        </tr>
        <tr>
            <th>IV Update by age</th>
            <th>IV Update by age</th>
            <th>1</th>
            <th>0/1</th>
        </tr>
        <tr>
            <td>IV Update Timeout</td>
            <td>IV Update Timeout</td>
            <td>345600</td>
            <td>345600-4294967</td>
        </tr>
        <tr>
            <th>IV Update by sequence number</th>
            <th>IV Update by sequence number</th>
            <th>1</th>
            <th>0/1</th>
        </tr>
        <tr>
            <td>Sequence number threshold</td>
            <td>When any element's sequence number gets above this, an IV Update is requested.</td>
            <td>0x700000</td>
            <td>0-16777215</td>
        </tr>
        <tr>
            <td>Sequence number testing period in seconds</td>
            <td>Sequence number testing period in seconds</td>
            <td>10</td>
            <td>0-4294967</td>
        </tr>
    </tbody>
</table>

![screenshot](/btmesh-iv-update/10.0.0/images/sld820-image5.png)

##### Additional Resources

Consult the following resources for additional information.

- [QSG176: Bluetooth® Mesh SDK v2.x Quick-Start Guide](https://www.silabs.com/documents/public/quick-start-guides/qsg176-bluetooth-mesh-sdk-v2x-quick-start-guide.pdf)
- Silicon Labs Bluetooth Mesh API Reference Manual
- [Bluetooth Mesh Networking - An Introduction for Developers](https://www.bluetooth.com/wp-content/uploads/2019/03/Mesh-Technology-Overview.pdf)
- Bluetooth Mesh Profile Specification v1.0.1

#### Series 2 and Series 3 Secure Debug

##### Series 2 and Series 3 Secure Debug

> **Note: This section replaces _AN1190: Series 2 and Series 3 Secure Debug_. Further updates to this application note will be provided here**.

To protect intellectual property and proprietary algorithms from malicious actors, it is important to lock the debug port. This prevents attackers from reading flash contents through the debug  interface  and  reverse  engineering  the application. However, there are situations where it becomes necessary to debug a device already deployed in the field. Silicon Labs Series 2 and 3 devices offer a feature called Secure Debug. This feature allows only authenticated users to unlock the debug port and securely debug the application.

This application note explains the different debug lock and unlock features available in Series 2 and Series 3 devices and their capabilities.

###### Key Points

- Basic overview of the Secure Engine
- Debug port access by Debug Challenge Interface (DCI) or Mailbox Interface
- Locking and unlocking features for Series 2 and Series 3 devices
- Examples for Public Command Key provisioning and Secure Debug Unlock

> **Note**: This application note covers both Series 2 and Series 3 devices. Unless explicitly stated otherwise, all items are applicable to both. If an item is not applicable to one of the series, it will be mentioned separately.

##### Series 2 and Series 3 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. 'Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. Series 3 devices further enhanced these capabilities, offering more advanced security features than their Series 2 counterparts. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based or virtual (software-based). Throughout this application note, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level**|**SE Support**|
|---|---|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|
|Secure Vault Mid (SVM)|HSE (HSE-SVM), VSE (VSE-SVM)|
|Secure Vault Base (SVB)|N/A|

**Notes**:

1. Series 3 devices have no secure vault Base and Mid devices. All devices are Secure Vault High.
2. Refer to [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/11-series-2-device-security-features) for details on supporting devices.

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug Access Control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High (SVH) offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper Protection**: A configurable module to protect the device against tamper attacks.
- **Device Authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products, Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Series 2 and Series 3 Secure Debug (this application note)</p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|
|Certificate Key (Used for generating Debug lock token)|Yes|Device authentication token which enabling debug lock port|

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 and Series 3 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 and Series 3 devices and modules.

##### Introduction to Secure Debug

###### Debug Lock

All Silicon Labs Series 2 and Series 3 devices have the capability to lock debug access to the device. This prevents attackers from using the debug interface to perform the following illegal operations:

- Reprogramming the device
- Interrogating the device
- Interfering with the operation of the device

A fairly standard practice during the board-level test in production is to program, test, and lock the parts. Three different locks can be enabled on debug interface:

- Standard debug lock
- Secure debug lock
- Permanent debug lock

Silicon Labs provides Custom Part Manufacturing Service (CPMS) to securely configure the debug port of the chip to one of the three possible locks before the devices leave the factory.

###### Debug Unlock

Users need to unlock parts under a number of circumstances:

- Code development
- Field failure diagnosis
- Product field service
- Existing inventory reprogramming

Two different unlocks can run on debug interface:

- Standard debug unlock
- Secure debug unlock

##### Secure Engine Subsystem

###### Overview

The HSE refers to a separate security co-processor that provides hardware isolation between security functions and the host processor.

The VSE refers to a collection of security functions available to the host processor in Root mode if a separate security co-processor is not provided.

The SE is used to perform a series of cryptographic operations and other secure system operations as described in the following table.

|**Operation**|**VSE-SVM**|**HSE-SVM**|**HSE-SVH**|**Description**|
|---|---|---|---|---|
|Unique ID|Y|Y|Y|Software can identify every device.|
|Secure Boot with RTSL|Y|Y|Y|Only boot authenticated firmware.|
|Secure Debug|Y|Y|Y|Securely lock/unlock debug ports using authorized tokens|
|Crypto Engine (1)|Y|Y|Y|Up to 256-bit ciphers and elliptic curves.|
|TRNG (1)|Y|Y|Y|Generate keys for cryptography.|
|DPA Countermeasures|—|Y|Y|Resist side channel attacks.|
|Secure Key Storage|—|—|Y|Protected by PUF technology.|
|Secure Key Management|—|—|Y|Isolate encrypted keys from application code.|
|Secure Attestation|—|—|Y|Ensure integrity and authenticity.|
|Anti-Tamper|—|—|Y|Detect tamper and protect keys/data.|
|Advanced Crypto|—|—|Y|Up to 512-bit ciphers and P-521-bit elliptic curves.|

**Note**:

1. On VSE-SVM devices, the crypto engine and TRNG (True Random Number Generator) are implemented by the CRYPTOACC (Cryptographic Accelerator) peripheral.

To start using the secure debug unlock functionality, the device needs to be provisioned. These steps include writing one time programmable (OTP) settings to the SE to determine which functionality is enabled, and uploading the Public Command Key to validate a secure debug attempt.

This application note describes how different device debug locks and unlocks are implemented through the SE on Series 2 and Series 3 devices.

The secure debug feature is implemented by Root code executed by the HSE Core. For VSE devices secure debug feature is implemented by Cortex-M33 operating in Root mode.

Silicon Labs strongly recommends installing the latest SE firmware to support the required security features. The latest SE firmware image (`.seu` and `.hex`) and release notes can be found in the Windows folder mentioned below.

`C:\Users\\<userName\>\SimplicityStudio\SDKs\Simplicity_sdk\util\se_release\public`

###### Command Interface

Interaction with the SE is performed over a command interface. The command interface is available through a dedicated Debug Challenge Interface (DCI) as well as through a mailbox interface from the Cortex-M33.

Some commands may not be available at all times and may not be accessible over both interfaces. The DCI typically only contains operations for setting up a new device and for locking it down (meant for production processes), while the mailbox interface also contains commands to support cryptographic operations in HSE.

###### Mailbox (heading level 7)

The SE Manager Mailbox Interface is a mechanism used on Silicon Labs Series 2 and Series 3 devices to communicate with the Secure Engine (SE) for cryptographic and security operations. The mailbox interface allows the host processor (such as Cortex-M33) to send commands to the SE, typically for secure key storage, cryptographic operations, device provisioning, and secure identity management.

Secure Engine Manager (SE Manager) provides an abstraction of the Secure Engine's command set. The SE Manager also provides APIs for cryptographic operations and thread synchronization.

![SE Manager Mailbox interface](/series2-secure-debug/0.3/images/sld714-image17.png)

###### Debug Challenge Interface (DCI) (heading level 7)

The Debug Challenge Interface (DCI) is made available through commands in Simplicity Studio and Simplicity Commander. This is the easiest way to access and set up the different security options.

For more information about DCI, see [Programming Series 2 Devices using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/).

##### Debug Lock

###### Overview

The debug access port connected to the Series 2 and Series 3 device's Cortex-M33 processor can be closed by issuing commands to the SE, either from a debugger over DCI or through the mailbox interface. Three properties govern the behavior of the debug lock.

|**Property**|**Description If Set**|**Default Value**|
|---|---|---|
|Debug Lock|The debug port is kept locked on boot.|Disabled|
|Device Erase|The Erase Device command is available.|Enabled|
|Secure Debug|Secure debug unlock is available.|Disabled|

The following sections describe how to interact with these properties and how to enable debug locks using the SE command interface over DCI. The status of the debug lock can be inspected using the [Read Lock Status](#debug-lock-command-reference) command.

###### Standard Debug Unlock

The device is in standard debug unlock state if the debug lock properties are set to the default values.

|**Debug Lock**|**Device Erase**|**Secure Debug**|**Description**|
|---|---|---|---|
|Disabled|Enabled|Disabled|All debug operations are allowed.|

###### Standard Debug Lock

With the default properties in the table above, the device can be locked using the [Apply Lock](#debug-lock-command-reference) command. The typical flow for this configuration is simply to issue the Apply Lock command after the device has been programmed, either using a DCI command from the programming debugger or through the mailbox interface.

|**Debug Lock**|**Device Erase**|**Secure Debug**|**Description**|
|---|---|---|---|
|Enabled|Enabled|Disabled|The Erase Device command will wipe the main flash and RAM, and then a reset will yield an unlocked device.|

The standard debug lock disables debug access port, but issuing a device erase wipes the device and enables the debug port again.

###### Secure Debug Lock

For secure debug lock, the debug interface can temporarily be unlocked by answering a challenge, if the Secure debug property is enabled before locking.

|**Debug Lock**|**Device Erase**|**Secure Debug**|**Description**|
|---|---|---|---|
|Enabled|Disabled (2)|Enabled (1)|Secure debug lock is enabled, which makes it possible to securely open the debug lock temporarily to reprogram or debug a locked device.|

**Notes**:

1. Secure debug lock is enabled in two steps before the debug lock is enabled:  
   1. Install the Public Command Key using Simplicity Studio, Simplicity Commander, or directly through the SE Manager API.  
   2. Enable secure debug using Simplicity Studio, Simplicity Commander, or directly through the SE Manager APIs.
2. Disable the device erase using Simplicity Studio or Simplicity Commander or directly through the SE Manager API. This is an **Irreversible** action and should be disabled **After** the secure debug is enabled.
3. The **Device Erase** option should **Disabled** only during production. If this setting is applied during development, it prevents the device from being re-flashed with new firmware using a debugger and significantly hinders debugging efforts.

###### Secure Debug Unlock

To enable debugging or to reprogram the device, the debug port is temporarily opened. It automatically closes upon a power-on reset or device reset, and the device returns to the Secure Debug Lock state.

|**Debug Lock**|**Device Erase**|**Secure Debug**|**Description**|
|---|---|---|---|
|Enabled|Disabled|Enabled|Device debug port remains unlocked, till power on rest or device rest is performed.|

###### Permanent Debug Lock

The device can enter into **Permanent Debug Lock** state when both the **Device Erase** and **Secure Debug** properties are disabled.

|**Debug Lock**|**Device Erase**|**Secure Debug**|**Description**|
|---|---|---|---|
|Enabled|Disabled|Disabled|The part cannot be unlocked. Devices with Permanent Debug Lock engaged cannot be returned for failure analysis.|

###### Debug Lock State Transition

The following figure describes the transitions between different debug lock states.

![Debug Lock State Transition](/series2-secure-debug/0.3/images/sld714-debug-lock-state-transition.png)

1. Standard debug unlock can transit to **Standard Debug Lock** state, by enabling '**Debug Lock**' flag.
2. Standard debug lock can revert to **Standard debug unlock** via an erasedevice/device unlock command (erases the main flash and RAM). After the device is reset, the debug port remains unlocked until it is explicitly locked again.
3. Device can transit to **Secure Debug lock** state by enabling Secure Debug property.
4. Secure debug lock can use Debug Unlock Token to temporary transit to secure debug unlock, which does not erase the main flash and RAM but enables debug operations. The device reverts to the secure debug lock through a power on or pin reset.

5,6,7. From any state, device can transit to Permanent Debug lock by Disabling **Device erase** and **Secure debug**. This is terminal state and can not transit to any other state. This should be done only after development is completed.

> **Note**: Device can be brought back to "**Standard Debug unlock**" state from "**Secure Debug Lock**" state by erasedevice command, if **Device Erase** is Enabled. So it strongly recommended to customers to Disable "**Device erase**" during production.

###### Debug Lock Command Reference

The commands for debug lock are described in the following table.

|**DCI Command (1)**|**Mailbox (SE Manager) API (2)**|**Description**|**Availability**|
|---|---|---|---|
|Apply Lock|sl_se_apply_debug_lock|Enables the debug lock for the part.|While debug is unlocked.|
|Read Lock Status|sl_se_get_debug_lock_status|Returns the current debug lock status and con-figuration.|Always.|
|Disable Device Erase|sl_se_disable_device_erase|Disables the Erase Device command. This command does not lock the debug interface to the part, but it is an IRREVERSIBLE action for the part.|Always.|
|Disable Secure Debug|sl_se_disable_secure_debug|Disables the secure debug functionality that can be used to open a locked debug port.|While secure debug is enabled.|
|Enable Secure Debug|sl_se_enable_secure_debug|Enables the secure debug functionality that can be used to open a locked debug port.|While debug is unlocked and Public Command Key is provisioned.|
|Set debug options|sl_se_set_debug_options|Configures the TrustZone access permissions of the debug interface. (3)|While debug is unlocked.|
|Init Pub Key|sl_se_init_otp_key|Used to provision a single public key during device initialization. The public key cannot be changed once written, and the command will be unavailable for that key.|Available once for each key.|
|Read Pub Key|sl_se_read_pubkey|Reads the stored public key.|Always.|
|Get Challenge|sl_se_roll_challenge|Used to roll the current challenge value (16 bytes) to revoke secure debug access. (4)|While Public Command Key is uploaded.|

**Notes**:

1. Performing these commands over DCI is implemented in Simplicity Studio and Simplicity Commander.
2. The `sl_se_apply_debug_lock`, `sl_se_get_debug_lock_status`, `sl_se_init_otp_key`, and `sl_se_read_pubkey` are available on all Series 2 and Series 3 devices. Other APIs are only available on HSE and Series 3 devices. The SE Manager API document can be found at [https://docs.silabs.com/gecko-platform/latest/platform-security-api/sl-se-manager](https://docs.silabs.com/gecko-platform/latest/platform-security-api/sl-se-manager).
3. For more information about debug options, see [TrustZone Debug Authentication](05-debug-unlock#trustzone-debug-authentication).
4. A new challenge will only be generated if the current one has been successfully used at least once. On Series 2 devices, there is no limitation on rolling a challenge, whereas on Series 3 devices, challenge can be rolled only 128 times.

##### Debug Unlock

###### Overview

The debug access port connected to the device's Cortex-M33 processor can be opened by issuing commands to the SE, either from a debugger over DCI or through the mailbox interface.

When secure debug unlock functionality is enabled, it is possible to request a challenge from the device and, by answering the challenge, debug lock can be disabled until the next power-on or reset.

The status of the debug lock can be inspected using the [Read Lock Status](04-debug-lock#debug-lock-command-reference) command.

###### Standard Debug Unlock

With the properties of the [standard debug lock](04-debug-lock#standard-debug-lock) with Device Erase enabled, the device can be returned to the standard debug unlock state using the Erase Device command. This command will wipe the main flash and RAM and verify they are empty before opening the debug lock. It will not wipe user data (USERDATA section of Flash) and provisioned SE settings.

![Standard Debug Unlock](/series2-secure-debug/0.3/images/sld714-standard-debug-unlock.png)

###### Secure Debug Unlock

In a secure debug unlock setup, the customer owns a private key and installs a matching public key into the device. This public key checks a certificate that shows what actions the customer allows either for themselves or someone they trust. For example, they might allow only the debug port on a Cortex-M33 to be unlocked, or only certain tamper signals to be restored on HSE-SVH devices.

This method is very helpful during failure analysis because it lets the device be unlocked without erasing the data in flash or RAM.

> **Note**: Enabling secure debug lock, without writing command public key into the device key, will cause the device to be permanently locked and cannot be debugged and even cannot be reprogrammed.

###### Secure Debug Lock/Unlock Flow (heading level 7)

The secure debug was designed with three organizations in mind:

- Direct Customer to whom Silicon Labs sells the chip. This chip has the Public Command Key installed in the SE OTP.
- That Direct Customer may be creating a white-labeled product for another company or a sub-component that goes into another company’s product. The Product Company is the customer of the direct customer.
- The Debug 3rd Party could be anyone, internal or external, that the Product Company decides is qualified to debug the device.

Because the Public Command Key is installed into the SE OTP of a large number of devices and cannot be changed, the corresponding Private Command Key should be stored securely in HSM. If this Private Command Key is ever leaked, all the devices programmed with the corresponding Public Command Key will be compromised.

A secure debug unlock use case is described in the following figure. The secure debug unlock flow moves across the time axis from left to right.

![image](/series2-secure-debug/0.3/images/sld714-image32.png)

![image](/series2-secure-debug/0.3/images/sld714-debug-unlock-token-contents.png)

1. The Product Company creates a Private/Public Certificate Key pair for each device. Because the key pair is assigned only to a single device the company may not need to protect the Private Certificate key as securely as the Private Command key by the direct customer.
2. The Public Certificate Key (cert_pubkey.pem) for each device is passed to the Silicon Labs Direct Customer. The part number and serial number are also required if Direct Customer cannot access the device.
3. The Direct Customer then places that Public Certificate Key in the access certificate. The access certificate is per-device because it contains the unique device serial number. This certificate is generated once upon creation of the device, and thereafter, is generally only modified when the Private/Public Certificate Key pair is changed by the Product Company.
4. The Access certificate should be signed by Private Command key.
5. The access certificate is passed to the Product Company. The purpose of the access certificate is to grant overall debug access capabilities to the Product Company and authorize them to allow third parties to debug the device. The Product Company can now use the access certificate to generate the Debug Unlock Token. The same access certificate can be used to generate as many Debug Unlock Tokens as necessary without having to ever go back to the Direct Customer.
6. To create the Debug Unlock Token, a debug session must be started with the device and the challenge value (which is a random number) should be read out to generate the challenge response.
7. The challenge response is then cryptographically hashed (SHA-256) to create a digest. The digest is then signed by the Private Certificate Key to generate the debug access command signature.
8. Generate Debug Unlock Token, using access certificate and debug access command signature generated in above steps.
9. **(Alternative)** The key protection is not required if the Private Certificate Key is ephemeral. In such case steps 6 to 8 can be skipped and Debug Unlock Token can be directly generated with the access certificate from direct customer's Private Certificate key.
10. The Debug Unlock Token and the device are now delivered to the Debug 3rd Party.
11. The device compares the Debug Unlock Token contents with its internal serial number, challenge value, and Public Command Key to determine the token’s authenticity. If authentic, it will execute the debug access command to unlock the device; otherwise, it will ignore the command.
12. The Debug 3rd Party can now use this same Debug Unlock Token to unlock the device (step 11), over and over again after each power on or reset, until they have finished debugging the device.
13. Once the Debug 3rd Party has finished debugging, they will send the device back to the Product Company. After receiving the device product company has to invalidate the debug key, so that it should not be misused. To do so product company has to start debug session and should roll the challenge and put the device back into secure debug lock state. Rolling the challenge will effectively invalidate any Debug Unlock Token that has been previously given to any third party.

> **Note**: Direct customer can use the Private Command Key on the connected chip to generate the Debug Unlock Token within the Security Store. However, this method carries a significant risk, as it bypasses the use of an HSM(Hardware Security Module), potentially exposing the Private Command Key to third parties.

###### Debug Unlock Token (heading level 7)

The elements of the Debug Unlock Token are described in the following figure and tables.

![image](/series2-secure-debug/0.3/images/sld714-debug-unlock-token.png)

|**Element**|**Value**|**Description**|
|---|---|---|
|Debug access command|0xfd010001|The command word of the Debug Unlock Token.|
|Debug mode request|Device dependent|The command parameter of the debug access command.|
|Access certificate (1)|Device dependent|See section Access Certificate.|
|Debug access command signature (1)|Device dependent|See section Challenge Response.|

**Note**:

1. The debug access command payload consists of an access certificate and a debug access command signature.

![Debug Mode Request](/series2-secure-debug/0.3/images/sld714-image35.jpg)

**Notes**:

- Enable debug port - Debug port enabled if set.
- [DBGLOCK](#trustzone-debug-authentication) (Non-secure, Invasive debug lock): The Invasive debug features for the Non-secure state are unlocked if set.
- [NIDLOCK](#trustzone-debug-authentication) (Non-secure, Non-invasive debug lock): The Non-invasive debug features for the Non-secure state are unlocked if set.
- [SPIDLOCK](#figure-54-debug-mode-request) (Secure, Invasive debug lock): The Invasive debug features for the Secure state are unlocked if set.
- [SPNIDLOCK](#figure-54-debug-mode-request) (Secure, Non-Invasive debug lock): The Non-invasive debug features for the Secure state are unlocked if set.
- All reserved bits should be 0, and bit 1 must be 1 to access the debug port.
- For the TrustZone-unaware debugging, bits 2 to 5 are irrelevant, so bits 1 to 5 are usually set (`0x0000003e`) to match with the [Authorizations](#access-certificate) in the access certificate.
- For the TrustZone-aware debugging, bits 2 to 5 are relevant. Refer to [TrustZone Debug Authentication](#trustzone-debug-authentication) for details about these debug options.

###### Access Certificate (heading level 7)

The elements of the access certificate are described in the following figures and table.

![Access Certificate](/series2-secure-debug/0.3/images/sld714-access-certificate.png)

|**Element**|**Value**|**Description**|
|---|---|---|
|Magic word|0xe5ecce01|A constant value used to identify the access certificate.|
|Authorizations|0x0000003e (1)|A value used to authorize which bit in the debug mode request can be enabled for secure debug.|
|Tamper Authorizations|0x00000000 or 0xffffffb6 (2)|A value used to authorize which bit in the tamper disable mask can be set to disable the tamper response.|
|Serial number|Device dependent|A number used to compare against the on-chip serial number for secure debug or tamper disable.|
|Public Certificate Key (3)|Device dependent|The public key corresponding to the Private Certificate Key (3) used to generate the signature (ECDSA-P256-SHA256) in a challenge response.|
|Access certificate signature|Device dependent|All the content above is signed (ECDSA-P256-SHA256) by the Private Command Key corresponding to the Public Command Key in the SE OTP.|

**Notes**:

1. This value allows all debug options to be reset for secure debug.
2. Value that sets available bits in the tamper disable mask for tamper disable (HSE-SVH device only).
3. The Private/Public Certificate Key is a randomly generated key pair. It can be ephemeral or retainable.

The Private Certificate Key can be used repeatedly to generate the signature in a challenge response on one device until the Private/ Public Certificate Key pair is discarded. This can reduce the frequency of access to the Private Command Key, allowing more restrictive access control on that key.

For more information about tamper disable, see [Anti-Tamper Protection Configuration and Use](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/).

![image](/series2-secure-debug/0.3/images/sld714-image36.jpg)

**Notes**:

- Set the bit to enable the corresponding bit in the debug mode request.
- The Debug Unlock Token will reset the corresponding debug option if the same bit is set in Debug mode request and Authorizations.

###### Challenge Response (heading level 7)

The elements of the challenge response are described in the following figure and table.

![Challenge Response](/series2-secure-debug/0.3/images/sld714-challenge-response.png)

|**Element**|**Value**|**Description**|
|---|---|---|
|Debug access command|0xfd010001|The command word of the Debug Unlock Token.|
|Debug mode request|Device dependent|The command parameter of the debug access command.|
|Challenge|Device dependent (1)|A random value generated by the SE.|
|Debug access command signature|Device dependent (2)|All the content above is signed (ECDSA-P256-SHA256) by the Private Certificate Key corresponding to the Public Certificate Key in the access certificate.|

**Notes**:

1. The challenge remains unchanged until it is updated to a new random value by rolling the challenge. The Private Certificate Key can be reused for signing when the device challenge is refreshed.
2. This signature is the final argument of the Debug Unlock Token.

###### Debug Access Flow (heading level 7)

The debug access flow is described in the following figure.

![Debug Access Flow](/series2-secure-debug/0.3/images/sld714-debug-access-flow.png)

1. Get the serial number and challenge from the SE.
2. Generate the access certificate with the device serial number.
3. Generate the challenge response with device challenge.
4. Generate the debug access command payload with access certificate and debug access command signature.
5. Send the Debug Unlock Token to the SE.
6. Verify the debug access command signature using the Public Certificate Key in the access certificate.
7. Verify the serial number and the access certificate signature using the on-chip serial number and Public Command Key in the SE OTP.
8. Authorize the debug mode request to reset the debug options until the next power-on or pin reset.
9. Roll the challenge to invalidate the current Debug Unlock Token.

###### TrustZone Debug Authentication (heading level 7)

The debug and trace support in the Cortex-M33 devices are based on the [CoreSight](https://developer.arm.com/documentation/ihi0029/f?lang=en) architecture, which can be classified into Invasive and Non-invasive debugging features as described in the following table.

|**Classification**|**Debug and Trace Features**|**Description**|
|---|---|---|
|Invasive|Core debug (e.g., single stepping), Breakpoints, Data watchpoints, Halt mode debugging|These features halt the Cortex-M33 core and change the program execution flow.|
|Non-invasive|Embedded Trace Macrocell (ETM), Micro Trace Buffer (MTB), Data trace, Instrumentation Trace Macrocell (ITM), Profiling|These features have a minor or no impact on the program execution flow.|

The separation of Invasive and Non-invasive debug and trace operations in CoreSight architecture can apply to TrustZone debug authentication, which defines the permission levels of the debug and trace features on Secure and Non-secure worlds.

The table below describes four debug options in SE to support TrustZone debug authentication. It is possible to restrict the TrustZone access permissions of the debug interface by setting one or more of the following options.

|**Debug Option**|**Description**|
|---|---|
|DBGLOCK|Non-secure, Invasive debug lock. If this bit is set, the Invasive debug features for the Non-secure state are locked.|
|NIDLOCK|Non-secure, Non-invasive debug lock. If this bit is set, the Non-invasive debug features for the Non-secure state are locked.|
|SPIDLOCK|Secure, Invasive debug lock. If this bit is set, the Invasive debug features for the Secure state are locked.|
|SPNIDLOCK|Secure, Non-invasive debug lock. If this bit is set, the Non-invasive debug features for the Secure state are locked.|

**Notes**:

- Use [Simplicity Commander](07-examples#examples-secure-debug-lock-using-commander-tool) or the SE Manager API to set the debug options.
- The state of the debug options is stored permanently in SE and can only be reset to the default value (0000) through the [Erase Device](#debug-unlock-command-reference) command (if enabled).
- A secure debug lock device [Device Erase](04-debug-lock#secure-debug-unlock) was disabled can only use the Debug Unlock Token to temporarily unlock (reset) the debug options to debug the Secure and Non-secure applications.

The following conditions are recommended (1, 2, and 3) or mandatory (4) when setting up the debug options for secure debug unlock.

1. If SPIDLOCK is unlocked, then DBGLOCK should also be unlocked.
2. If SPNIDLOCK is unlocked, then NIDLOCK should also be unlocked.
3. If DBGLOCK is unlocked, the NIDLOCK should also be unlocked.
4. If SPIDLOCK is unlocked, then SPNIDLOCK is automatically unlocked. The following table lists the recommended combinations of debug options.

|**SPNIDLOCK**|**SPIDLOCK**|**NIDLOCK**|**DBGLOCK**|**Description**|
|---|---|---|---|---|
|0|0|0|0|Allows all debug and trace features for both the Secure and the Non-secure world (default setting).|
|0|1|0|0|Only allows a Non-invasive debug in the Secure world. Allows both Invasive and Non-invasive debugs in the Non-secure world.|
|0|1|0|1|Only allows a Non-invasive debug in the Secure and the Non-secure world.|
|1|1|0|0|Only allows debug and trace features in the Non-secure world.|
|1|1|0|1|Only allows a Non-invasive debug in the Non-secure world.|
|1|1|1|1|All debug and trace features are disabled.|

**Notes**:

- [Trace Point Interface Unit (TPIU) registers' access fault](https://developer.arm.com/documentation/ka005320/latest) will occur and lock the processor in a security assertion if both NIDLOCK and DBGLOCK in debug option are set (xx11). The device will be unrecoverable if it is in the permanent debug lock state.
- The workaround is to avoid using the xx11 debug option or avoid accessing the TPIU registers and upgrade to SE firmware **≥ v1.2.14** (xG21 and xG22) or **≥ v2.2.1** (other Series 2 and all Series 3 devices) so that the debug options cannot be modified after the device is locked.

The highly recommended setting of debug options is to allow debugging in the Non-secure world while, at the same time, disabling debugging for the Secure world (1100).

- Secure memories (flash and RAM) are not accessible by the debugger.
- All debug access is blocked from accessing Secure addresses.
- The debugger will ignore the vector-catch events generated by the Secure exceptions.
- Trace sources (e.g., ETM) will stop generating instruction/data trace packets when the Cortex-M33 is in a Secure state.
- The debugger can neither halt a Secure application (e.g., breakpoint) nor single step into it.
- The Cortex-M33 will not stop when stepping into the Secure application until it returns to the Non-secure state.

The figure below describes the debug scenario of debug options with `1100` configuration.

![image](/series2-secure-debug/0.3/images/sld714-image67.jpg)

The following examples describe the relationship between **debug options** and **debug mode request** when performing a secure debug unlock on Series 2 devices.

**Example 1: All debug and trace features for both the Secure and the Non-secure world are allowed (0000)**

|**Debug Options**|**Authorizations**|**Debug Mode Request**|**Debug options after Secure Debug Unlock**|**Description**|
|---|---|---|---|---|
|0000|00|1111|10|00|xxxx|10|0000|No action|

**Example 2: Only debug and trace features in the Non-secure world are allowed (1100)**

|**Debug Options**|**Authorizations**|**Debug Mode Request**|**Debug options after Secure Debug Unlock**|**Description**|
|---|---|---|---|---|
|1100|00|1111|10|00|00xx|10|1100|No action|
|1100|00|1111|10|00|10xx|10|0100|Unlock SPNIDLOCK|
|1100|00|1111|10|00|01xx|10 or 00|11xx|10|0000 (reset SPIDLOCK will automatically unlock SPNIDLOCK)|Unlock SPNIDLOCK and SPIDLOCK|

**Notes**:

- The bit order of debug options are SPNIDLOCK (MSB), SPIDLOCK, NIDLOCK, and DBGLOCK (LSB).
- Debug options : 0 = Unlocked, 1 = Locked
- Authorizations in the access certificate: 0 = Disable, 1 = Enable
- The authorizations in the access certificate are usually set to 00|1111|10 (0x3e), so the corresponding debug options (bits 2 to 5) can be reset (unlocked) by debug mode request during secure debug unlock.
- Debug mode request (bits 2 to 5) in the Debug Unlock Token:  
  - 0 = No action on the corresponding debug option if it was locked (i.e., 1)  
  - 1 = Reset (unlock) the corresponding debug option from 1 to 0 if it was locked (i.e., 1)  
  - x = No action (either 0 or 1) on the corresponding debug option if it was unlocked (i.e., 0)
- Debug options return to the original state after power-on or pin reset.

###### Debug Unlock Command Reference

The commands for debug unlock are described in the following table.

|**DCI Command (1)**|**Mailbox (SE Manager) API (2)**|**Description**|**Availability**|
|---|---|---|---|
|Erase Device|sl_se_erase_device|Performs a device mass erase and resets the debug configuration to its initial unlocked state.|While Device Erase is enabled.|
|Read Serial Number|sl_se_get_serialnumber|Reads out the serial number (16 bytes) of the Series 2 device.|Always.|
|Get Challenge|sl_se_get_challenge|Reads out the current challenge value (16 bytes) for Secure debug unlock.|While Public Command key is uploaded.|
|Debug Access|sl_se_open_debug|Opens the secure debug access of the Cortex-M33.|Only when Secure Debug is enabled.|

**Notes**:

1. Performing these commands over DCI is implemented in Simplicity Studio and Simplicity Commander.
2. These APIs are only available on HSE devices. The SE Manager API document can be found at [https://docs.silabs.com/gecko-platform/latest/platform-security-api/sl-se-manager](https://docs.silabs.com/gecko-platform/latest/platform-security-api/sl-se-manager).

##### Precautions

###### Device Erase for Secure Debug

Disabling the Device Erase is mandatory for secure debug as described in the following table.

<table>
    <thead>
        <tr>
            <th>Device Erase</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Enabled</td>
            <td>By using <code>erasedevice</code> command, entire Flash contents can be erased, except the OTP bits. This could potentially expose the device to security risks, as it allows malicious actors to flash different or vulnerable image to the device.</td>
        </tr>
        <tr>
            <td>Disabled</td>
            <td>
                <ul>
                    <li>Command <code>erasedevice</code> will not work as JTAG (debug port) is closed</li>
                    <li>Since JTAG is disabled, only way to upgrade the firmware is via boot loader.</li>
                    <li>If <strong>secure Debug</strong> and <strong>Debug Lock</strong> are enabled, devices allow only authorized parties to debug the device.</li>
                    <li>If secure boot is also enabled boot loader will accept only authenticated (signed) firmware image, thereby ensures authenticity and integrity of the firmware.</li>
                </ul>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

1. Advised not to disable **Device Erase** during development phase as it is one time operation.
2. Without enabling **Secure Debug** disabling **Device Erase** will make the device permanently not usable.

Run the `security lockconfig --secure-debug-unlock disable` command to disable **Device Erase**.

```sh
commander security lockconfig --secure-debug-unlock disable --device sixg301 --serialno 440328778
```

```sh
================================================================================
WARNING: Device erase is disabled and secure debug access is locked.
If disabling secured debug access, there is no way to regain debug access to this device if continuing with this command.
Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
Secure debug unlock was disabled
DONE
```

###### Secure Boot and Debug Lock

The following table describes the different debug lock scenarios on the secure boot-enabled device.

|**Secure Debug**|**Device Erase**|**Debug Lock**|**State**|**Recover from Secure Boot Failure**|
|---|---|---|---|---|
|Disabled|Enabled|Disabled|Standard debug unlock|Flash a correctly signed image.|
|Disabled|Enabled|Enabled|Standard debug lock|Flash a correctly signed image after standard debug unlocking the device.|
|Disabled|Disabled|Enabled|Permanent debug lock|There is no way to recover the device. Make sure the programmed image is correctly signed before locking the device.|
|Enabled|Disabled|Enabled|Secure debug lock|Flash a correctly signed image after secure debug unlocking the device.|

**Note**: See _Recover Devices when Secure Boot Fails_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) to flash a correctly signed image on different debug lock scenarios.

###### Limitation on Roll Challenge

On Series 2 devices, challenge can be rolled any number of times, whereas on Series 3, challenge can be rolled a maximum of 128 times.

##### Examples

###### Using Commander tool

###### Standard Debug Lock/Unlock using Simplicity Commander (heading level 7)

This application note uses Simplicity Commander v1.19.2. The procedures and console output may be different for the other versions of Simplicity Commander. The latest version of Simplicity Commander can be downloaded from silabs.com.

```sh
commander --version
```

```sh
Simplicity Commander 1v19p2b1907

JLink DLL version: 8.44
Qt 5.15.2 Copyright (C) 2017 The Qt Company Ltd.
EMDLL Version: 0v19p19b793 mbed TLS version: 2.16.6

Emulator found with SN=440328778 USBAddr=0

DONE
```

For more information about Simplicity Commander, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

1. Run the security status command to get the selected device configuration.  
   ```sh  
   commander security status --device sixg301 --serialno 440328778  
   ```  
   ```sh  
   SE ROM version          : 5.3  
   SE Firmware version     : 3.3.2  
   Serial number           : 0000000000000000781c9dfffe58959e  
   Debug lock              : Disabled  
   Device erase            : Enabled  
   Secure debug unlock     : Disabled  
   Tamper status           : OK  
   Secure boot             : Disabled  
   Boot status             : 0x20 - OK  
   Command key installed   : False  
   Sign key installed      : False  
   Security state          : Production  
   DONE  
   ```
2. Run the security lock command to lock the selected device.  
   ```sh  
   commander security lock --device sixg301 --serialno 440328778  
   ```  
   ```sh  
   WARNING: Secure debug unlock is disabled. Only way to regain debug access is to run a device erase.  
   Device is now locked.  
   DONE  
   ```
3. Run the security lock command to lock the selected device.  
   ```sh  
   commander security status --device sixg301 --serialno 440328778  
   ```  
   ```sh  
   SE ROM version        : 5.3  
   SE Firmware version   : 3.3.2  
   Serial number         : 0000000000000000781c9dfffe58959e  
   Debug lock            : Enabled  
   Device erase          : Enabled  
   Secure debug unlock   : Disabled  
   Tamper status         : OK  
   Secure boot           : Disabled  
   Boot status           : 0x20 - OK  
   Command key installed : False  
   Sign key installed    : False  
   Security state        : Production  
   DONE  
   ```
4. Run the `security erasedevice` command to unlock the selected device.  
   ```sh  
   commander security erasedevice --device sixg301 --serialno 440328778  
   ```  
   ```sh  
   Successfully erased device  
   DONE  
   ```  
   > **Note**: Issue a power-on or pin reset to complete the unlock process.
5. Run the `security status` command again to check the device configuration.

```sh
commander security status --device EFR32MG21B010F1024IM32 --serialno 440328778
```

```sh
SE ROM version          : 5.3
SE Firmware version     : 3.3.2
Serial number           : 0000000000000000781c9dfffe58959e
Debug lock              : Disabled
Device erase            : Enabled
Secure debug unlock     : Disabled
Tamper status           : OK
Secure boot             : Disabled
Boot status             : 0x20 - OK
Command key installed   : False
Sign key installed      : False
Security state          : Production
DONE
```

###### Secure Debug Lock Using Commander Tool (heading level 7)

1. Run the `security status` command to get the selected device configuration.  
   ```sh  
   commander security status --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   commander security status --device sixg301 --serialno 440326972  
   ---------------------------------------------------------------  
   SE ROM version          : 5.3  
   SE Firmware version     : 3.3.2  
   Serial number           : 0000000000000000781c9dfffe589591  
   Debug lock              : Disabled  
   Device erase            : Enabled  
   Secure debug unlock     : Disabled  
   Tamper status           : OK  
   Secure boot             : Disabled  
   Boot status             : 0x20 - OK  
   Command key installed   : False  
   Sign key installed      : False  
   Security state          : Production  
   DONE  
   ```
2. Run `util genkey` to generate commander private/public key pair.  
   ```sh  
   commander util genkey --type ecc-p256 --privkey command_key.pem --pubkey command_pubkey.pem  
   ```  
   ```sh  
   Generating ECC P256 key pair...  
   Writing private key file in PEM format to command_key.pem  
   Writing public key file in PEM format to command_pubkey.pem  
   DONE  
   ```
3. Run the `security writekey` command to provision the Public Command Key (e.g., `command_pubkey.pem`).  
   ```sh  
   commander security writekey --command command_pubkey.pem --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   Device has serial number 0000000000000000781c9dfffe589591  
     
   ================================================================================  
   Please look through any warnings before proceeding.  
   THIS IS A ONE-TIME command which permanently ties debug and tamper access to certificates signed by this key.  
   Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   Command public key stored in: C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/ device_0000000000000000781c9dfffe589591/command_pubkey.pem  
   DONE  
   ```  
   > **Note**: The Public Command Key cannot be changed once written.
4. This step is optional. To verify the public command key written into the device's SE OTP, run the `security readkey` command.  
   ```sh  
   commander security readkey --command --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   50DF50A09242A49F53251xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxE6E81C6  
   B3B891B1B9DBFC3D5F2D0yyyyy435DA6E8AFAF60037DA21AD7B2E1  
   DONE  
   ```
5. Run the `security lockconfig` command to enable the secure debug.  
   ```sh  
   commander security lockconfig --secure-debug-unlock enable --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   Secure debug unlock was enabled  
   DONE  
   ```
6. a. For the **TrustZone-unaware** application, run the `security lock` command to lock the selected device.  
   ```sh  
   commander security lock --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   Device is now locked.  
   DONE  
   ```  
   b. For the **TrustZone-aware** application, run the `security lock --trustzone ####` command to set the [debug options](05-debug-unlock#trustzone-debug-authentication) (e.g., `1100`) and lock the selected device. The bit order of #### is SPNIDLOCK (MSB), SPIDLOCK, NIDLOCK, and DBGLOCK (LSB).  
   ```sh  
   commander security lock --trustzone 1100 --device EFR32MG21A010F1024 --serialno 440048205  
   ```  
   ```sh  
   Writing debug restriction bits:  
   DBGLOCK:	0  
   NIDLOCK:	0  
   SPIDLOCK:   1  
   SPNIDLOCK:  1  
   Device is now locked.  
   DONE  
   ```  
   **Notes**:  
   - The `--trustzone` option for the `security lock` command requires Simplicity Commander **≥ v1.13.3**.  
   - It is strongly recommended to upgrade to SE firmware **≥ v1.2.14** (xG21 and xG22) or **≥ v2.2.1** (other Series 2 devices). For Series 3 devices, it is strongly recommended to upgrade SE firmware to ≥ v3.3.2 so that the debug options cannot be modified after the device is locked.  
   - Use `commander security lock` without the `--trustzone ####` option if the default setting of debug options (`0000`) is good enough for a TrustZone-aware application.
7. Run the `security disabledeviceerase` command to disable device erase. This is an **IRREVERSIBLE** action, and should be the last step in production. (**It is recommended not to set this option while evaluating secure debug functionality.**)  
   ```sh  
   commander security disabledeviceerase --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   ================================================================================  
   THIS IS A ONE-TIME command which Permanently disables device erase.  
   If secure debug lock has not been set, there is no way to regain debug access to this device. Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   Disabled device erase successfully  
   DONE  
   ```  
   > **Note**: The debug options cannot be reset to the default value 0000 (unlock) if the device erase option is disabled.
8. Read back device status after it is securely locked.  
   a. For the TrustZone-unaware application, run the security status command to check the debug lock status of the device  
   ```sh  
   commander security status --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   SE ROM version        : 5.3  
   SE Firmware version   : 3.3.2  
   Serial number         : 0000000000000000781c9dfffe589591  
   Debug lock            : Enabled  
   Device erase          : Enabled  
   Secure debug unlock   : Enabled  
   Tamper status         : OK  
   Secure boot           : Disabled  
   Boot status           : 0x20 - OK  
   Command key installed : True  
   Sign key installed    : False  
   Security state        : Production  
   DONE  
   ```  
   b. For the TrustZone-aware application, run the `security status --trustzone` command to check the full debug lock status of the device.  
   ```sh  
   commander security status --trustzone --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   SE ROM version          : 5.3  
   SE Firmware version     : 3.3.2  
   Serial number           : 0000000000000000781c9dfffe589591  
   Debug lock              : Enabled  
   Device erase            : Enabled  
   Secure debug unlock     : Enabled  
     
   Debug lock state: Locked  
     
   TrustZone Config:  
   Non-secure, invasive debug lock     (DBGLOCK) : Unlocked  
   Non-secure, non-invasive debug lock (NIDLOCK) : Unlocked  
   Secure, invasive debug lock         (SPIDLOCK) : Unlocked  
   Secure, non-invasive debug lock     (SPNIDLOCK) : Unlocked  
     
   TrustZone State:  
   Non-secure, invasive debug lock state       (DBGLOCK) : Unlocked  
   Non-secure, non-invasive debug lock state   (NIDLOCK) : Unlocked  
   Secure, invasive debug lock state           (SPIDLOCK) : Unlocked  
   Secure, non-invasive debug lock state       (SPNIDLOCK) : Unlocked  
     
   Tamper status          : OK  
   Secure boot            : Disabled  
   Boot status            : 0x20 - OK  
   Command key installed  : True  
   Sign key installed     : False  
   Security state         : Production  
   DONE  
   ```

###### Secure Debug Unlock Using Commander tool (heading level 7)

Use case for secure debug unlock is explained in [secure debug unlock](05-debug-unlock#secure-debug-lockunlock-flow) as pictorially. The steps to securely unlock the device securely are explained below.

1. The Product Company creates a Private/Public Certificate Key pair for each device. Because the key pair is assigned only to a single device, the company may not need to protect the Private Certificate Key as securely as the Private Command Key by the Direct Customer.  
   In this example, the Private/Public Certificate Key pair (`cert_key.pem` and `cert_pubkey.pem`) is generated by running the `util genkey` command.  
   ```sh  
   commander util genkey --type ecc-p256 --privkey cert_key.pem --pubkey cert_pubkey.pem  
   ```  
   ```sh  
   Generating ECC P256 key pair...  
   Writing private key file in PEM format to cert_key.pem  
   Writing public key file in PEM format to cert_pubkey.pem  
   DONE  
   ```
2. The Public Certificate Key (`cert_pubkey.pem`) for each device is passed to the Silicon Labs Direct Customer. The part number and serial number are also required if Direct Customer cannot access the device.If necessary, run the `security status` command to get the device serial number.  
   ```sh  
   commander security status --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   SE ROM version	        : 5.3  
   SE Firmware version	    : 3.3.2  
   Serial number	        : 0000000000000000781c9dfffe589591  
   Debug lock	            : Enabled  
   Device erase	        : Enabled  
   Secure debug unlock	    : Enabled  
   Tamper status	        : OK  
   Secure boot	            : Disabled  
   Boot status	            : 0x20 - OK  
   Command key installed	: True  
   Sign key installed	    : False  
   Security state	        : Production  
   DONE  
   ```
3. The Direct Customer then places that Public Certificate Key in the [access certificate](05-debug-unlock#access-certificate). The access certificate is unique per device because it contains the unique device serial number. This certificate is generated once upon creation of the device, and thereafter, is generally only modified when the Private/Public Certificate Key pair is changed by the Product Company.  
   Run the `security gencert` command with the following parameters from the Product Company to generate an unsigned access certificate (`access_certificate.extsign`) in Security Store:  
   - Device part number  
   - Device serial number  
   - Public Certificate Key  
   ```sh  
   commander security gencert --device sixg301 --deviceserialno 0000000000000000781c9dfffe589591 --cert-pubkey cert_pubkey.pem --extsign  
   ```  
   ```sh  
   Authorization file written to Security Store:  
   C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/ device_0000000000000000781c9dfffe589591/certificate_authorizations.json Cert key written to Security Store:  
   C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/ device_0000000000000000781c9dfffe589591/cert_pubkey.pem  
   Created an unsigned certificate in Security Store:  
   C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/ device_0000000000000000781c9dfffe589591/access_certificate.extsign  
   DONE  
   ```
4. The signing of the access certificate can be done by passing an unsigned access certificate to a Hardware Security Module (HSM) containing the Private Command Key.  
   In this example, the OpenSSL tool is used instead of HSM. Please install openSSL version above 3.5.0. Sign the access certificate (`access_certificate.extsign`) in Security Store with the Private Command Key (`command_key.pem`). The [access certificate signature](05-debug-unlock#access-certificate) is in the `cert_signature.bin` file.  
   Run the `util signcert` command with the following parameters to verify the signature and generate the signed access certificate (`access_certificate.bin`):  
   - Unsigned access certificate  
   - Access certificate signature  
   - Public Command Key  
   ```sh  
   commander util signcert access_certificate.extsign --cert-type access --signature cert_signature.bin  
   --verify command_pubkey.pem --outfile access_certificate.bin  
   ```  
   ```sh  
   R = D97E43FEA278207080D6D0808B46810C1167F123AF1CA9FAF2DE0F4322B97ACE  
   S = FEDFEA11A3C83AFFCD5293283B13A50580862B9F651AAE08012C2BFB6BA8E697  
   Successfully verified signature  
   Successfully signed certificate  
   DONE  
   ```
5. The access certificate is passed to the Product Company. The purpose of the access certificate is to grant overall debug access capabilities to the Product Company and authorize them to allow third parties to debug the device. The Product Company can now use the access certificate to generate the Debug Unlock Token. The same access certificate can be used to generate as many Debug Unlock Tokens as necessary without having to ever go back to the Direct Customer.
6. To create the Debug Unlock Token, a debug session must be started with the device and the challenge value (which is a random number `Challenge 1` in this example) should be read out to generate the challenge response.  
   Run the `security gencommand` command to generate the challenge response without debug access command signature and store it in a file (`command_unsign.bin`).  
   ```sh  
   commander security gencommand --action debug-unlock --unlock-param 1111 -o command_unsign.bin --nostore  
   --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   Unsigned command file written to:  
   command_unsign.bin  
   DONE  
   ```  
   **Notes**:  
   - The data in the `--unlock-param` option are the bits 2 to 5 of debug mode request in the challenge response.  
   - The default value `1111` (reset all debug options) is in place if the `security gencommand` command does not include the `-- un-lock-param` option.
7. The challenge response is then cryptographically hashed (SHA-256) to create a digest. The digest is then signed by the Private Certificate Key to generate the debug access command signature.  
   The signing of the challenge response can be done by passing an unsigned challenge response to a Hardware Security Module (HSM) containing the Private Certificate Key.  
   In this example, OpenSSL is used to sign the challenge response (`command_unsign.bin`) with the Private Certificate Key (`cert_key.pem`). The debug access command signature is in the `command_signature.bin` file.  
   ```sh  
   openssl dgst -sha256 -binary -sign cert_key.pem -out command_signature.bin command_unsign.bin  
   ```
8. Run the `security unlock` command with the access certificate (`access_certificate.bin`) from Direct Customer and debug access command signature (`command_signature.bin`) in step 7 to generate the Debug Unlock Token.  
   ```sh  
   commander security unlock --cert access_certificate.bin --command-signature command_signature.bin -- unlock-param 1111 --device sixg301 --serialno 440326972  
   ```  
   ```sh  
   Certificate written to Security Store:  
   C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000781c9dfffe589591/access_certificate.bin  
   R = B4F5F2628B50BBA54ADAB4EB67CD0F933FE4C01E8BA760915D5167E75330F3A2  
   S = 4D7EEA1B6D8EA61F3140198B26060D9F96D32CDCC5CE58CB4611ECED0D21F9B8  
   Command signature is valid  
   Secure debug successfully unlocked  
   Command unlock payload was stored in Security Store  
   DONE  
   ```  
   **Notes**:  
   - Put the required files in the same folder to run the command.  
   - The debug access command signature can be in a Raw or Distinguished Encoding Rules (DER) format.  
   - It requires Simplicity Commander Version 1.11.2 or above to support signature in DER format.  
   - The data in the `--unlock-param` option are the bits 2 to 5 of debug mode request in the Debug Unlock Token. This value **MUST** be equal to the value of `--unlock-param` option in step 6.  
   - The default value `1111` (reset all debug options) is in place if the `security unlock` command does not include the `--unlock- param` option.
9. **(Alternative)** The key protection is not required if the Private Certificate Key is ephemeral. Steps 6 to 8 can be implemented by running the `security unlock` command with the access certificate (`access_certificate.bin`) from the Direct Customer and Private Certificate Key (`cert_key.pem`) to generate the Debug Unlock Token.  
   ```sh  
   commander security unlock --cert access_certificate.bin --cert-privkey cert_key.pem --unlock-param 1111 -- device sixg301 --serialno 440326972  
   ```  
   ```sh  
   Unlocking with unlock payload:  
   C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000781c9dfffe589591/challenge_a7be6d84d1a41321b1492e643ba626f1/unlock_payload_0000000000111110.bin  
   Secure debug successfully unlocked  
   DONE  
   ```  
   **Notes**:  
   - The data in the `--unlock-param` option are the bits 2 to 5 of debug mode request in the Debug Unlock Token.  
   - The default value `1111` (reset all debug options) is in place if the `security unlock` command does not include the `--unlock-param` option.
10. The Debug Unlock Token (also known as `Command unlock payload`) file (`unlock_payload_0000000000111110.bin`, where `0000000000111110` is the value of debug mode request) is stored in the Security Store. The location in Windows is `C:\Users\<userName>\AppData\Local\SiliconLabs\commander\SecurityStore\device_<Serial number>\challenge_<Challenge value>`.  
    ![screenshot](/series2-secure-debug/0.3/images/sld714-image68.jpg)  
    Users can also use the `security getpath` command to get the path of the Security Store or a specified device.  
    ```sh  
    commander security getpath --device sixg301  
    ```  
    ```sh  
    C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore  
    DONE  
    ```  
    ```sh  
    commander security getpath --deviceserialno 0000000000000000781c9dfffe589591  
    ```  
    ```sh  
    C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000781c9dfffe589591  
    DONE  
    ```
11. The Debug Unlock Token and the device are now delivered to the Debug 3rd Party.  
    Run the `security gencommand` command to create the Security Store to place the Debug Unlock Token file.  
    ```sh  
    commander security gencommand --action debug-unlock --device sixg301 --serialno 440326972  
    ```  
    ```sh  
    Unsigned command file written to Security Store:  
    C:/Users/<userName>/AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000781c9dfffe589591/challenge_a7be6d84d1a41321b1492e643ba626f1/ unlock_command_to_be_signed22_07_2025.bin  
    DONE  
    ```  
    Copy the Debug Unlock Token file (`unlock_payload_0000000000111110.bin`) from Product Company to the Windows Security Store `challenge_<Challenge value>` folder located in `C:\Users\<PC user name>\AppData\Local\SiliconLabs\commander\SecurityStore\device_<Serial number>challenge_<Challenge value>`.
12. The device compares the Debug Unlock Token contents with its internal serial number, challenge value, and Public Command Key to determine the token’s authenticity. If authentic, it will execute the debug access command to unlock the device; otherwise, it will ignore the command.  
    Run the `security unlock` command to unlock the device.  
    ```sh  
    commander security unlock --unlock-param 1111 --device sixg301 --serialno 440326972  
    ```  
    ```sh  
    Unlocking with unlock payload:  
    C:/Users/<userName>AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000781c9dfffe589591/challenge_a7be6d84d1a41321b1492e643ba626f1/unlock_payload_0000000000111110.bin  
    Secure debug successfully unlocked  
    DONE  
    ```  
    **Notes**:  
    - If the security store has multiple tokens for the selected device, use `--unlock-param` option to specify which unlock token is chosen to unlock the device.  
    - Simplicity Commander will only use the token with value `1111` (error if not available) from the security store to unlock the device if the security unlock command does not include the `--unlock-param` option.
13. Run `security status --trustzone` command to check the full debug lock status of the device.  
    ```sh  
    commander security status --trustzone --device sixg301 --serialno 440326972  
    ```  
    ```sh  
    SE ROM version	        : 5.3  
    SE Firmware version	    : 3.3.2  
    Serial number	        : 0000000000000000781c9dfffe589591  
    Debug lock	            : Disabled  
    Device erase	        : Enabled  
    Secure debug unlock     : Disabled  
      
    Debug lock state: Unlocked  
      
    TrustZone Config:  
    Non-secure, invasive debug lock   (DBGLOCK) : Unlocked  
    Non-secure, non-invasive debug lock (NIDLOCK) : Unlocked  
    Secure, invasive debug lock  (SPIDLOCK) : Unlocked  
    Secure, non-invasive debug lock   (SPNIDLOCK): Unlocked  
      
    TrustZone State:  
    Non-secure, invasive debug lock state  (DBGLOCK) : Unlocked  
    Non-secure, non-invasive debug lock state (NIDLOCK) : Unlocked  
    Secure, invasive debug lock state   (SPIDLOCK) : Unlocked  
    Secure, non-invasive debug lock state   (SPNIDLOCK): Unlocked  
      
    Tamper status	      : OK  
    Secure boot	          : Disabled  
    Boot status	          : 0x20 - OK  
    Command key installed : True  
    Sign key installed	  : False  
    DONE  
    ```
14. The Debug 3rd Party can now use this same Debug Unlock Token to unlock the device (step 12), over and over again after each power-on or pin reset, until they have finished debugging the device.
15. Once the Debug 3rd Party has finished debugging, they will send the device back to the Product Company.
16. Once the Product Company receives the device, they will immediately start a debug session, roll the challenge (from `Challenge 1` to `Challenge 2` in this example), and put the device back into the secure debug lock state. Rolling the challenge will effectively invalidate any Debug Unlock Token that has been previously given to any third party.  
    Run the `security rollchallenge` command and reset the device to invalidate the current Debug Unlock Token. The challenge cannot be rolled before it has been used at least once.  
    ```sh  
    commander security rollchallenge --device sixg301 --serialno 440326972  
    ```  
    ```sh  
    Challenge was rolled successfully.  
    DONE  
    ```  
    The unlock token is invalidated after rolling the challenge because any previously issued Debug Unlock Token now contains a different challenge value (`Challenge 1`) than the challenge value currently in the device (`Challenge 2`).  
    The validation process of any previously issued Debug Unlock Token will always fail until a new Debug Unlock Token is issued with a current matching challenge value (`Challenge 2`).

###### Using Simplicity Studio

The security operations are performed in the Security Settings of Simplicity Studio. This application note uses Simplicity Studio v5.11.0.0. The procedures and pictures may be different for the other versions of Simplicity Studio 5.

###### Standard Debug lock/unlock using Simplicity Studio (heading level 7)

1. Right-click the selected debug adapter RB (ID:J-Link serial number) to display the context menu.  
   ![Debug Adapters Context Menu](/series2-secure-debug/0.3/images/sld714-image69.png)
2. Click **Device configuration...** to open the **Configuration of device: J-Link Silicon Labs (serial number)** dialog box. Click the **Security Settings** tab to get the selected device configuration.  
   ![Configuration on Selected Device](/series2-secure-debug/0.3/images/sld714-image70.png)
3. Click [**Enable**] next to **Enable Debug Lock:** to lock the device. The following **Enable Debug Lock Warning** is displayed. Click [**Yes**] to confirm. This configures standard debug lock.  
   ![Enable Debug Lock](/series2-secure-debug/0.3/images/sld714-image71.png)
4. The [**Enable**] controls next to **Enable Secure Debug Unlock:** and **Enable Debug Lock:** are grayed out after standard debug lock is enabled.  
   ![Standard Debug Lock](/series2-secure-debug/0.3/images/sld714-image72.jpg)
5. Click [**Device Erase**] to unlock the device.  
   ![Device Erase](/series2-secure-debug/0.3/images/sld714-image73.png)
6. The device will return to the unlock state. Click [**OK**] to exit.  
   ![Standard Debug Unlock](/series2-secure-debug/0.3/images/sld714-image74.png)

###### Secure Debug Lock Using Simplicity Studio (heading level 7)

1. Run the `util keytotoken` command to convert the Public Command Key file (PEM format) into a text file (`command_pubkey.txt`).  
   Refer to [Secure Debug Lock Using Commander tool)](#secure-debug-unlock-using-commander-tool) before performing these steps.  
   ```sh  
   commander util keytotoken command_pubkey.pem --outfile command_pubkey.txt  
   ```  
   ```sh  
   Writing EC tokens to command_pubkey.txt...  
   DONE  
   ```
2. Open **Security Settings** of the selected device
3. Click the **WriteKey** link next to **Command Key:** to open a dialog box.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-write-key-link.png)
4. The **Write Command Key** dialog box is displayed.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image77.png)
5. Open the `command_pubkey.txt` file generated in step 1.  
   ```sh  
   MFG_SIGNED_BOOTLOADER_KEY_X : 50DF50A09242A49F53251D38E1A368C82EC7CA2D33E6E81C6B3B891B1B9DBFC3  
   MFG_SIGNED_BOOTLOADER_KEY_Y : D5F2D045236CBEF3CB46B13BF7527AA36A26435DA6E8AFAF60037DA21AD7B2E1  
   ```
6. Copy Public Command Key (X-point `50DF...` first, then Y-point `D5F2...`) to **Command Key:** box.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image78.png)
7. Click [**Write**] to provision the Public Command Key.
8. Click [**Enable**] next to **Enable Secure Debug Unlock:** to enable the secure debug functionality.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image79.png)
9. Click [**Enable**] next to **Enable Debug Lock:** to lock the device. This configures secure debug lock.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image81.jpg)
10. Click [**Disable**] next to **Disable Device Erase:** to disable the device erase. The following **Disable Device Erase Warning** is displayed. Click [**Yes**] to confirm.

![screenshot](/series2-secure-debug/0.3/images/sld714-image83.png)

> **Important**: This is an **IRREVERSIBLE** action, and should be the last step in production. While evaluating Secure Debug functionality, it is best to not enable this option.

###### Secure Debug Unlock Token Provision Simplicity Studio (heading level 7)

Use the Debug Unlock Token file (`unlock_payload_0000000000111110.bin`) generated in [Secure Debug Unlock Using Commander Tool](#secure-debug-unlock-using-commander-tool) steps 8 or 9 to unlock the device with Simplicity Studio.

1. Open the `unlock_payload_0000000000111110.bin` file with the Hex File editor.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image85.jpg)
2. Click **View** to open the context menu, and then select **Group By** → **Double words** to convert the token into a little-endian format.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image86.jpg)
3. Select all (Ctrl+A) and copy (Ctrl+C) the Debug Unlock Token to a text editor.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image87.jpg)
4. Use the text editor to remove all the spaces from the token.
5. Right-click the selected debug adapter **RB (ID:J-Link serial number)** to display the context menu.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image88.png)
6. Click **Set Unlock Token** to open the **Add Debug Unlock Token** dialog box. Enter the name (e.g., `AN1190 Token`) for this Debug Unlock Token, and copy the content in step 4 to the **Debug Unlock Token:** box. Click [**OK**] to confirm and exit.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image89.png)  
   > **Note**: The Simplicity Studio can only keep one Debug Unlock Token on each WSTK.
7. Open Security Settings of the selected device as described in [Standard Debug Lock/Unlock Using Simplicity Studio](#standard-debug-lockunlock-using-simplicity-studio).
8. The token added in step 6 should be displayed on the **Crypto Profile:** field. If not, click the link next to **Crypto Profile:** to select the token from the **Crypto Profile Manager** drop-down list. The Simplicity Studio will automatically add the WSTK J-Link serial number (`-J-Link Silicon Labs (serial number)`) to the token's name.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-jlink-serial-number.png)
9. Click [**Unlock Debug Port**] to use the token in **Crypto Profile:** to unlock the device (invalid token will display an error message). The device stays in the unlock state until the next power-on or pin reset. Click [**OK**] to exit.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image90.png)
10. The Simplicity IDE will automatically use the selected Debug Unlock Token in **Crypto Profile** for debugging and flashing.

After finished debugging, open the Security Settings of the selected device as described in [Standard Debug Lock/Unlock Using Simplicity Studio](#standard-debug-lockunlock-using-simplicity-studio).

###### Roll Challenge Using Simplicity Studio (heading level 7)

1. Click [**Roll Challenge**] to generate a new challenge value to invalidate the Debug Unlock Token added in step 6. Click [**OK**] to exit.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image93.png)
2. Right-click the selected debug adapter **RB Board (ID:J-Link serial number)** to display the context menu.  
   ![screenshot](/series2-secure-debug/0.3/images/sld714-image94.png)
3. Click [**Clear Unlock Token**] to delete the WSTK Debug Unlock Token from Simplicity Studio.

###### Using Platform SE - Manager

Simplicity Studio 5 includes the SE Manager platform examples for Secure Tamper. Refer to the corresponding readme file for details about the SE Manager example. This file also includes the procedures to create the project and run the example about the SE Manager example. This file also includes the procedures to create the project and run the example.

<table>
    <thead>
        <tr>
            <th>Category</th>
            <th>SE Manager Platform Example</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Perform Secure Debug</td>
            <td>Platform Security - SoC SE Manager Secure Debug</td>
            <td>Sample application to:
                <ul>
                    <li>Set DEBUG_OPTION for TrustZone aware debug</li>
                    <li>Enable/Disable standard Debug Lock</li>
                    <li>Provision command key</li>
                    <li>Enable/Disable Secure Debug</li>
                    <li>Lock or Unlock debug port securely</li>
                    <li>Disable Device erase</li>
                    <li>Roll challenge</li>
                </ul>
            </td>
        </tr>
    </tbody>
</table>

##### Failure Analysis

The following table describes the different scenarios when returning a Series 2 device to Silicon Labs for failure analysis.

|**State**|**Secure Boot Disabled**|**Secure Boot Enabled (2)**|
|---|---|---|
|Standard debug unlock|Device erase is not necessary for failure analysis.|Device erase is not necessary, but a correctly signed image is required to perform failure analysis.|
|Standard debug lock|Device erase is required to perform failure analysis.|Require device erase and correctly signed image to perform failure analysis.|
|Permanent debug lock|Cannot perform failure analysis.|Cannot perform failure analysis.|
|Secure debug lock (1)|Require debug unlock token to perform failure analysis.|Require debug unlock token and correctly signed image to perform failure analysis.|

**Notes**:

1. Follow the procedures mentioned in [Debug Access Flow](05-debug-unlock#debug-access-flow) to generate a valid debug unlock token for each device returned to Silicon Labs for failure analysis.
2. Secure boot enabled devices, especially with secure boot failure, may limit Silicon Labs' ability to determine the root cause of failure.

#### Production Programming of Series 2 and Series 3 Devices

##### Production Programming of Series 2 and Series 3 Devices

> **Note: This section replaces _AN1222: Production Programming of Series 2 and Series 3 Devices_. Further updates to this application note will be provided here**.

This application note demonstrates how to properly program, provision, and configure Series 2 and Series 3 devices in a production environment.

Series 2 and Series 3 devices contain a Secure Engine, which runs Secure Engine firmware. When a newer version of Secure Engine firmware is released, the firmware may be upgraded either in the production programming process for devices still in manufacturing or via a field update for deployed devices. Keys must be provisioned to the Secure Engine's one-time-programmable (OTP) memory to use the Secure Boot and Secure Debug features.

For more information about Secure Engine, see [Secure Engine Subsystem](https://docs.silabs.com/iot-security/latest/series2-secure-debug/03-secure-engine-subsystem) in _Series 2 and Series 3 Secure Debug_.

###### Key Points

- It is the customer's responsibility to ensure the Secure Engine firmware is up-to-date
- The Secure Engine firmware can be upgraded via the Serial Wire Debug (SWD) interface
- Secure Engine firmware is protected from downgrade
- Secure Engine's OTP memory prevents re-writing of:  
  - GBL Decryption Key  
  - Public Sign Key  
  - Public Command Key  
  - Secure Boot Enable flag and Tamper Configuration

##### Series 2 and Series 3 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this application note, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

On Series 3 devices, the security features are implemented by the Secure Engine and SYMCRYPTO (if available). The Secure Engine is hardware-based.

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level (1)**|**SE Support**|**Part (2)**|
|---|---|---|
|Series 3|Series 3 Secure Vault|Refer to (2) for details on supporting devices.|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|“|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|"|
|"|VSE (VSE-SVM)|"|
|Secure Vault Base (SVB)|N/A|"|

> **Notes**:
> 
> 1. The features of different Secure Vault levels can be found in the [Silicon Labs IoT Security](https://docs.silabs.com/iot-security/latest/iot-security-start/) documentation site.
> 2. [Device Security Features](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/11-series-2-and-series-3-device-security-features).

Secure Vault Mid consists of two core security functions:

- Secure Boot: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- Secure Debug access control: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- Secure Key Storage: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- Anti-Tamper protection: A configurable module to protect the device against tamper attacks.
- Device authentication: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

Series 3 Secure Vault offers the same features as Secure Vault High, except

- Device identity certificates are only installed for the SE, not the host core
- Support for AXiP/EXiP is added

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products, Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Production Programming of Series 2 and Series 3 Devices (this application note)</p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|
|AXiP Key|No|Used on Series 3 devices for encryption/decryption and authentication of firmware placed in flash|
|EXiP Key|No|Used on Series 3 devices for encryption/decryption of firmware placed in flash|

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 and Series 3 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 and Series 3 devices and modules.

##### Overview

More steps are involved in the production programming process of Series 2 and Series 3 devices compared to Series 1 devices. The steps vary if the device is to have Secure Boot enabled or disabled. For more information about Secure Boot, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/). Enabling Secure Debug is a recommended step in the process. For more information about Secure Debug, see [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

A general overview of the production programming steps is described in the following sections.

Silicon Labs provides [Custom Part Manufacturing Service (CPMS)](https://docs.silabs.com/iot-security/latest/iot-security-cpms/) to customize the users' security features and settings.

###### Production Programming for Secure Boot-Disabled Device

The following figure illustrates the production programming flow for Secure Boot-disabled devices. It is possible to upgrade Series 2 and Series 3 devices deployed in the field without Secure Boot to Secure Boot with RTSL.

![Series 2 and Series 3 High-Level Production Programming Flowchart for Secure Boot-Disabled Devices](/prod-programming-series2-and-series3/0.2/images/sld952-prod-program-flowchart.png)

Upgrading the SE Firmware and flashing the bootloader and application firmware are required in the production programming process. Provisioning the GBL Decryption Key for GBL payload decryption, Public Sign Key for Secure Boot, Public Command Key for Secure Debug Unlock, and enabling the Debug Lock are strongly recommended.

A more detailed version of the Series 2 and Series 3 production programming flowchart for a Secure Boot-disabled device is illustrated in the following figure.

![Series 2 and Series 3 Step-by-Step Production Programming Flowchart for a Secure Boot-Disabled Device](/prod-programming-series2-and-series3/0.2/images/sld952-prod-program-stepbystep-flowchart.png)

**Notes**:

1. Refer to [Provisioning the GBL Decryption Key in Simplicity Commander](07-key-provisioning#provisioning-the-gbl-decryption-key-in-simplicity-commander) on how to program the GBL Decryption Key to the Series 2 or Series 3 device.
2. The VSE devices store a Public Sign Key copy on the top page of the main flash for Secure Boot (see _Signing for ECDSA-P256-SHA256 Secure Boot_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)).
3. The Public Command Key can also be used to temporarily disable anti-tamper protection on HSE-SVH devices (see [Anti-Tamper Protection Configuration and Use](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/)).
4. Enabling the debug lock should be the final step in production, and the following debug lock options are available on Series 2 and Series 3 devices.  
   - [Standard Debug Lock](10-enabling-debug-lock#standard-debug-lock)  
   - [Secure Debug Lock](10-enabling-debug-lock#secure-debug-lock) (Public Command Key was provisioned)  
   - [Permanent Debug Lock](10-enabling-debug-lock#permanent-debug-lock)  
   For more information about these debug lock options, see the section _Debug Lock State Transition_ in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).
5. For Series 3, the final  step is to close all code regions. See [_Bootloader Firmware Programming](05-bootloader-firmware-programming) and [Application Firmware Programming](06-application-firmware-programming) for instructions.

###### Production Programming for Secure Boot-Enabled Device

The following figure illustrates the production programming flow for Secure Boot-enabled devices.

![Series 2 and Series 3 High-Level Production Programming Flowchart for Secure Boot-Enabled Devices](/prod-programming-series2-and-series3/0.2/images/sld952-high-level-prod-program-flow-secureboot-enabled.png)

Upgrading the SE Firmware and flashing the **SIGNED** bootloader and application firmware are required in the production programming process. Provisioning the Public Sign Key and enabling Secure Boot are also needed in the production programming process to enable the Secure Boot option. Provisioning the GBL Decryption Key for GBL payload decryption, Public Command Key for Secure Debug Unlock, and enabling the Debug Lock are strongly recommended. Provisioning Tamper Configuration (HSE-SVH and Series 3 Secure Vault only) is also recommended.

A more detailed version of the Series 2 and Series 3 production programming flowchart for a Secure Boot-enabled device is illustrated in the following figure.

![Series 2 and Series 3 High-Level Production Programming Flowchart for Secure Boot-Enabled Devices](/prod-programming-series2-and-series3/0.2/images/sld952-stepbystep-prod-program-flow-secureboot-enabled.png)

**Notes**:

1. The device will enter the Secure Boot failed state if the bootloader firmware is either unsigned or incorrectly signed (see [Bootloader Firmware Programming](05-bootloader-firmware-programming)).
2. If the Secure Boot option is enabled in the bootloader, the application firmware must be signed (see [Application Firmware Programming](06-application-firmware-programming)).
3. The VSE devices store a Public Sign Key copy on the top page of the main flash for Secure Boot (see section _Signing for ECDSA-P256-SHA256 Secure Boot_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)).
4. On HSE-SVH and Series 3 Secure Vault devices, the anti-tamper protection configuration is provisioned with Secure Boot settings (see [Enabling Secure Boot and Tamper Configuration](09-enabling-secure-boot-and-tamper-configuration)).
5. Refer to [Provisioning the GBL Decryption Key in Simplicity Commander](07-key-provisioning#provisioning-the-gbl-decryption-key-in-simplicity-commander) on how to program the GBL Decryption Key to Series 2 or Series 3 devices.
6. The Public Command Key can also be used to temporarily disable anti-tamper protection on HSE-SVH devices (see [Anti-Tamper Protection Configuration and Use](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/)).
7. Enabling the debug lock should be the final step in production, and the following debug lock options are available on the Series 2 device.  
   - [Standard Debug Lock](10-enabling-debug-lock#standard-debug-lock)  
   - [Permanent Debug Lock](10-enabling-debug-lock#permanent-debug-lock)  
   - [Secure Debug Lock](10-enabling-debug-lock#secure-debug-lock) (Public Command Key was provisioned)  
   For more information about these debug lock options, see the section _Debug Lock State Transition_ in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).
8. For Series 3, the final step is to close all code regions. See [Bootloader Firmware Programming](05-bootloader-firmware-programming) and [Application Firmware Programming](06-application-firmware-programming) for instructions.

##### Using Simplicity Commander

1. This application note uses Simplicity Commander v1.19.2. The procedures and console output may be different for the other versions of Simplicity Commander. The latest version of Simplicity Commander can be downloaded from [https://www.silabs.com/developers/mcu-programming-options](https://www.silabs.com/developers/mcu-programming-options).  
   ```sh  
   commander --version  
   ```  
   ```sh  
   Simplicity Commander 1v19p2b1907  
     
   JLink DLL version: 8.44  
     
   Qt 5.15.2 Copyright (C) 2017 The Qt Company Ltd.  
     
   EMDLL Version: 0v19p19b793  
     
   mbed TLS version: 2.16.6  
     
   Emulator found with SN=440329507 USBAddr=0  
     
   DONE  
   ```
2. The Simplicity Commander's Command Line Interface (CLI) is invoked by `commander.exe` in the Simplicity Commander folder. The location for Simplicity Studio 5 in Windows is `C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander`. For ease of use, it is highly recommended to add the path of `commander.exe` to the system PATH in Windows.
3. If more than one Wireless Starter Kit (WSTK) is connected via USB, the target WSTK must be specified using the `--serialno <J-Link serial number>` option.
4. If the WSTK is in debug mode OUT, the target device must be specified using the `--device <device name>` option. For more information about Simplicity Commander, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

##### SE Firmware Programming

###### Overview

Consistent with best practices for Internet of Things (IoT) security, the SE Firmware provided with Series 2 and Series 3 devices supports secure firmware updates. Silicon Labs will periodically release new versions of the SE Firmware to fix bugs and patch vulnerabilities, which may require updates to devices on the manufacturing line or to devices already in the field.

Silicon Labs operates under a **Security as a Shared Responsibility Model**. This model provides flexibility to system integrators to manage SE Firmware security updates on their own timetable based on their product's use case, risk assessment, agility of their manufacturing flow, and the agility of their field firmware deployment flow.

Series 2 and Series 3 devices are rarely shipped with the latest SE Firmware installed, meaning system integrators must add SE Firmware programming to their production programming flow.

In all cases, Silicon Labs recommends that system integrators:

Subscribe to security notifications by managing their notification settings in the Silicon Labs Support Portal. This is the easiest method to be notified of SE Firmware updates and discovered vulnerabilities.

Instructions for subscribing to notifications can be found here [https://community.silabs.com/s/article/get-notified-when-a-document-changes](https://community.silabs.com/s/article/get-notified-when-a-document-changes)

- Ensure they are installing the latest SE Firmware release in their manufacturing line.
- Be prepared to deploy [security-related field updates](11-field-upgrade-the-se-firmware) to devices in the field.

###### How to Check the SE Firmware Version on a Device

The SE Firmware version of the device can be found in two ways.

- Simplicity Studio
- Simplicity Commander

This application note mainly uses Simplicity Commander.

###### Check the SE Firmware Version Using Simplicity Commander (heading level 7)

To check the SE Firmware version on the device, issue the Simplicity Commander `security status` command.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.14
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Disabled
Device erase	    : Enabled
Secure debug unlock : Disabled
Tamper status	    : OK
Secure boot	        : Disabled
Boot status	        : 0x20 - OK
DONE
```

In this example, the SE Firmware version on the EFR32MG21A is 1.2.14.

###### How to Find the Latest SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 and Series 3 devices to support the required security features. The latest SE firmware image (`.seu` or `.seuv2` and `.hex`) and release notes can be found in the Windows folder below.

For GSDK v3.2 and lower:

`C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION>\util\se_release\public`

For GSDK v4.0 and higher:

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public`

For Simplicity SDK

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\simplicity_sdk\util\se_release\public`

###### Serial Wire Debug (SWD)

The SE Firmware cannot be directly programmed to the SE using the SWD interface. Instead, an image containing the loader application and SE Firmware is flashed onto the host MCU. The SE Firmware is encrypted, versioned, and signed.

![SWD SE Firmware Upgrade Block Diagram](/prod-programming-series2-and-series3/0.2/images/sld952-swd-se-firmware-upgrade-diagram.png)

Using the SWD interface, the user flashes the loader application onto the host. The host then runs the loader application, which checks the signature and version of the SE Firmware. If the signature check passes and the upgrade's version number is higher than the device's SE Firmware version, the firmware is applied to the SE.

The upgrade will not be applied if the signature check fails or if the upgrade's version number is less than or equal to the device's SE Firmware version. Trying to apply a lower SE Firmware version to the device does no harm, but the upgrade will be ignored. This also means the device's SE Firmware cannot be downgraded.

After the SE Firmware has been upgraded, the loader application can be overwritten with the application firmware via the SWD interface.

As detailed in diagrams in the [Overview](02-overview), the steps to upgrade the SE Firmware are:

1. Connect Hardware: Connect the device's SWD interface with the WSTK and ensure proper connections.
2. Check Version: Check the SE Firmware version already on the device.
3. Flash SE Firmware: Flash the loader application onto the host processor.
4. Run: Allow the loader application to run and install the SE Firmware.
5. Re-Check Version: Ensure the update succeeded.

Each of these steps is described in more detail in the next sections.

###### Connect Hardware (heading level 7)

After connecting the device's SWD interface to the WSTK, try to read the device information using Simplicity Commander, to verify that proper connections were established to the device.

```sh
commander device info --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Part Number	   : EFR32MG21A010F1024IM32
Die Revision   : A1
Production Ver : 2
Flash Size	   : 1024 kB
SRAM Size	   : 96 kB
Unique ID      : 14b457fffe045a8e
DONE
```

###### Check Version (heading level 7)

To check the SE Firmware version on the device, issue the Simplicity Commander `security status` command.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.13
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Disabled
Device erase	    : Enabled
Secure debug unlock : Disabled
Tamper status	    : OK
Secure boot	        : Disabled
Boot status	        : 0x20 - OK
DONE
```

**Notes**:

- The `Tamper status` item is device dependent.
- Updating SE firmware on Series 3 takes significantly longer than Series 2. If the SE firmware on your device is already up to date, skip the next step for efficiency.

###### Flash SE Firmware (heading level 7)

To flash the SE Firmware upgrade application, run:

```sh
commander flash --masserase s2c1_se_fw_upgrade_app_1v2p14.hex --device EFR32MG21A010F1024 --serialno 440048205
```

where `s2c1_se_fw_upgrade_app_1v2p14.hex` is replaced with the name of the SE Firmware upgrade application file.

```sh
Parsing file s2c1_se_fw_upgrade_app_1v2p14.hex...
Erasing chip...
Flash was erased successfully
Writing 57344 bytes starting at address 0x00000000
Comparing range 0x00000000 - 0x0000DFFF (56 KB)
Programming range 0x00000000 - 0x00001FFF (8 KB)
Programming range 0x00002000 - 0x00003FFF (8 KB)
Programming range 0x00004000 - 0x00005FFF (8 KB)
Programming range 0x00006000 - 0x00007FFF (8 KB)
Programming range 0x00008000 - 0x00009FFF (8 KB)
Programming range 0x0000A000 - 0x0000BFFF (8 KB)
Programming range 0x0000C000 - 0x0000DFFF (8 KB)
DONE
```

###### Run (heading level 7)

Allow the SE Firmware upgrade application to run for at least two seconds on Series 2 devices and for at least 10 seconds on Series 3 devices. After this time has elapsed, the SE Firmware should have been upgraded.

###### Re-Check Version (heading level 7)

Run the `security status` command again to check the upgraded SE Firmware version.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.14
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Disabled
Device erase	    : Enabled
Secure debug unlock : Disabled
Tamper status	    : OK
Secure boot	        : Disabled
Boot status	        : 0x20 - OK
DONE
```

The version is now upgraded to 1.2.14.

##### Bootloader Firmware Programming

If Secure Boot is enabled, a **SIGNED** version of the bootloader firmware must be programmed to the flash.

Instructions on how to sign the bootloader firmware can be found in sections _Signing for ECDSA-P256-SHA256 Secure Boot_ and _Signing for Certificate-Based Secure Boot_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

The bootloader starting address is device dependent. For more information about the bootloader starting address, see [Memory Space for Bootloading](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/03-memory-space-for-bootloading).

Flashing the bootloader firmware using Simplicity Commander is similar to flashing the SE Firmware upgrade application.

```sh
commander flash --masserase <bootloader file> --device <device name> --serialno <J-Link serial number>
```

where `<bootloader file>` is the name of the bootloader firmware file.

For TrustZone-aware bootloaders, the `<bootloader file>` is the combined image of Secure and Non-secure bootloaders. To check the Boot status of the device, run the security status command.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.14
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Disabled
Device erase	    : Enabled
Secure debug unlock : Disabled
Tamper status	    : OK
Secure boot	        : Disabled
Boot status	    : 0x20 - OK
DONE
```

Any Boot status other than `0x20 – OK` indicates that the secure boot process has failed. It means the bootloader firmware is either unsigned or incorrectly signed. The only way to recover is to flash a correctly-signed image (see section _Recover Devices when Secure Boot Fails_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)).

For Series 3, make sure that code region 0 is closed.

```sh
commander security readregionconfig -d sixg301
```

```sh
Index        : 0
Size         : 32 kB
Protection   : Encrypted and authenticated
Closed       : False

Index        : 1
Size         : 1984 kB
Protection   : Encrypted and authenticated
Closed       : False

DONE
```

To close region 0, run the following command:

```sh
commander security closeregion 0 -d sixg301
```

> **Note**: the default behavior of the commander flash command is to close regions once programming is complete.

```sh
Successfully closed code region 0 (version 0x00000000)
DONE
```

##### Application Firmware Programming

If the Secure Boot option is enabled in the bootloader, a **SIGNED** version of the application firmware must be programmed to the flash.

Instructions on how to sign the application firmware can be found in sections _Signing for ECDSA-P256-SHA256 Secure Boot_ and _Signing for Certificate-Based Secure Boot_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

The application firmware starting address is device dependent. For more information about the application starting address, see section _Memory Space For Bootloading_ in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

Flashing the application firmware using Simplicity Commander is similar to flashing the SE Firmware upgrade application.

```sh
commander flash <application file> --device <device name> --serialno <J-Link serial number>
```

where `<application file>` is the name of the application firmware file.

For TrustZone-aware applications, the `<application file>` is the combined image of Secure and Non-secure applications.

> **Note**: Do not use the `--masserase` option to flash the application firmware since it will erase the bootloader at the starting address.

For Series 3 devices, make sure that  all code regions are closed

```sh
commander security closeregion 1 -d simg301
```

If the region was not previously closed, the command completes successfully:

```sh
Successfully closed code region 1 (version 0x00000000)
DONE
```

If the region was already closed, the response is as follows:

```sh
ERROR: DCI command failed due to: Invalid command
DONE
```

**Notes**:

1. The default configuration is for the entire application to reside in region 1, applications that use additional regions must close those regions as well.
2. The default behavior of the commander flash command is to close the region once programming is complete.

##### Key Provisioning

###### Overview

The symmetric GBL Decryption Key is used to decrypt GBL files. All encrypted GBL images on this device must be encrypted with the same 128-bit AES key. _Provisioning the GBL Decryption Key in Simplicity Commander_ below describes different ways to program the GBL Decryption Key to the Series 2 and Series 3 devices.

If the Secure Boot feature is to be used, the Public Sign Key must be provisioned to the device.

If the Secure Debug or tamper feature is to be used, the Public Command Key must be provisioned to the device.

The GBL Decryption Key (HSE device), Public Sign Key, and the Public Command Key are written to one-time-programmable (OTP) memory. Once written, they cannot be changed.

> **Note**: Silicon Labs strongly recommends provisioning these keys for future-proofing even if the device does not use the GBL Encryption, Secure Boot, and Secure Debug features.

###### Provisioning the GBL Decryption Key in Simplicity Commander

To generate the text file for the GBL Decryption Key, run the command:

```sh
commander util genkey --type aes-ccm --outfile aes_key.txt
```

```sh
Using Windows' Cryptographic random number generator
DONE
```

where `aes_key.txt` contains the randomly generated AES-128 key.

To write the GBL Decryption Key to the HSE device, run the command:

```sh
commander security writekey --decrypt aes_key.txt --device EFR32MG21A010F1024 --serialno 440048205
```

This command can be executed only once per device.

```sh
Device has serial number 000000000000000014b457fffe045a8e

================================================================================
Please look through any warnings before proceeding.
THIS IS A ONE-TIME command, any encrypting of GBL files must be done with this key.
Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
DONE
```

> **Note**: The GBL Decryption Key cannot be read back from the HSE OTP.

To write the GBL Decryption Key to the `Application Properties` struct of the GBL, run the command:

```sh
commander convert bootloader-uart-xmodem.s37 --aeskey aes_key.txt --outfile bootloader-uart-xmodem.s37
```

```sh
Parsing file bootloader-uart-xmodem.s37...
Writing to bootloader-uart-xmodem.s37...
Overwriting file: bootloader-uart-xmodem.s37...
DONE
```

where `bootloader-uart-xmodem.s37` is the GBL image file.

**Notes**:

- The `--aeskey` option for the convert command requires Simplicity Commander **v1.12.3** or above.
- The GBL Decryption Key can only be added to the GBL with `Application Properties` struct **v1.2** or higher (GSDK ≥ v4.1.0 or with SiSDK).
- This procedure must be implemented before signing the GBL image for Secure Boot.

To write the GBL Decryption Key to the top page of the main flash of a Series 2 VSE device, run the command:

```sh
commander flash --tokengroup znet --tokenfile aes_key.txt --device EFR32MG22C224F512 --serialno 440048205
```

```sh
Writing 8192 bytes starting at address 0x0007e000
Comparing range 0x0007E000 - 0x0007FFFF (8 KB)
Erasing range 0x0007E000 - 0x0007FFFF (1 sector, 8 KB)
Programming range 0x0007E000 - 0x0007FFFF (8 KB)
DONE
```

> **Note**: The MCU Series 2 devices (like EFM32PG22C200F512IM40) require Simplicity Commander Version 1.12.2 or above to support the flash `--tokengroup znet` command.

###### Generate the Sign Key pair

Silicon Labs recommends using an HSM for the creation and storage of the Sign Key pair. The instructions for OpenSSL are shown here for simplicity.

1. Create a keypair for the SECP256r1 curve by running the following command:  
   ```sh  
   openssl ecparam -genkey -name prime256v1 -out sign_key.pem  
   ```
2. Export the public key from this keypair using the following command:

```sh
openssl ec -in sign_key.pem -pubout -out sign_pubkey.pem
```

```sh
read EC key
writing EC key
```

###### Provisioning the Public Sign Key in Simplicity Commander

To write the Public Sign Key to the device, run the command:

```sh
commander security writekey --sign sign_pubkey.pem --device EFR32MG21A010F1024 --serialno 440048205
```

where `sign_pubkey.pem` is the Public Sign Key in Privacy Enhanced Mail (PEM) format. This command can be executed only once per device.

```sh
Device has serial number 000000000000000014b457fffe045a8e

================================================================================
Please look through any warnings before proceeding.
THIS IS A ONE-TIME command, all code to be run on the device must be signed by this key.
Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
DONE
```

To read the Public Sign Key on the device, run the command:

```sh
commander security readkey --sign --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
C4AF4AC69AAB9512DB50F7A26AE5B4801183D85417E729A56DA974F4E08A562C
DE6019DEA9411332DC1A743372D170B436238A34597C410EA177024DE20FC819
DONE
```

To generate the Public Sign Key token file for VSE devices, run the command:

```sh
commander util keytotoken sign_pubkey.pem --outfile sign_pubkey.txt
```

```sh
Writing EC tokens to sign_pubkey.txt...
DONE
```

To store a Public Sign Key copy on the top page of the main flash in the VSE device for ECDSA-P256-SHA256 Secure Boot, run the command:

```sh
commander flash --tokengroup znet --tokenfile sign_pubkey.txt --device EFR32MG22C224F512 --serialno 440048205
```

```sh
Writing 8192 bytes starting at address 0x0007e000
Comparing range 0x0007E000 - 0x0007FFFF (8 KB)
Erasing range 0x0007E000 - 0x0007FFFF (1 sector, 8 KB)
Programming range 0x0007E000 - 0x0007FFFF (8 KB)
DONE
```

> **Note**: The MCU Series 2 VSE devices (like EFM32PG22C200F512IM40) require Simplicity Commander Version 1.12.2 or above to support the `flash --tokengroup znet` command.

###### Generate the Command Key Pair

Silicon Labs recommends using an HSM for the creation and storage of the Command Key pair. The instructions for OpenSSL are shown here for simplicity.

1. Create a keypair for the SECP256r1 curve by running the following command:  
   ```sh  
   openssl ecparam -genkey -name prime256v1 -out command_key.pem  
   ```
2. Export the public key from this keypair using the following command:  
   ```sh  
   openssl ec -in command_key.pem -pubout -out command_pubkey.pem  
   ```  
   ```sh  
   read EC key  
   writing EC key  
   ```

###### Provisioning the Public Command Key in Simplicity Commander

To write the Public Command Key to the device, run the command:

```sh
commander security writekey --command command_pubkey.pem --device EFR32MG21A010F1024 --serialno 440048205
```

where `command_pubkey.pem` is the Public Command Key in PEM format. This command can be executed only once per device.

```sh
Device has serial number 000000000000000014b457fffe045a8e

================================================================================
Please look through any warnings before proceeding.
THIS IS A ONE-TIME command which permanently ties debug and tamper access to certificates signed by this key.
Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
DONE
```

To read the Public Command Key on the device, run the command:

```sh
commander security readkey --command --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
B1BC6F6FA56640ED522B2EE0F5B3CF7E5D48F60BE8148F0DC08440F0A4E1DCA4
7C04119ED6A1BE31B7707E5F9D001A659A051003E95E1B936F05C37EA793AD63
DONE
```

##### Configuring AXiP/EXiP (Series 3 only)

The Authenticated eXecute in-Place feature is available for Series 3 devices with QSPI flash. This feature is provided to resist attempts to

extract the contents of the executable code in the QSPI flash and modify it. Series 3 can configure up to 8 code regions in flash with

the protection level set separately for each region. By default, SixG301 devices have 2 code regions as follows:

|Flash size|Region 0|Region 1(2)|Protection|
|---|---|---|---|
|2 MB|32 kB|864 kB|AXiP|
|3 MB|32 kB|1408 kB|AXiP|
|4 MB|32 kB|1984 kB|AXiP|
|External|32 kB|1.|AXiP|

**Notes**:

1. Region 1 size = (size of flash – 192 kB (SE Firmware) – 32 kB)/2
2. Sizes shown in this column are logical, not physical, sizes

To verify the AXiP configuration for your device, run the following command:

```sh
commander security readregionconfig --device SixG301 --outfile region-config.yaml
```

```sh
Writing parsed configuration to file region-config.yaml...
DONE
```

To view the configuration, open `region-config.yaml` in a text editor. The default configuration looks like this:

```sh
regions:
  - size_kb: 32
    protection: encrypted_authenticated
  - size_kb: 1408
    protection: encrypted_authenticated
```

This is the recommended configuration for most applications. For instructions on modifying the default configuration, refer to AN1509.

To write a new region configuration to the device, run the following command:

```sh
commander security writeregionconfig region-config.yaml -d simg301
```

```sh
Reading configuration from file region-config.yaml...
Writing region configuration to device...
DONE
```

##### Enabling Secure Boot and Tamper Configuration

The Secure Boot feature verifies the integrity and authenticity of the host application before allowing it to execute. Enabling this feature is **IRREVERSIBLE**, which means once enabled, Secure Boot can no longer be disabled throughout the life of the device. The Secure Boot settings are written to the one-time-programmable (OTP) memory. They cannot be changed once programmed.

On HSE-SVH and Series 3 Secure Vault devices, the anti-tamper configuration is provisioned with Secure Boot settings. The anti-tamper configuration determines the response from the HSE-SVH device if a tamper event occurs.

**Notes**:

- All tamper-related information in the following sections is only valid on HSE-SVH devices.
- For more information about anti-tamper configuration, see [Anti-Tamper Protection Configuration and Use](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/).
- Except for the EFR32xG21B devices, other HSE-SVH devices require Simplicity Commander Version 1.12.2 or above for tamper configuration.
- Series 3 devices require Simplicity Commander Version 1.18.0, or higher

The `user_configuration.json` is a JSON file that contains the desired Secure Boot settings and anti-tamper configuration. Use the following command on the target device (e.g., EFR32MG21B010F1024) to generate a default configuration file.

```sh
commander security genconfig --nostore -o user_configuration.json --device EFR32MG21B010F1024
--serialno 440048205
```

```sh
DONE
```

> **Note**: The content of the JSON file is device dependent (`--device <device name>`).

The `security genconfig` command above generates a generic configuration file for **EFR32MG21B010F1024** consisting of the properties listed in the tables below. A text editor can be used to modify the default settings shown below to the desired configuration.

```sh
{
    "mcu_flags": { "SECURE_BOOT_ENABLE": true,
        "SECURE_BOOT_VERIFY_CERTIFICATE": false,
        "SECURE_BOOT_ANTI_ROLLBACK": true,
        "SECURE_BOOT_PAGE_LOCK_NARROW": false,
        "SECURE_BOOT_PAGE_LOCK_FULL": true
    },
    "tamper_levels": {
        "FILTER_COUNTER": 0,
        "WATCHDOG": 4,
        "SE_RAM_CRC": 4,
        "SE_HARDFAULT": 4,
        "SOFTWARE_ASSERTION": 4,
        "SE_CODE_AUTH": 4,
        "USER_CODE_AUTH": 0,
        "MAILBOX_AUTH": 0,
        "DCI_AUTH": 0,
        "OTP_READ": 4,
        "SELF_TEST": 4,
        "TRNG_MONITOR": 0,
        "PRS0": 0,
        "PRS1": 0,
        "PRS2": 0,
        "PRS3": 0,
        "PRS4": 0,
        "PRS5": 0,
        "PRS6": 0,
        "PRS7": 0,
        "DECOUPLE_BOD": 4,
        "TEMP_SENSOR": 0,
        "VGLITCH_FALLING": 0,
        "VGLITCH_RISING": 0,
        "SECURE_LOCK": 4,
        "SE_DEBUG": 0,
        "DGLITCH": 0,
        "SE_ICACHE": 4
    },
    "tamper_filter": {
        "FILTER_PERIOD": 0,
        "FILTER_THRESHOLD": 0,
        "RESET_THRESHOLD": 0
    },
    "tamper_flags": {
        "DGLITCH_ALWAYS_ON": false
    }
}

```

> **Note**: For `USER_CODE_AUTH` (user secure boot failed), recommended setting is 0 (Ignore) to avoid boot loops.

**Table: Secure Boot Items (mcu_flags) for Series 2 Devices**

|**Name**|**Description**|
|---|---|
|SECURE_BOOT_ENABLE|If set, verifies the host image on the Cortex-M33 before releasing the Cortex-M33 from reset.|
|SECURE_BOOT_VERIFY_CERTIFICATE|If set, requires certificate-based signing of the host image.|
|SECURE_BOOT_ANTI_ROLLBACK|If set, prevents secure upgrading to a host image with a lower version than the image that is currently stored in flash.|
|SECURE_BOOT_PAGE_LOCK_NARROW|If set, locks flash pages that have been validated by the Secure Boot process to prevent re-flashing by other means than through the SE. Write/erase locks pages from 0 through the page where the Secure Boot host image signature is located, not including the last page if the signature is not on a page boundary.|
|SECURE_BOOT_PAGE_LOCK_FULL|If set, locks flash pages that have been validated by the Secure Boot process to prevent re-flashing by other means than through the SE. Write/erase locks pages from 0 through the page where the Secure Boot host image signature is located, including the last page if the signature is not on a page boundary.|

> **Note**: The host image is usually the Gecko Bootloader (GBL).

**Table: Secure Boot Items (mcu_flags) for Series 3 Secure Vault Devices**

|**Name**|**Description**|
|---|---|
|SECURE_BOOT_ENABLE|If set, verifies the host image on the Cortex-M33 before releasing the Cortex-M33 from reset.|
|SECURE_BOOT_VERIFY_CERTIFICATE|If set, requires certificate-based signing of the host image.|
|SECURE_BOOT_ANTI_ROLLBACK|If set, prevents secure upgrading to a host image with a lower version than the image that is currently stored in flash.|

###### Table: Tamper Items for HSE-SVH and Series 3 Secure Vault Devices

|**Name**|**Description**|
|---|---|
|tamper_levels|The tamper levels of different tamper sources.|
|tamper_filter|The settings for tamper filters.|
|tamper_flags|The settings for tamper flags.|

The following command writes the Secure Boot settings and anti-tamper configuration in `user_configuration.json` file to the device. This command can be executed only once per device.

```sh
commander security writeconfig --configfile user_configuration.json --device EFR32MG21B010F1024
--serialno 440048205
```

```sh
================================================================================

THIS IS A ONE-TIME configuration: Please inspect file before confirming: user_configuration.json
Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
DONE
```

To check the device's Secure Boot settings and anti-tamper configuration, run the `security readconfig` command.

```sh
commander security readconfig --serialno 440048205
```

```sh
MCU Flags
Secure Boot                    : Enabled
Secure Boot Verify Certificate : Disabled
Secure Boot Anti Rollback	   : Enabled
Secure Boot Page Lock Narrow   : Disabled
Secure Boot Page Lock Full	   : Enabled

Tamper Levels
FILTER_COUNTER      : 1
WATCHDOG            : 4
SE_RAM_CRC          : 4
SE_HARDFAULT        : 4
SOFTWARE_ASSERTION  : 4
SE_CODE_AUTH	    : 4
USER_CODE_AUTH	    : 0
MAILBOX_AUTH	    : 1
DCI_AUTH	        : 0
OTP_READ	        : 4
SELF_TEST	        : 4
TRNG_MONITOR	    : 1
PRS0	            : 1
PRS1	            : 1
PRS2	            : 2
PRS3	            : 2
PRS4	            : 4
PRS5	            : 4
PRS6	            : 7
PRS7	            : 7
DECOUPLE_BOD	    : 4
TEMP_SENSOR	        : 2
VGLITCH_FALLING	    : 2
VGLITCH_RISING	    : 2
SECURE_LOCK	        : 4
SE_DEBUG	        : 0
DGLITCH	            : 2
SE_ICACHE	        : 4

Tamper Filter
Filter Period    : 10
Filter Threshold : 6
Reset Threshold  : 5

Tamper Flags
Digital Glitch Detector Always On: Disabled
DONE
```

##### Enabling Debug Lock

The debug lock is an important feature to prevent attackers from using the debug interface to perform unauthorized operations on the device. The following sections describe how to apply three different locks to the Series 2 and Series 3 debug interface.

###### Standard Debug Lock

The following command locks the debug interface.

```sh
commander security lock --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
WARNING: Secure debug unlock is disabled. Only way to regain debug access is to run a device erase.
Device is now locked.
DONE
```

To check the debug lock status of the device, run the `security status` command:

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.14
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Enabled
Device erase	    : Enabled
Secure debug unlock : Disabled
Tamper status	    : OK
Secure boot	        : Disabled
Boot status	        : 0x20 - OK
DONE
```

###### Permanent Debug Lock

The following command locks the debug interface.

```sh
commander security lock --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
WARNING: Secure debug unlock is disabled. Only way to regain debug access is to run a device erase. Device is now locked.
DONE
```

After locking the device, disable the device erase using the following command. This is an **IRREVERSIBLE** action and should be the last step in production.

```sh
commander security disabledeviceerase --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
================================================================================
THIS IS A ONE-TIME command which Permanently disables device erase.
If secure debug lock has not been set, there is no way to regain debug access to this device.
Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
Disabled device erase successfully
DONE
```

To check the debug lock status of the device, run the `security status` command.

```sh
commander security status --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.14
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Enabled
Device erase        : Disabled
Secure debug unlock : Disabled
Secure boot         : Disabled
Boot status         : 0x20 - OK
DONE
```

###### Secure Debug Lock

The Secure Debug feature is enabled through the `security lockconfig` command. After locking the device, the security unlock command securely unlocks the device for debugging until the next device reset without erasing flash and RAM contents. For more information about Secure Debug Unlock, see [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

The following command enables the secure debug unlock.

```sh
commander security lockconfig --secure-debug-unlock enable --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Secure debug unlock was enabled
DONE
```

For **TrustZone-unaware** applications, after enabling the Secure Debug feature, lock the debug interface using the following command.

```sh
commander security lock --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Device is now locked.
DONE
```

For **TrustZone-aware** applications, after enabling the Secure Debug feature, set the debug options (e.g., `1100`) and lock the debug interface using the following command.

```sh
commander security lock --trustzone 1100 --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Writing debug restriction bits:
DBGLOCK:	0
NIDLOCK:	0
SPIDLOCK: 1
SPNIDLOCK: 1
Device is now locked.
DONE
```

**Notes**:

- The `--trustzone` option for the `security lock` command requires Simplicity Commander **≥ v1.13.3**.
- It is strongly recommended to upgrade to SE firmware **≥ v1.2.14** (xG21 and xG22) or **≥ v2.2.1** (other Series 2 devices) so that the debug options cannot be modified after the device is locked.
- Use `commander security lock` without the `--trustzone ####` option if the default setting of debug options (`0000`) is good enough for a TrustZone-aware application.
- For more information about debug options, see the _TrustZone Debug Authentication_ section in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

After locking the device, disable the device erase using the following command. This is an **IRREVERSIBLE** action and should be the last step in production.

```sh
commander security disabledeviceerase --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
================================================================================
THIS IS A ONE-TIME command which Permanently disables device erase.
If secure debug lock has not been set, there is no way to regain debug access to this device. Type 'continue' and hit enter to proceed or Ctrl-C to abort:
================================================================================
continue
Disabled device erase successfully
DONE
```

> **Note**: The debug options cannot be reset to the default value `0000` (unlock) if the `device erase option` is disabled.

Run the `security status --trustzone` command to check the full debug lock status of the device.

```sh
commander security status --trustzone --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
SE Firmware version : 1.2.14
Serial number	    : 000000000000000014b457fffe045a8e
Debug lock	        : Enabled
Device erase	    : Disabled
Secure debug unlock : Enabled

Debug lock state: Locked

Non-secure, invasive debug lock     (DBGLOCK) : Unlocked
Non-secure, non-invasive debug lock (NIDLOCK) : Unlocked 
Secure, invasive debug lock	        (SPIDLOCK) : Locked 
Secure, non-invasive debug lock	    (SPNIDLOCK): Locked

Non-secure, invasive debug lock state     (DBGLOCK) : Unlocked
Non-secure, non-invasive debug lock state (NIDLOCK) : Unlocked
Secure, invasive debug lock state	      (SPIDLOCK) : Locked
Secure, non-invasive debug lock state	  (SPNIDLOCK): Locked

Tamper status:      : OK
Secure boot         : Disabled
Boot status         : 0x20 - OK 
DONE
```

> **Note**: For more information about Secure and Non-secure debug locks, see the _TrustZone Debug Authentication_ section in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

##### Field Upgrade the SE Firmware

###### Secure Boot-Disabled Device

Simplicity Commander or Gecko Bootloader can be used to upgrade the SE Firmware on a Secure Boot-disabled device. The following table lists the scenarios of SE Firmware upgrade on the Secure Boot-disabled device.

|**Secure Debug**|**Device Erase**|**Debug Lock**|**State**|**SE Firmware Upgrade**|
|---|---|---|---|---|
|Disabled|Enabled|Disabled|Unlock|Simplicity Commander or Gecko Bootloader|
|Disabled|Enabled|Enabled|Standard debug lock|Simplicity Commander or Gecko Bootloader|
|Enabled|Disabled|Enabled|Secure debug lock|Simplicity Commander or Gecko Bootloader|
|Disabled|Disabled|Enabled|Permanent debug lock|Gecko Bootloader|

###### Simplicity Commander (heading level 7)

To flash the SE Firmware upgrade application (e.g., `s2c1_se_fw_upgrade_app_1v2p9.hex`), run:

```sh
commander flash s2c1_se_fw_upgrade_app_1v2p9.hex --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Parsing file s2c1_se_fw_upgrade_app_1v2p9.hex...
Writing 49152 bytes starting at address 0x00000000
Comparing range 0x00000000 - 0x0000BFFF (48 KB)
Programming range 0x00000000 - 0x00001FFF (8 KB)
Programming range 0x00002000 - 0x00003FFF (8 KB)
Programming range 0x00004000 - 0x00005FFF (8 KB)
Programming range 0x00006000 - 0x00007FFF (8 KB)
Programming range 0x00008000 - 0x00009FFF (8 KB)
Programming range 0x0000A000 - 0x0000BFFF (8 KB)
DONE
```

The device should be unlocked before upgrading the SE Firmware if the standard or secure debug lock has been applied. The sections _Standard Debug Lock and Unlock_ and _Secure Debug Unlock and Roll Challenge_ in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) describe how to unlock the device.

> **Note**: This method will **OVERWRITE** the bootloader and application firmware on the device. The user should then re-program the [bootloader](05-bootloader-firmware-programming) and [application firmware](06-application-firmware-programming) after the SE Firmware upgrade.

###### Gecko Bootloader (heading level 7)

Refer to section _Generate a GBL Upgrade Image File_ (Secure Engine Upgrade) in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) for details.

The Gecko Bootloader can still parse the SE GBL upgrade image file and flash its content to the device even if a debug lock is applied. The application firmware must be updated through the Gecko Bootloader after the SE Firmware upgrade if the SE GBL upgrade image file storage overwrites the existing application. Refer to section "Gecko Bootloader Operation - Secure Engine Upgrade" in [UG266](https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf)/[Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) for details.

###### Secure Boot-Enabled Device

Simplicity Commander or Gecko Bootloader can be used to upgrade the SE Firmware on a Secure Boot-enabled device. The following table lists the scenarios of SE Firmware upgrade on the Secure Boot-enabled device.

|**Secure Debug**|**Device Erase**|**Debug Lock**|**State**|**SE Firmware Upgrade**|
|---|---|---|---|---|
|Disabled|Enabled|Disabled|Unlock|Simplicity Commander or Gecko Bootloader|
|Disabled|Enabled|Enabled|Standard debug lock|Simplicity Commander or Gecko Bootloader|
|Disabled|Disabled|Enabled|Permanent debug lock|Gecko Bootloader|
|Enabled|Disabled|Enabled|Secure debug lock|Gecko Bootloader|

> **Note**: Using Simplicity Commander to upgrade the SE Firmware on a Secure Debug Locked device is not recommended. It causes Secure Boot failure since the SE Firmware upgrade erases the signed host image for Secure Boot. The user may have issues when recovering a Secure Boot failure device with Device Erase disabled. See section _Recover Devices when Secure Boot Fails_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) for details.

###### Simplicity Commander (heading level 7)

A signed SE Firmware upgrade application must be used for the upgrade. Instructions for signing the SE Firmware upgrade application are found in the sections "Signing for ECDSA-P256-SHA256 Secure Boot" and _Signing for Certificate-Based Secure Boot_ in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

If the `SECURE_BOOT_PAGE_LOCK_NARROW` or `SECURE_BOOT_PAGE_LOCK_FULL` in the [Secure Boot Items (mcu_flags) for Series 2](09-enabling-secure-boot-and-tamper-configuration) table was enabled for Secure Boot or the standard debug lock applies, run:

```sh
commander security erasedevice --device EFR32MG21A010F1024 --serialno 440048205
```

to perform a device erase. Issue a power-on or pin reset to complete the device erase process.

```sh
Successfully erased device
DONE
```

To flash the signed SE Firmware upgrade application (`s2c1_se_fw_upgrade_app_1v2p9_signed.hex`), run:

```sh
commander flash s2c1_se_fw_upgrade_app_1v2p9_signed.hex --device EFR32MG21A010F1024 --serialno 440048205
```

```sh
Parsing file s2c1_se_fw_upgrade_app_1v2p9_signed.hex...
Writing 49152 bytes starting at address 0x00000000
Comparing range 0x00000000 - 0x0000BFFF (48 KB)
Erasing range 0x00000000 - 0x00007FFF (4 sectors, 32 KB)
Erasing range 0x00008000 - 0x0000BFFF (2 sectors, 16 KB)
Programming range 0x00000000 - 0x00001FFF (8 KB)
Programming range 0x00002000 - 0x00003FFF (8 KB)
Programming range 0x00004000 - 0x00005FFF (8 KB)
Programming range 0x00006000 - 0x00007FFF (8 KB)
Programming range 0x00008000 - 0x00009FFF (8 KB)
Programming range 0x0000A000 - 0x0000BFFF (8 KB)
DONE
```

**Notes**:

1. This method will **OVERWRITE** the signed bootloader and application firmware on the device. The user should then re-program the **SIGNED** [bootloader](05-bootloader-firmware-programming) and [application firmware](06-application-firmware-programming) after the SE Firmware upgrade.
2. If the `SECURE_BOOT_ANTI_ROLLBACK` in the tables in [Enabling Secure Boot and Tamper Configuration](09-enabling-secure-boot-and-tamper-configuration) was enabled for Secure Boot, the device will prevent the signed SE Firmware upgrade when the host image version (e.g., Gecko Bootloader v1.12.0) is equal to or higher than the SE Firmware version (e.g., v1.2.9). Under this situation, the Gecko Bootloader should be used to upgrade the SE firmware. This method will **OVERWRITE** the bootloader version in SE flash with the SE Firmware version after the upgrade.

```sh
Parsing file s2c1_se_fw_upgrade_app_1v2p9_signed.hex...
Writing 49152 bytes starting at address 0x00000000
Comparing range 0x00000000 - 0x0000BFFF (48 KB)
Erasing range 0x00000000 - 0x00007FFF (4 sectors, 32 KB)
Programming range 0x00000000 - 0x00001FFF (8 KB)
Programming range 0x00002000 - 0x00003FFF (8 KB)
Programming range 0x00004000 - 0x00005FFF (8 KB)
Programming range 0x00006000 - 0x00007FFF (8 KB)
Programming range 0x00008000 - 0x00009FFF (8 KB)
Programming range 0x0000A000 - 0x0000BFFF (8 KB)
JLinkError: Failed to halt CPU.
DONE
```

###### Gecko Bootloader (heading level 7)

Refer to section _Generate a GBL Upgrade Image File_ (Secure Engine Upgrade) in [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) for details.

The Gecko Bootloader can still parse the SE GBL upgrade image file and flash its content to the device even if a debug lock applies. The application firmware must be updated through the Gecko Bootloader after the SE Firmware upgrade if the SE GBL upgrade image file storage overwrites the existing application. Refer to section _Gecko Bootloader Operation - Secure Engine Upgrade_ in [Developing and Debugging a Gecko Bootloader](https://docs.silabs.com/mcu-bootloader/latest/gecko-bootloader-developing-debugging/) for details.

#### Anti-Tamper Protection Configuration and Use

##### Anti-Tamper Protection Configuration and Use

> **Note: This section replaces _AN1247: Anti-Tamper Protection Configuration and Use_. Further updates to this application note will be provided here**.

This application note describes how to program, provision, and configure the Secure Engine anti-tamper module. Many aspects of the anti-tamper module, including disabling the anti-tamper response when needed, are discussed.

The anti-tamper module is only available on Secure Vault High and Series 3 Secure Vault devices. The external tamper detect module is available on some Secure Vault Mid devices (e.g. xG27), Secure Vault High devices (e.g. xG25B) and Series 3 Secure Vault devices.

###### Key Points

- Tamper responses
- Tamper sources
- Tamper configuration
- Tamper disable
- Examples of provisioning and disabling the anti-tamper module

##### Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine, this continues in Series 3. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE: Hardware Secure Engine
- VSE: Virtual Secure Engine
- SE: Secure Engine (either HSE or VSE)

On Series 3 devices, the security features are implemented by the Secure Engine and SYMCRYPTO. The Secure Engine and SYMCRYPTO are hardware-based.

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level (1)**|**SE Support**|**Part (2)**|
|---|---|---|
|Series 3 Secure Vault|HSE only|Refer to [Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for details on supporting devices.|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|“|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|"|
|"|VSE (VSE-SVM)|"|
|Secure Vault Base (SVB)|N/A|"|

**Notes**:

1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).
2. [Series 2 and Series 3 Device Security Features](https://docs.silabs.com/iot-security/latest/11-series-2-device-security-features11-series-2-and-series-3-device-security-features/).

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

Series 3 Secure Vault offers the same features as Secure Vault High except:

- Device Authentication is only available for the SE

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Anti-Tamper Protection Configuration and Use (this application note)</p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|
|Authenticated eXecute in Place (AXiP) key|No|Authenticate and decrypt executable in external flash on Series 3 devices|
|Encrypted eXecute in Place (EXiP) key|No|Decrypt executable code in external flash on Series 3 devices|

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 and Series 3 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 and Series 3 devices and modules.

##### Overview

The HSE-SVH and Series 3 Secure Vault Anti-Tamper module is used to hamper or prevent both reverse engineering and re-engineering of proprietary software systems or applications.

Tamper attacks come from one or more vectors. Common attacks include voltage glitching, magnetic interference, and forced temperature adjustment. The HSE-SVH and Series 3 Secure Vault Anti-Tamper module provides fast hardware detection of external tamper signals such as case opening, glitching, and logical attacks allowing analysis and escalation up to and including bricking the device.

The anti-tamper module connects a number of hardware and software-driven tamper signals to a set of configurable hardware and software responses. This can be used to program the device to automatically respond to external events that could signal that someone is trying to tamper with the device, and very rapidly remove secrets stored in the HSE.

The available tamper signals range from signals based on failed authentication and secure boot to specialized glitch detectors. When any of these signals fire, the tamper block can be configured to trigger several different responses, ranging from triggering an interrupt to erasing the One-Time-Programmable (OTP) memory, removing all HSE secrets and resulting in a permanently destroyed device.

Silicon Labs provides [Custom Part Manufacturing Service (CPMS)](https://www.silabs.com/developers/custom-part-manufacturing-service) to protect the users' privacy by configuring the most effective tamper detection features at the Silicon Labs factory. For more information about CPMS, see [Custom Part Manufacturing Service User's Guide](https://docs.silabs.com/iot-security/latest/iot-security-cpms/).

Some SVM devices (e.g. xG25A and xG27) and SVH devices (e.g. xG25B) and Series 3 Secure Vault devices (e.g. xG301) feature an External Tamper Detect module which is used to detect signals such as case opening. The ETAMPDET signal on SVH and Series 3  Secure Vault devices is routed to the SE as an Anti-Tamper module tamper source, in addition to being a stand-alone module. For more information about ETAMPDET operation, refer to the device reference manual. Examples demonstrating how to use ETAMPDET can be found on the [Silicon Labs peripheral_example github repository](https://github.com/SiliconLabs/peripheral_examples/tree/master/series2/etampdet). The peripheral reflex system (PRS) can also be routed as a tamper source. For more information on PRS, refer to your device’s reference manual.

##### Secure Engine Manager

The Secure Engine Manager provides thread-safe APIs for the SE's mailbox interface. The SE Manager APIs related to tamper operations are listed in the following table.

For the SE's mailbox interface, see _Secure Engine Subsystem_ in [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

|**SE Manager API**|**Usage**|
|---|---|
|sl_se_init_otp|Initialize SE OTP configuration (including tamper configuration on HSE-SVH and Series 3 Secure Vault devices).|
|sl_se_read_otp|Read SE OTP configuration (including tamper configuration on HSE-SVH and Series 3 Secure Vault devices).|
|sl_se_init_otp_key|Used during device initialization to upload the Public Command Key.|
|sl_se_read_pubkey|Read the stored Public Command Key.|
|sl_se_get_serialnumber|Read out the serial number (16 bytes) of the HSE device.|
|sl_se_get_challenge|Read out the current challenge value (16 bytes) for tamper disable.|
|sl_se_roll_challenge|Used to roll the current challenge value (16 bytes) to invalidate the Disable Tamper Token.|
|sl_se_disable_tamper|Temporarily disable tamper configuration using the Disable Tamper Token.|
|sl_se_get_status|Read the current HSE status (including recorded tamper status on HSE-SVH devices).|
|sl_se_get_reset_cause|Read the EMU->RSTCAUSE register from HSE devices after a tamper reset.|
|sl_se_get_tamper_reset_cause|Read the cached value of the EMU->TAMPERRSTCAUSE register after a tamper reset.|
|sl_se_enter_active_mode|Force the SE to remain active to enable the detection of glitch tamper events on the host Cortex-M33 core (see fourth note below)|
|sl_se_exit_active_mode|Exit active mode and allow the SE to sleep when not performing operations. This will prevent the detection of glitch tamper events when the SE is sleeping. This API should only be used if active mode was entered by calling `sl_se_enter_active_mode`. If active mode is set through a DCI command, it can only be disabled through a DCI command. (see fourth note below)|

**Notes**:

- The `sl_se_get_reset_cause` is only available on EFR32xG21B devices. The `EMU->RSTCAUSE` register can be directly read on other HSE-SVH and Series 3 Secure Vault devices.
- The `sl_se_get_tamper_reset_cause` is unavailable on EFR32xG21B devices, and SE firmware ≥ v2.2.1 is required.
- The SE Manager API document can be found at [https://docs.silabs.com/gecko-platform/latest/platform-security-api/sl-se-manager](https://docs.silabs.com/gecko-platform/latest/platform-security-api/sl-se-manager).
- Does not apply to EFR32MG21B parts.

##### Tamper Responses

A [tamper source](05-tamper-sources) can lead to a series of different autonomous responses from the HSE. These responses are listed in the following table.

|**Level (1)**|**Response (2)**|**Description**|
|---|---|---|
|0|Ignore|No action is taken|
|1|Interrupt|Triggers the SETAMPERHOST interrupt on the host|
|2|Filter|Increases a counter in the tamper filter|
|4|Reset|Resets the device|
|7|Erase OTP|Erases the device's OTP configuration|

**Notes**:

1. Levels 3, 5, and 6 are reserved.
2. These responses are cumulative:  
   - If a filter response is triggered, it will also trigger an interrupt.  
   - If a reset response is triggered, it will supersede the interrupt. The filter counter and interrupt flag are cleared at reset.  
   - If an erase OTP response is triggered, it will erase the OTP and reset the device. The device will fail to boot and become unusable.

###### Interrupt

If a tamper source is configured to respond with the interrupt response or higher (≥ level 1), the `SETAMPERHOST` interrupt line to the host Cortex-M33 will be pulsed and make the NVIC trigger the corresponding interrupt handler (`SETAMPERHOST_IRQHandler`).

After the interrupt has been handled, the tamper status can be found by reading the HSE status (using `sl_se_get_status` in the [SE Manager](03-secure-engine-manager)), which contains a list of all the tamper sources that have been triggered since the last time the status was read. Reading HSE status clears the registered tamper sources.

> **Note**: Enabling the `SEMAILBOXHOST` clock for the tamper source is required to trigger the `SETAMPERHOST` interrupt in most HSE-SVH and Series 3 Secure Vault devices. EFR32xG21B does not require this.

###### Filter

The HSE has a filter to debounce spurious tamper events. The filter has a counter that is periodically reset. If a tamper source is configured to the filter response (level 2), when it is triggered, the counter is increased. If the counter value reaches a configurable threshold, the `Filter counter` tamper source is triggered, which can configure to lead to any other responses (1, 4, or even 7).

Only a single shared filter counter is available, so the cumulative triggering of all tamper sources configured to the filter level will increase the same counter. The filter can be programmed to use one of the trigger thresholds and reset periods provided below. The filter counter is zero upon a tamper or normal reset.

###### Filter Trigger Threshold

- Value (n): 0 to 7
- Filter Trigger Threshold: 256/2^n (256 to 2)

###### Filter Reset Period

- Value (n): 0 to 31
- Filter Reset Period: 32 ms * 2^n (32 ms to ~795.4 days)

###### Example Filter Configuration

For example, consider a device with a Filter Trigger Threshold of 3 and Filter Reset Period of 5. If that device detects 32 (256/2^3) Filter response events in 1.024 seconds (32 ms * 2^5), the `Filter counter` tamper source will trigger.

###### Reset

The reset response resets the HSE and Cortex-M33. After a tamper reset, the last reset cause can be directly read from `EMU-\>RSTCAUSE` register or using `sl_se_get_reset_cause` in the [SE Manager](03-secure-engine-manager). In cases where the reset was caused by a tamper response, the source of the tamper can be determined by calling `sl_se_get_tamper_reset_cause` in the SE Manager. (Note that this API is not available for EFR32xG21B-based parts). See [Tamper Sources](05-tamper-sources) for more information. Tamper reset occurs when the HSE sends a request to the Cortex-M33’s EMU, which issues a hard reset.

If a tamper reset is triggered during boot, this can lead to a boot loop. To debug such a scenario, the HSE has a tamper reset counter and enters diagnostic mode if the counter reaches a programmable threshold. Users can issue a non-tamper reset to clear the tamper reset counter before the programmable threshold is reached.

In diagnostic mode, the Cortex-M33 is held in reset and only DCI commands are available. The device will remain in diagnostic mode until a power-on or pin reset occurs.

For more information on the SE's DCI, see [Secure Engine Subsystem](https://docs.silabs.com/iot-security/latest/series2-secure-debug/03-secure-engine-subsystem/) in _Series 2 and Series 3 Secure Debug_.

###### Erase OTP

The Erase OTP response is the strongest reaction the HSE can take, and it will make the device and all wrapped secrets unrecoverable. After this response, the device will no longer be able to boot or connect to a debugger.

This response should typically only be used in situations where the device believes that it is under an actual attack, for instance through the detection of several voltage or digital glitches in a short time window.

##### Tamper Sources

The following table lists the available tamper sources and the default level on the EFR32xG21B. Refer to Appendix C for the other HSE-SVH and Series 3 devices. The tamper sources with the default level higher than 0 (Ignore) are always in effect even if the user does not initialize the tamper configuration in HSE OTP. Users can keep or escalate the default tamper responses (≥ 0 for Ignore and ≥ 4 for Reset) of any sources when initially configuring the part.

|**Type**|**Number**|**Name**|**Description**|**Default Level**|
|---|---|---|---|---|
|SE Hardware|0|Reserved|—|—|
|"|1|Filter counter|Filter counter reached the configured threshold value|0 (Ignore)|
|"|2|SE watchdog|Internal SE watchdog expired|4 (Reset)|
|"|3|Reserved|—|—|
|"|4|SE RAM CRC|A 2-bit, non-correctable error in the SE RAM has occurred.|4 (Reset)|
|"|5|SE hard fault|The SE core has encountered a hard fault exception indicating that an invalid memory access was attempted.|4 (Reset)|
|"|6|Reserved|—|—|
|SE Software|7|SE software assertion|SE firmware has triggered an assertion, indicating that one of several sanity checks has failed and that normal operation cannot continue without a reset.|4 (Reset)|
|"|8|SE secure boot|Secure boot of SE firmware failed|4 (Reset)|
|"|9|User secure boot|Secure boot of host firmware failed|0 (Ignore)|
|"|10|Mailbox authorization|Unauthorized command received over the Mailbox interface. This can be triggered by either (1) an incorrectly signed debug unlock or tamper disable token or (2) attempting to export a non-exportable key.|0 (Ignore)|
|"|11|DCI authorization|Unauthorized command received over the DCI interface. This can be triggered by either (1) an incorrectly signed debug unlock or tamper disable token or (2) attempting to export a non-exportable key.|0 (Ignore)|
|"|12|OTP read|OTP or flash content could not be properly authenticated.|4 (Reset)|
|"|13|Reserved|—|—|
|"|14|Self test|A check of the integrity of the SE's internal storage failed during boot up.|4 (Reset)|
|"|15|TRNG monitor|The TRNG monitor performs a number of tests on the collected entropy data. If any of these tests fail, this tamper source is triggered.|0 (Ignore)|
|Hardware|16 - 23|PRS0 - 7 [1]|PRS consumer for SE Tamper 0 - 7 asserted|0 (Ignore)|
|"|24|Decouple BOD [1]|Decouple Brown-Out-Detector threshold alert|4 (Reset)|
|"|25|Temperature sensor [1]|SE temperature is monitored to be within 5 degrees C of the limits for the device. If the limit is exceeded, this tamper source will be triggered.|0 (Ignore)|
|"|26|Voltage glitch falling|Voltage glitch detector detected a falling glitch|0 (Ignore)|
|"|27|Voltage glitch rising|Voltage glitch detector detected a rising glitch|0 (Ignore)|
|"|28|Secure lock|This tamper source indicates that the guarding mechanism (comparing the locks with their logical complement) of the debug port locks has failed.|4 (Reset)|

|**Type**|**Number**|**Name**|**Description**|**Default Level**|
|---|---|---|---|---|
|"|29|SE debug|Debug access to SE|0 (Ignore)|
|"|30|Digital glitch|Digital glitch detector detected an event|0 (Ignore)|
|"|31|SE ICACHE|The SE's instruction cache uses a checksum to verify the integrity of the data. This tamper source is triggered if the checksum is invalid.|4 (Reset)|

**Notes**:

- [1] These tamper sources are available down to EM2. Other sources are available in EM1 and above.
- In EFR32xG21B devices, hardware tamper sources 24 to 27 can operate down to Energy Mode 3 (EM3), whereas other hardware tamper sources (16 - 23 and 28 - 31) can be active down to Energy Mode 1 (EM1).
- For devices other than EFR32xG21B see [Appendix C](12-appendix-c-tamper-sources-reference) for tamper sources
- User configuration or tamper disable cannot reduce the tamper response below the default Level.
- The **User secure boot** source gets triggered if secure boot is enabled and host image verification fails. It is likely to put the device in the boot loop if users escalate the tamper response of this source to 4 (Reset).
- The **Mailbox and DCI authorizations** get triggered whenever one of the following conditions has occurred. The mailbox returns `SE_RESPONSE_AUTHORIZATION_ERROR`, and [DCI](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/) returns `AUTH_ERROR = 2`.

1. A mailbox or DCI command tries to exercise a key that it is not allowed to use (e.g., trying to export a non-exportable key).
2. A secure debug access or tamper disable request over the mailbox or DCI is invalidly signed.
3. A malformed HSE firmware upgrade over the mailbox or DCI is attempted.

- The **OTP read** gets triggered if there is an issue when decrypting and authenticating settings in HSE OTP or flash.
- The HSE has redundancy built into the locking mechanism, and the **Secure lock** source is used to detect errors in that redundancy.
- PRS inputs can allow user applications to implement additional tamper sources and feed them into the tamper response mechanism. The **PRS** tamper sources are under the control of the user application and could be reconfigured or disabled if the user application is compromised.
- The **Temperature sensor** source is not completely accurate and is generally only suitable for systems that expect to stay well within the specified temperature range. Users requiring a tighter temperature limit can implement their temperature monitor and provide the results as a tamper source via PRS.

##### Anti-Tamper Configuration

The user can provision the anti-tamper configuration in HSE OTP detailed in the following table through `sl_se_init_otp` in the [SE Manager](03-secure-engine-manager). Tamper configurations must be programmed with secure boot settings and are immutable once written.

For more information on enabling the OTP tamper configuration along with the secure boot settings, see _Enabling Secure Boot and Tamper Configuration_ in [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/09-enabling-secure-boot-and-tamper-configuration/).

|**Setting**|**Description**|
|---|---|
|Tamper response levels|A user response level for each tamper source (1)|
|Filter settings|The tamper filter counter has two settings: trigger threshold and reset period|
|Digital Glitch Detector Always On|Bit 1 of tamper flag: 0 — Digital glitch detector runs only when the HSE is executing a command; 1 — Digital glitch detector runs even when the HSE is not performing any operations (note that this leads to increased energy consumption)|
|Keep Tamper Alive During Sleep (2)|Bit 2 of tamper flag: 0 — The tamper module stops running in sleep mode; 1 — The tamper module keeps running in sleep mode (down to EM3)|
|Reset threshold|The number of consecutive tamper resets (up to 255) before the part enters diagnostic mode (3)|

**Notes**:

1. The effective response of a tamper source is the maximum value between the default level and user level (Active level = MAX(`default level`, `user level`)). If the user sets the response of a tamper source to a level lower than the default level, the setting will still be saved to HSE OTP but does not take any effect. The HSE returns the user levels instead of active levels of all tamper sources when reading back `sl_se_read_otp` the tamper configuration from the HSE OTP.
2. This flag is not available on EFR32xG21B devices.
3. If the threshold is set to 0, the part will never enter the diagnostic mode due to tamper reset.

##### Typical Configuration

Several of the available [tamper sources](05-tamper-sources) report internal HSE errors. A number of these sources are configured to reset the device (level 4) by default. Custom handling of internal and external tamper sources (default level 0) can be configured to trigger an interrupt (level 1) on the Cortex-M33 or trigger an interrupt and increase a counter in the tamper filter (level 2) as in the following figure for EFR32xG21B devices.

![Custom Handling of Tamper Sources (EFR32xG21B Devices)](/efr32-secure-vault-tamper/0.3/images/sld715-custom-handling-tamper-sources.png)

> **Note**: The actions for level 1 on the right side are implemented by the tamper interrupt handler.

###### Typical Configuration Highlights

- The response of the TRNG monitor depends on the failure rate due to lack of entropy.
- The voltage and digital glitch detectors can see spurious activations. They should typically not be used to drive a high-level tamper response directly. Instead, they should feed their signals into a tamper interrupt, which activates a high-level action (e.g., Reset in this example) through PRS tamper if a certain number of detections (noise filter) occur in a short time window.
- The operating conditions decide the time out of the specification filter for the temperature sensor. For some systems, any time out of specification should trigger a reset.
- Mailbox authorization is handled similarly for voltage and digital glitch detectors.
- A PRS tamper implements a high-level response for a tamper interrupt, which issues a tamper reset (level 4) to prevent or slow further attacks.
- In extreme cases, if the system identifies an attack with high confidence, a PRS tamper can be configured as [Erase OTP](04-tamper-responses#erase-otp) (level 7) to brick the part and prevent further attacks. This is recommended only when the destruction of parts is acceptable and where high confidence of an attack can be achieved.
- Another PRS tamper detects enclosure opening from GPIO. This source feeds into the tamper filter counter (level 2), which will trigger an interrupt cumulative effect and activate a `Filter counter` number 1 response (Reset in this example) if the filter counter reaches the trigger threshold within the filter reset period. This filter counter response approach is less flexible than the interrupt response approach since the trigger threshold and filter reset period are one-time programmable.

##### Tamper Disable

For diagnostic purposes, it may be necessary to disable the tamper response. For example, if a user has configured the part to [Erase OTP](04-tamper-responses#erase-otp) on external tamper detection, disabling the tamper response is required to open the unit and perform failure analysis or field service activities.

After the tamper configuration has been initialized, users can temporarily restore the tamper response to default for a set of tamper sources via a Disable Tamper Token authenticated against the Public Command Key in HSE OTP (similar to secure debug unlock). This is only possible if the Public Command Key has been provisioned in the device.

![Tamper Disable on the EFR32xG21B Devices](/efr32-secure-vault-tamper/0.3/images/sld715-tamper-disable-efr32xg21b-devices.png)

**For default tamper settings on other devices, refer to [Appendix C – Tamper Sources Reference](12-appendix-c-tamper-sources-reference).**

###### Disable Tamper Token

The elements of the Disable Tamper Token are described in the following figure and tables.

![Disable Tamper Token](/efr32-secure-vault-tamper/0.3/images/sld715-disable-tamper-token.png)

|**Element**|**Value**|**Description**|
|---|---|---|
|Disable tamper command|0xfd020001|The command word of the Disable Tamper Token.|
|Tamper disable mask|Device-dependent|The command parameter of the Disable Tamper Token.|
|Access certificate (1)|Device-dependent|See [Access Certificate](#access-certificate).|
|Disable tamper command signature (1)|Device-dependent|See [Challenge Response](#challenge-response).|

**Note**:

1. The disable tamper command payload consists of an access certificate and a disable tamper command signature.

![Tamper Disable Mask](/efr32-secure-vault-tamper/0.3/images/sld715-tamper-disable-mask.png)

**Note**: Set bit to restore the default response of the corresponding tamper source.

The Disable Tamper Token temporarily reverts all masked tamper sources in the figure above to the hard-coded configuration.

The Disable Tamper Token can only restore the escalated user-level configuration to default. It cannot degrade the default level of a tamper source.

###### Access Certificate

The elements of the access certificate are described in the following figure and table.

![Access Certificate](/efr32-secure-vault-tamper/0.3/images/sld715-access-certificate.png)

|**Element**|**Value**|**Description**|
|---|---|---|
|Magic word|0xe5ecce01|A constant value used to identify the access certificate.|
|Authorizations|0x0000003e (1)|A value used to authorize which bit in the debug mode request can be enabled for secure debug.|
|Tamper Authorizations|0xffffffb6 (2)|A value used to authorize which bit in the tamper disable mask can be set to disable the tamper response.|
|Serial number|Device-dependent|A number used to compare against the on-chip serial number for secure debug or tamper disable.|
|Public Certificate Key (3)|Device-dependent|The public key corresponding to the Private Certificate Key (3) used to generate the signature (ECDSA-P256-SHA256) in a challenge response.|
|Access certificate signature|Device-dependent|All the content above is signed (ECDSA-P256-SHA256) by the Private Command Key corresponding to the Public Command Key in the HSE OTP.|

**Notes**:

1. The value allows all debug options to be reset for secure debug. Note that the commands for debug unlock and tamper disable are separate, so the secure debug lock will not be disabled when issuing a tamper disable command.
2. Value that sets available bits in the tamper disable mask for tamper disable.
3. The Private/Public Certificate Key is a randomly generated key pair. It can be ephemeral or retainable.

The Private Certificate Key can be used repeatedly to generate the signature in a challenge response on one device until the Private/ Public Certificate Key pair is discarded. This can reduce the frequency of access to the Private Command Key, allowing more restrictive access control on that key.

For more information about secure debug, see [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

![Tamper Authorizations](/efr32-secure-vault-tamper/0.3/images/sld715-image43.jpg)

**Notes**:

- Set the bit to enable the corresponding bit in the tamper disable mask.
- The Disable Tamper Token will restore the default response of the corresponding tamper source if the same bit is set in the tamper disable mask and tamper authorizations. If the same bit is not set, the tamper response for that tamper source will be untouched.

###### Challenge Response

The elements of the challenge response are described in the following figure and table.

![Challenge Response](/efr32-secure-vault-tamper/0.3/images/sld715-challenge-response.png)

|**Element**|**Value**|**Description**|
|---|---|---|
|Disable tamper command|0xfd020001|The command word of Disable Tamper Token.|
|Tamper disable mask|Device-dependent|The command parameter of Disable Tamper Token.|
|Challenge|Device-dependent (1)|A random value generated by the HSE.|
|Disable tamper command signature|Device-dependent (2)|All the content above is signed (ECDSA-P256-SHA256) by the Private Certificate Key corresponding to the Public Certificate Key in the access certificate.|

**Notes**:

1. The challenge remains unchanged until it is updated to a new random value by rolling the challenge. The Private Certificate Key can be reused for signing when device challenge is refreshed.
2. This signature is the final argument of the Disable Tamper Token.

###### Tamper Disable Flow

The tamper disable flow is described in the following figure.

![Tamper Disable Flow](/efr32-secure-vault-tamper/0.3/images/sld715-tamper-disable-flow.png)

1. Get the serial number and challenge from the HSE.
2. Generate the access certificate with device serial number.
3. Generate the challenge response with device challenge.
4. Generate the disable tamper command payload with access certificate and disable tamper command signature.
5. Send the Disable Tamper Token to the HSE.
6. Verify the disable tamper command signature using the Public Certificate Key in the access certificate.
7. Verify the serial number and the access certificate signature using the on-chip serial number and Public Command Key in the HSE OTP.
8. Restore default levels on tamper disable mask until the next power-on or pin reset.
9. Roll the challenge to invalidate the current Disable Tamper Token.

> **Note**: Refer to the [Simplicity Commander example](09-examples#using-simplicity-commander) for details on how to follow this flow using Simplicity Commander.

##### Examples

###### Overview

The examples for HSE-SVH and Series 3 Secure Vault Anti-Tamper module are described in the following table.

|**Example**|**Device (Radio Board)**|**HSE Firmware**|**Tool**|
|---|---|---|---|
|Provision Tamper configuration|EFR32MG21B010F1024IM32 (BRD4181C)|Version 1.2.9|SE Manager|
|Provision Public Command Key & Tamper configuration|EFR32MG21B010F1024IM32 (BRD4181C)|Version 1.2.9|Simplicity Commander|
|"|EFR32MG21B010F1024IM32 (BRD4181C)|Version 1.2.9|Simplicity Studio 5|
|Tamper disable and Roll challenge|EFR32MG21B010F1024IM32 (BRD4181C)|Version 1.2.9|SE Manager|
|"|EFR32MG21B010F1024IM32 (BRD4181C)|Version 1.2.9|Simplicity Commander|
|Roll challenge|EFR32MG21B010F1024IM32 (BRD4181C)|Version 1.2.9|Simplicity Studio 5|

> **Note**: Unless specified in the example, these examples can be applied to other HSE-SVH and Series 3 Secure Vault devices.

###### Using Simplicity Commander (heading level 7)

1. This application note uses Simplicity Commander v1.14.6. The procedures and console output may be different on other versions of Simplicity Commander. The latest version of Simplicity Commander can be downloaded from [https://www.silabs.com/developers/mcu-programming-options](https://www.silabs.com/developers/mcu-programming-options/).  
   ```sh  
   commander --version  
   ```  
   ```sh  
   Simplicity Commander 1v14p6b1289  
     
   JLink DLL version: 7.70d  
   Qt 5.12.10 Copyright (C) 2017 The Qt Company Ltd.  
   EMDLL Version: 0v18p9b677 mbed TLS version: 2.16.6  
     
     
   DONE  
   ```
2. The Simplicity Commander's Command Line Interface (CLI) is invoked by `commander.exe` in the Simplicity Commander folder. The location for Simplicity Studio 5 in Windows is `C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander`. For ease of use, it is highly recommended to add the path of `commander.exe` to the system PATH in Windows.
3. If more than one Wireless Starter Kit (WSTK or WPK) is connected via USB, the target WSTK must be specified using the `--serialno \<J-Link serial number\>` option.
4. If the WSTK or WPK is in debug mode OUT, the target device must be specified using the --device <device name> option. For more information about Simplicity Commander, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).
5. The minimum recommended version of Simplicity Commander for SixG301 devices is v1.19.2.

###### Using an External Tool (heading level 7)

The tamper disable example uses **OpenSSL** to sign the access certificate and challenge response. The Windows version of OpenSSL can be downloaded from [https://slproweb.com/products/Win32OpenSSL.html](https://slproweb.com/products/Win32OpenSSL.html). This application note uses OpenSSL Version 3.5.0 (Win64).

```sh
openssl version
```

```sh
OpenSSL 3.5.0 8 Apr 2025
```

The OpenSSL's Command Line Interface (CLI) is invoked by openssl.exe in the OpenSSL folder. The location in Windows (Win64) is `C:\Program Files\OpenSSL-Win64\bin`. For ease of use, it is highly recommended to add the path of `openssl.exe` to the system PATH in Windows.

###### Provision Public Command Key and Tamper Configuration

The Public part of the Command Key pair can be generated from the “unsafe” private key delivered with Simplicity Studio, by Simplicity Commander, or by a Hardware Security Module (HSM). Using an HSM is recommended for production systems.

###### Public Command Key Extracted from “Unsafe” Private Key using OpenSSL (heading level 7)

External tools such as openssl can be used to generate a public key from the reference private key provided in Simplicity Studio. Note that this private key is well known and must not be used in production devices.

Run the `openssl ec` command to generate the Public Command Key from the Private Command Key.

```sh
openssl ec -in /c/SiliconLabs/SimplicityStudio/v5/developer/adapter_packs/secmgr/scripts/offline/cmd-unsafe-privkey.pem -pubout -out cmd-unsafe-pubkey.pem
```

###### Command Keypair Generated Randomly Using Simplicity Commander (heading level 7)

Run the `util genkey` command to generate the Public Command Key pair (`command_key.pem` and `command_pubkey.pem`) and Public Command Key token file (`command_pubkey.txt`).

```sh
commander util genkey --type ecc-p256 --privkey command_key.pem --pubkey command_pubkey.pem
--tokenfile command_pubkey.txt
```

```sh
Generating ECC P256 key pair...
Writing private key file in PEM format to command_key.pem
Writing public key file in PEM format to command_pubkey.pem
Writing EC tokens to command_pubkey.txt...
DONE
```

```sh
commander util keytotoken command_pubkey.pem --outfile command_pubkey.txt
```

```sh
Writing EC tokens to command_pubkey.txt...
DONE
```

###### Provision Public Command Key and Tamper Configuration (heading level 7)

1. Run the `security writekey` command to provision the Public Command Key (e.g., `command_pubkey.pem`).  
   ```sh  
   commander security writekey --command command_pubkey.pem --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   Device has serial number 000000000000000014b457fffe0f77ce  
     
   ================================================================================  
   Please look through any warnings before proceeding.  
   THIS IS A ONE-TIME command which permanently ties debug and tamper access to certificates signed by this key.  
   Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   DONE  
   ```  
   > **Note**: The Public Command Key cannot be changed once written.
2. Run the `security readkey` command to read the Public Command Key from the HSE OTP for verification with the key in step 1.  
   ```sh  
   commander security readkey --command --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   B1BC6F6FA56640ED522B2EE0F5B3CF7E5D48F60BE8148F0DC08440F0A4E1DCA4  
   7C04119ED6A1BE31B7707E5F9D001A659A051003E95E1B936F05C37EA793AD63  
   DONE  
   ```
3. Run the `security genconfig` command to generate a default `user_configuration.json` file for secure boot and tamper configuration.  
   ```sh  
   commander security genconfig --nostore -o user_configuration.json --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   Configuration file written to user_configuration.json  
   DONE  
   ```  
   > **Note**: Simplicity Commander Version 1.14.6 or above is required to support tamper configuration for all Series 2 HSE-SVH devices.
4. Use a text editor to modify the default tamper responses in `user_configuration.json` to the desired configuration as below.  
   ```sh  
   {  
   "OPN": "EFR32MG21B010F1024", "VERSION": "1.0.0",  
   "mcu_flags": { "SECURE_BOOT_ANTI_ROLLBACK": false, "SECURE_BOOT_ENABLE": false, "SECURE_BOOT_PAGE_LOCK_FULL": false, "SECURE_BOOT_PAGE_LOCK_NARROW": false, "SECURE_BOOT_VERIFY_CERTIFICATE": false  
   },  
   "tamper_filter": { "FILTER_PERIOD": 10,  
   "FILTER_THRESHOLD": 6,  
   "RESET_THRESHOLD": 5  
   },  
   "tamper_flags": { "DGLITCH_ALWAYS_ON": false  
   },  
   "tamper_levels": { "DCI_AUTH": 0,  
   "DECOUPLE_BOD": 4,  
   "DGLITCH": 2,  
   "FILTER_COUNTER": 1,  
   "MAILBOX_AUTH": 1,  
   "OTP_READ": 4,  
   "PRS0": 1,  
   "PRS1": 1,  
   "PRS2": 2,  
   "PRS3": 2,  
   "PRS4": 4,  
   "PRS5": 4,  
   "PRS6": 7,  
   "PRS7": 7,  
   "SECURE_LOCK": 4,  
   "SELF_TEST": 4,  
   "SE_CODE_AUTH": 4,  
   "SE_DEBUG": 0,  
   "SE_HARDFAULT": 4,  
   "SE_ICACHE": 4,  
   "SE_RAM_CRC": 4,  
   "SOFTWARE_ASSERTION": 4,  
   "TEMP_SENSOR": 2,  
   "TRNG_MONITOR": 1,  
   "USER_CODE_AUTH": 0,  
   "VGLITCH_FALLING": 2,  
   "VGLITCH_RISING": 2,  
   "WATCHDOG": 4  
   }  
   }  
   ```  
   **Notes**:  
   - This example does not enable the secure boot.  
   - The `SECURE_BOOT_PAGE_LOCK_FULL` and `SECURE_BOOT_PAGE_LOCK_NARROW` flags are not supported in Series 3.
5. Run the `security writeconfig` command to program the secure boot and tamper configuration to the HSE OTP. This command can be executed once per device.  
   ```sh  
   commander security writeconfig --configfile user_configuration.json --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   THIS IS A ONE-TIME configuration: Please inspect file before confirming:  
   user_configuration.json  
   Type 'continue' and hit enter to proceed or Ctrl-C to abort:  
   ================================================================================  
   continue  
   DONE  
   ```
6. Run the `security readconfig` command to check the secure boot and tamper configuration of the device.  
   ```sh  
   commander security readconfig --serialno 440030580  
   ```  
   ```sh  
   MCU Flags  
   Secure Boot                    : Disabled  
   Secure Boot Verify Certificate : Disabled  
   Secure Boot Anti Rollback      : Disabled  
   Secure Boot Page Lock Narrow   : Disabled  
   Secure Boot Page Lock Full     : Disabled  
     
   Tamper Levels  
     
   FILTER_COUNTER     : 1  
   WATCHDOG           : 4  
   SE_RAM_CRC         : 4  
   SE_HARDFAULT       : 4  
   SOFTWARE_ASSERTION : 4  
   SE_CODE_AUTH	   : 4  
   USER_CODE_AUTH	   : 0  
   MAILBOX_AUTH	   : 1  
   DCI_AUTH	       : 0  
   OTP_READ	       : 4  
   SELF_TEST	       : 4  
   TRNG_MONITOR	   : 1  
   PRS0	           : 1  
   PRS1	           : 1  
   PRS2	           : 2  
   PRS3	           : 2  
   PRS4	           : 4  
   PRS5	           : 4  
   PRS6	           : 7  
   PRS7	           : 7  
   DECOUPLE_BOD	   : 4  
   TEMP_SENSOR	       : 2  
   VGLITCH_FALLING	   : 2  
   VGLITCH_RISING	   : 2  
   SECURE_LOCK	       : 4  
   SE_DEBUG	       : 0  
   DGLITCH	           : 2  
   SE_ICACHE	       : 4  
     
   Tamper Filter  
   Filter Period   : 10  
   Filter Threshold : 6  
   Reset Threshold  : 5  
     
   Tamper Flags  
   Digital Glitch Detector Always On: Disabled  
   DONE  
   ```  
   > **Note**: The `SECURE_BOOT_PAGE_LOCK_FULL` and `SECURE_BOOT_PAGE_LOCK_NARROW` flags are not supported in Series 3.

###### Tamper Disable and Roll Challenge

See Platform Sample app for PRS connections.

The tamper disable was designed with three organizations in mind:

1. The Direct Customer to whom Silicon Labs sells the chip. This chip has the Public Command Key installed in the SE OTP.
2. The Product Company is a customer of the Direct Customer. This is applicable if the Direct Customer is creating a white-labeled product for another company or a sub-component that goes into another company’s product.
3. The Debug 3rd Party could be anyone, internal or external, that the Product Company decides is qualified to debug the device.

Because the Public Command Key is installed into the SE OTP of a large number of devices and cannot be changed, the corresponding Private Command Key must be guarded by a very stringent process. If this Private Command Key is ever leaked, all the devices programmed with the corresponding Public Command Key will be compromised.

A tamper disable use case is described in the following figure, and the signing process is performed by a Hardware Security Module (HSM).

![Tamper Disable Use Case](/efr32-secure-vault-tamper/0.3/images/sld715-tamper-disable-use-case.png)

The tamper disable flow moving across the time axis from left to right is explained below:

1. The Product Company creates a Private/Public Certificate Key pair for each device. Because the key pair is assigned only to a single device, the company may not need to protect the Private Certificate Key as securely as the Private Command Key by the Direct Customer.  
   In this example, the Private/Public Certificate Key pair (`cert_key.pem` and `cert_pubkey.pem`) is generated by running the `util genkey` command.  
   ```sh  
   commander util genkey --type ecc-p256 --privkey cert_key.pem --pubkey cert_pubkey.pem  
   ```  
   ```sh  
   Generating ECC P256 key pair...  
   Writing private key file in PEM format to cert_key.pem  
   Writing public key file in PEM format to cert_pubkey.pem  
   DONE  
   ```
2. The Public Certificate Key (`cert_pubkey.pem`) for each device is passed to the Silicon Labs Direct Customer. The part number and serial number are also required if Direct Customer cannot access the device.  
   Run the security status command to get the device serial number. The `--serialno` option is for the J-Link serial number of the WSTK.  
   ```sh  
   commander security status --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   SE Firmware version	   : 1.2.9  
   Serial number	       : 000000000000000014b457fffe0f77ce  
   Debug lock	           : Disabled  
   Device erase	       : Enabled  
   Secure debug unlock	   : Disabled  
   Tamper status	       : OK  
   Secure boot	           : Disabled  
   Boot status	           : 0x20 - OK  
   Command key installed  : True  
   Sign key installed	   : False  
   DONE  
   ```
3. The Direct Customer then places that Public Certificate Key in the access certificate. The access certificate is per device because it contains the unique device serial number. This certificate is generated once upon creation of the device, and thereafter, is generally only modified when the Private/Public Certificate Key pair is changed by the Product Company.  
   The following two steps are **OPTIONAL** for customization of Authorizations and Tamper Authorizations.  
   - (Optional) Run the `security genauth` command to generate the default certificate authorization file (`certificate_authorization.json`).    
     ```sh    
     commander security genauth -o certificate_authorizations.json --nostore --serialno 440030580    
     ```    
     ```sh    
     DONE    
     ```  
   - (Optional) Use a text editor to modify the default Authorizations and Tamper Authorizations in the `json` file.  
   Run the `security gencert` command with the following parameters from the Product Company to generate an unsigned access certificate (`access_certificate.extsign`) in Security Store:  
   - Device part number  
   - Device serial number  
   - Public Certificate Key  
   ```sh  
   commander security gencert --device EFR32MG21B010F1024 --deviceserialno 000000000000000014b457fffe0f77ce  
   --cert-pubkey cert_pubkey.pem --extsign  
   ```  
   ```sh  
   Authorization file written to Security Store:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/ certificate_authorizations.json  
   Cert key written to Security Store:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/ cert_pubkey.pem  
   Created an unsigned certificate in Security Store:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/ access_certificate.extsign  
   DONE  
   ```  
   **Notes**:  
   - The `--extsign` option to create an unsigned access certificate is only available in Simplicity Commander Version 1.11.2 or above.  
   - The unsigned access certificate is generated with the default certificate authorization file (`certificate_authorization.json`) which uses `0x0000003e` for Authorizations and `0xffffffb6` (HSE-SVH device) for Tamper Authorizations.  
   - (Optional) Use `--authorization` option if the customized json file generated in the above optional steps is used.  
   ```sh  
   commander security gencert --device EFR32MG21B010F1024 --authorization certificate_authorizations.json  
   --deviceserialno 000000000000000014b457fffe0f77ce --cert-pubkey cert_pubkey.pem –extsign –outfile access_certificate.extsign  
   ```
4. The signing of the access certificate can be done by passing an unsigned access certificate to a Hardware Security Module (HSM) containing the Private Command Key.  
   In this example, the OpenSSL is used to sign the access certificate (`access_certificate.extsign`) in Security Store with the Private Command Key (`command_key.pem`). The access certificate signature is in the `cert_signature.bin` file.  
   ```sh  
   openssl dgst -sha256 -binary -sign command_key.pem -out cert_signature.bin access_certificate.extsign  
   ```  
   Run the `util signcert` command with the following parameters to verify the signature and generate the signed access certificate (`access_certificate.bin`):  
   - Unsigned access certificate  
   - Access certificate signature  
   - Public Command Key  
   ```sh  
   commander util signcert access_certificate.extsign --cert-type access --signature cert_signature.bin  
   --verify command_pubkey.pem --outfile access_certificate.bin  
   ```  
   ```sh  
   R = 76CDC5BA18E5248FDA5418002F250F149B449829A005D6F0726268016CC53ED4  
   S = E4B8ABA2CF742B0E6CC5BA2C1023D76BEEF3C4A11DA97CC4D23459F32237A206  
   Successfully verified signature  
   Successfully signed certificate  
   DONE  
   ```  
   **Notes**:  
   - Put the required files in the same folder to run the command.  
   - The `util signcert` command for access certificate is only available in Simplicity Commander Version 1.11.2 or above.  
   - The access certificate signature can be in a Raw or Distinguished Encoding Rules (DER) format.
5. The access certificate is passed to the Product Company. The purpose of the access certificate is to grant overall debug access capabilities to the Product Company and authorize them to allow third parties to debug the device. The Product Company can now use the access certificate to generate the Disable Tamper Token. The same access certificate can be used to generate as many Disable Tamper Tokens as necessary without having to ever go back to the Direct Customer.
6. To create the Disable Tamper Token, a debug session must be started with the device and the challenge value (which is a random number `Challenge 1` in this example) should be read out to generate the challenge response.  
   Run the `security gencommand` command to generate the challenge response without disable tamper command signature and store it in a file (`command_unsign.bin`).  
   ```sh  
   commander security gencommand --action disable-tamper --disable-param 0x00fa0000 -o command_unsign.bin  
   --nostore --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   Unsigned command file written to:  
   command_unsign.bin  
   DONE  
   ```  
   **Notes**:  
   - The tamper disable mask (`0x00fa0000`) is based on the Tamper platform example on EFR32xG21B devices (See readme.md in the Platform sample).  
   - If the `--disable-param` option is not provided, it will restore all tamper sources (`0xffffffb6`) by default.
7. The challenge response is then cryptographically hashed (SHA-256) to create a digest. The digest is then signed by the Private Certificate Key to generate the disable tamper command signature.  
   The signing of the challenge response can be done by passing an unsigned challenge response to a Hardware Security Module (HSM) containing the Private Certificate Key.  
   In this example, the OpenSSL is used to sign the challenge response (`command_unsign.bin`) with the Private Certificate Key (`cert_key.pem`). The disable tamper command signature is in the `command_signature.bin` file.  
   ```sh  
   openssl dgst -sha256 -binary -sign cert_key.pem -out command_signature.bin command_unsign.bin  
   ```
8. Run the `security disabletamper` command with the access certificate (`access_certificate.bin`) from Direct Customer and disable tamper command signature (`command_signature.bin`) in step 7 to generate the Disable Tamper Token.  
   ```sh  
   commander security disabletamper --disable-param 0x00fa0000 --cert access_certificate.bin  
   --command-signature command_signature.bin EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   Certificate written to Security Store:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/ device_000000000000000014b457fffe0f77ce/access_certificate.bin  
   R = A70834D97640A92510D151765F0EED6C6A05CB8BE81E06E905C230ED24E71659  
   S = 9B69C113C2B7DEE60BF0BC7D72719F7F9465840D68EADBBB4F9BCE7A1267B936  
   Command signature is valid  
   Tamper successfully disabled.  
   Command disable tamper payload was stored in Security Store  
   DONE  
   ```  
   **Notes**:  
   - Put the required files in the same folder to run the command.  
   - The disable tamper command signature can be in a Raw or Distinguished Encoding Rules (DER) format.  
   - Simplicity Commander Version 1.11.2 or above is required to support signature in DER format.
9. (Alternative) Key protection is not required if the Private Certificate Key is ephemeral. Steps 6 to 8 can be implemented by running the `security disabletamper` command with the access certificate (`access_certificate.bin`) from the Direct Customer and Private Certificate Key (`cert_key.pem`) to generate the Disable Tamper Token.  
   ```sh  
   commander security disabletamper --disable-param 0x00fa0000 --cert access_certificate.bin --cert-privkey  
   cert_key.pem --device EFR32MG21B010F1024 --serialno 440030580  
   ```  
   ```sh  
   Certificate written to Security Store:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/access_certificate.bin  
   Cert key written to Security Store:  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/cert_pubkey.pem  
   Created unsigned disable tamper command  
   Signed disable tamper command using  
   C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/cert_key.pem  
   Tamper successfully disabled.  
   Command disable tamper payload was stored in Security Store  
   DONE  
   ```
10. The Disable Tamper Token (aka `Command disable tamper payload`) file (`tamper_payload_111110100000000000000000.bin`, where `111110100000000000000000` is `0x00fa0000` for tamper disable mask) is stored in the Security Store. The location in Windows is `C:\Users\<PC user name>\AppData\Local\SiliconLabs\commander\SecurityStore\device_<Serial number>\challenge_<Challenge value>`.  
    ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image71.jpg)  
    Users can also use the `security getpath` command to get the path of the Security Store or a specified device.  
    ```sh  
    commander security getpath  
    ```  
    ```sh  
    C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore  
    DONE  
    ```  
    ```sh  
    commander security getpath --deviceserialno 0000000000000000588e81fffe70350d  
    ```  
    ```sh  
    C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_0000000000000000588e81fffe70350d  
    DONE  
    ```
11. The Disable Tamper Token and the device are now delivered to the Debug 3rd Party.  
    Run the `security gencommand` command to create the Security Store to place the Disable Tamper Token file.  
    ```sh  
    commander security gencommand --action disable-tamper --disable-param 0x00fa0000  
    --device EFR32MG21B010F1024 --serialno 440030580  
    ```  
    ```sh  
    Unsigned command file written to Security Store:  
    C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/challenge_8e7f73e6322edda06b62997155334f29/ disable_tamper_command_to_be_signed09_08_2021.bin  
    DONE  
    ```  
    Copy the Disable Tamper Token file (`tamper_payload_111110100000000000000000.bin`) from Product Company to the Windows Security Store `challenge_<Challenge value>` folder located in `C:\Users\<PC user name>\AppData\Local\SiliconLabs\commander\SecurityStore\device_<Serial number>\challenge_<Challenge value>`.
12. The device compares the Disable Tamper Token contents with its internal serial number, challenge value, and Public Command Key to determine the token’s authenticity. If authentic, it will execute the disable tamper command to restore the default levels on the tamper disable mask (`0xfa000000`); otherwise, it will ignore the command.  
    Run the `security disabletamper` command to disable the tamper.  
    ```sh  
    commander security disabletamper --disable-param 0x00fa0000 --device EFR32MG21B010F1024  
    --serialno 440030580  
    ```  
    ```sh  
    Disabling tamper with tamper payload:  
    C:/Users/<username>/AppData/Local/SiliconLabs/commander/SecurityStore/device_000000000000000014b457fffe0f77ce/challenge_8e7f73e6322edda06b62997155334f29/ tamper_payload_111110100000000000000000.bin  
    Tamper successfully disabled.  
    DONE  
    ```  
    > **Note**: Users can verify the Disable Tamper Token by following steps 4 to 6 in [Tamper Disable](08-tamper-disable) if the EFR32xG21B device is running in the Normal mode of the SE Manager Tamper platform example.
13. The Debug 3rd Party can now use this same Disable Tamper Token to disable the tamper (step 12), over and over again after each power-on or pin reset, until they have finished debugging the device.
14. Once the Debug 3rd Party has finished debugging, they will send the device back to the Product Company.
15. Once the Product Company receives the device, they will immediately start a debug session to roll the challenge (from `Challenge 1` to `Challenge 2` in this example). Rolling the challenge will effectively invalidate any Disable Tamper Token that has been previously given to any third party.  
    Run the `security rollchallenge` command and reset the device to invalidate the current Disable Tamper Token. The challenge cannot be rolled before it has been used at least once; that is, by running the `security disabletamper` or `security unlock` command.  
    ```sh  
    commander security rollchallenge --device EFR32MG21B010F1024 --serialno 440030580  
    ```  
    ```sh  
    Challenge was rolled successfully.  
    DONE  
    ```  
    The unlock token is invalidated after rolling the challenge because any previously issued Disable Tamper Token now contains a different challenge value (`Challenge 1`) than the challenge value currently in the device (`Challenge 2`).  
    The validation process of any previously issued Disable Tamper Token will always fail until a new Disable Tamper Token is issued with a current matching challenge value (`Challenge 2`).  
    > **Note**: Direct Customer can directly use the Private Command Key on the connected chip to generate the Disable Tamper Token in Security Store. But it has a high risk (cannot use HSM) to leak the Private Command Key to a 3rd party when using this approach.  
    ```sh  
    commander security disabletamper --disable-param 0x00fa0000 --command-key command_key.pem  
    --device EFR32MG21B010F1024 --serialno 440030580  
    ```

##### Appendix A: Examples with Simplicity Studio

###### Overview

The security operations are performed in the Security Settings of Simplicity Studio. This application note uses Simplicity Studio v5.4.0.0. The procedures and pictures may be different on the other version of Simplicity Studio 5.

1. Right-click the selected debug adapter **RB (ID:J-Link serial number)** to display the context menu.  
   ![Debug Adapters Context Menu](/efr32-secure-vault-tamper/0.3/images/sld715-image72.jpg)
2. Click **Device configuration...** to open the **Configuration of device: J-Link Silicon Labs (serial number)** dialog box. Click the **Security Settings** tab to get the selected device configuration.  
   ![Configuration on Selected Device](/efr32-secure-vault-tamper/0.3/images/sld715-image73.png)

###### Provision Public Command Key and Tamper Configuration

This example focuses on provisioning the Public Command Key and tamper configuration. It skips the procedures for provisioning of the Public Sign Key and Secure Boot Enabling.

1. Run the `util keytotoken` command to convert the Public Command Key file (PEM format) into a text file (`command_pubkey.txt`).  
   ```sh  
   commander util keytotoken command_pubkey.pem --outfile command_pubkey.txt  
   ```  
   ```sh  
   Writing EC tokens to command_pubkey.txt...  
   DONE  
   ```
2. Open the **Security Settings** of the selected device as described in [Using Simplicity Studio](09-examples#using-simplicity-commander).
3. Click [**Start Provisioning Wizard...**] in the upper right corner to display the **Secure Initialization** dialog box.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image74.jpg)
4. Click [**Edit**] to open the **Tamper Source Configuration** dialog box. Use the dropdown menus to modify the default tamper responses to the desired configuration. Click [**OK**] to exit.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image75.png)
5. Click [**Next >**]. The **Security Keys** dialog box is displayed.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image76.jpg)
6. Using a text editor, open the `command_pubkey.txt` file generated in step 1.  
   ```sh  
   MFG_SIGNED_BOOTLOADER_KEY_X : B1BC6F6FA56640ED522B2EE0F5B3CF7E5D48F60BE8148F0DC08440F0A4E1DCA4  
   MFG_SIGNED_BOOTLOADER_KEY_Y : 7C04119ED6A1BE31B7707E5F9D001A659A051003E95E1B936F05C37EA793AD63  
   ```
7. Check **Enable Writing Command Key**. Copy the Public Command Key (X-point `B1BC...` first, then Y-point `7C04...`) to the **Key:** box under **Command Key:**.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image77.jpg)  
   > **Note**: This example does not enable the secure boot (not checking **Enable Writing Sign Key** option).
8. Click [**Next >**]. The **Secure Locks** dialog box is displayed. The **Debug locks** are set by default. Uncheck **Enable secure debug unlock** and **Enable debug lock**.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image78.jpg)
9. Click [**Next >**] to display the **Summary** dialog box. Verify the tamper configuration and Public Command Key in the **Provisioning Summary** are correct.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image79.png)
10. If the information displayed is correct, click [**Provision**]. Click [**Yes**] to confirm.  
    ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image80.png)  
    > **Note**: The Public Command Key and tamper configuration cannot be changed once written.
11. The **Provisioning Status** is displayed in the **Summary** dialog box.  
    ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image81.png)
12. Click [**Done**] to exit the provisioning process. The device configuration is updated.  
    ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image82.png)

###### Tamper Disable and Roll Challenge

1. Open **Security Settings** of the selected device as described in [Using Simplicity Studio](09-examples#using-simplicity-studio).
2. Click [**Roll Challenge**] to generate a new challenge value to invalidate the Disable Tamper Token for tamper disable. Click [**OK**] to exit.  
   ![screenshot](/efr32-secure-vault-tamper/0.3/images/sld715-image83.jpg)

##### Appendix B: Platform Examples

###### Overview

Simplicity Studio 5 includes the [SE Manager platform examples](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/start-a-project#examples) for Secure Tamper. Refer to the corresponding readme file for details about the SE Manager example. This file also includes the procedures to create the project and run the example.

<table>
    <thead>
        <tr>
            <th>Category</th>
            <th>SE Manager Platform Example</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Tamper provisioning and runtime operations</td>
            <td>SoC SE Manager Tamper</td>
            <td>
                Sample application to:
                <ul>
                    <li>provision tamper settings</li>
                    <li>temporarily disable tamper and roll challenge</li>
                    <li>Implement an interrupt handler for a filtered tamper source</li>
                </ul>
            </td>
        </tr>
    </tbody>
</table>

###### Adapting PRS Tamper for Custom Hardware

The platform examples are designed to work with Silicon Labs development kits. To adapt the code to work with custom hardware a few steps are required as follows. In the sample application these steps are found in `init_tamper_prs` of the `app_se_manager_tamper.c` source file:

1. Set up the GPIO pin as an input. The sample application demonstrates calls to set up the GPIO. It is recommended to install the ‘simple button’ software component to ensure that the necessary drivers are installed.
2. Set up an unused PRS channel as a producer. The sample application uses PRS channels 6, 7 and 8. Refer to the reference manual for your device to determine the source and signal for GPIO. The sample application demonstrates API calls for Series 2 and Series 3 devices.
3. Connect the PRS channel chosen in the previous step to the desired tamper signal. Tamper signals are named `CONSUMER_SETAMPER_TAMPERSR\<bit\>`, where bit is the bit position of the PRS tamper signal. Refer to [Tamper Sources](05-tamper-sources) for the bit positions of PRS tamper signals in the EFR32xG21B and [Appendix C: Tamper Sources Reference](12-appendix-c-tamper-sources-reference) for the bit positions of PRS tamper signals in other devices. The sample application demonstrates calls to perform this task.

##### Appendix C: Tamper Sources Reference

This section provides the tamper sources for devices other than EFR32xG21B.

###### Tamper Sources on Other Series 2 HSE-SVH Devices

|**Type**|**Number**|**Name**|**Description**|**Default Level**|
|---|---|---|---|---|
|SE Hardware|0|Reserved|—|—|
|"|1|Filter counter|Filter counter reached the configured threshold value|0 (Ignore)|
|"|2|SE watchdog|Internal SE watchdog expired|4 (Reset)|
|"|3|Reserved|—|—|
|"|4|SE RAM ECC2|A 2-bit, non-correctable error in the SE RAM has occurred.|4 (Reset)|
|"|5|SE hard fault|The SE core has encountered a hard fault exception indicating that an invalid memory access was attempted.|4 (Reset)|
|"|6|Reserved|—|—|
|SE Software|7|SE software assertion|SE firmware has triggered an assertion, indicating that one of several sanity checks has failed and that normal operation cannot continue without a reset.|4 (Reset)|
|"|8|SE secure boot|Secure boot of SE firmware failed|4 (Reset)|
|"|9|User secure boot|Secure boot of host firmware failed|0 (Ignore)|
|"|10|Mailbox authorization|Unauthorized command received over the Mailbox interface. This can be triggered by either (1) an incorrectly signed debug unlock or tamper disable token or (2) attempting to export a non-exportable key.|0 (Ignore)|
|"|11|DCI authorization|Unauthorized command received over the DCI interface. This can be triggered by either (1) an incorrectly signed debug unlock or tamper disable token or (2) attempting to export a non-exportable key.|0 (Ignore)|
|"|12|OTP read|OTP or flash content could not be properly authenticated|4 (Reset)|
|"|13|Reserved|—|—|
|"|14|Self test|A check of the integrity of the SE's internal storage failed during boot up.|4 (Reset)|
|"|15|TRNG monitor|The TRNG monitor performs a number of tests on the collected entropy data. If any of these tests fail, this tamper source is triggered.|0 (Ignore)|
|Hardware|16|Secure lock|This tamper source indicates that the guarding mechanism (comparing the locks with their logical complement) of the debug port locks has failed.|4 (Reset)|
|"|17|Digital glitch|Digital Glitch detector detected an event|0 (Ignore)|
|"|18|Voltage glitch|Voltage Glitch Detector detected an event|0 (Ignore)|
|"|19|SE ICACHE|The SE's instruction cache uses a checksum to verify the integrity of the data. This tamper source is triggered if the checksum is invalid.|4 (Reset)|

|**Type**|**Number**|**Name**|**Description**|**Default Level**|
|---|---|---|---|---|
|"|20|SE RAM ECC1|SE RAM 1-bit ECC error occurred|0 (Ignore)|
|"|21|BOD [1]|Brown-Out-Detector threshold alert|4 (Reset)|
|"|22|Temperature sensor [1]|SE temperature is monitored to be within 5 degrees C of the limits for the device. If the limit is exceeded, this tamper source will be triggered.|0 (Ignore)|
|"|23|DPLL fall|DPLL lock failed low|0 (Ignore)|
|"|24|DPLL rise|DPLL lock failed high|0 (Ignore)|
|"|25|PRS0 or ETAMPDET|PRS consumer for SE Tamper 25 or ETAMPDET asserted|0 (Ignore)|
|"|26 - 31|PRS1 - 6 or PRS0 - 5 [1]|PRS consumer for SE Tamper 26 - 31 asserted|0 (Ignore)|

**Notes**:

- [1] These tamper sources are available down to EM2. Other sources are available in EM1 and above.
- On EFR32xG23B and later devices, the default behavior is to detect tamper events only when the SE core is active. To detect tamper events when the SE is not performing operations, call `sl_se_enter_active_mode()`. This prevents the SE from sleeping and will result in higher current draw.
- In other HSE-SVH devices, tamper sources 25 to 31 are used for External Tamper Detect (ETAMPDET) if present and PRS consumers. Devices with ETAMPDET (e.g. EFR32xG25B) will have 6 PRS consumers (26 to 31) and devices without ETAMPDET will have 7 PRS consumers (25 to 31).
- The **ETAMPDET** source gets triggered when any of the ETAMPDET channels are asserted.

###### Tamper Sources on SixG301 Devices

|**Type**|**Number**|**Name**|**Description**|**Default Level**|
|---|---|---|---|---|
|SE Hardware|0|Reserved|—|—|
|"|1|Filter counter|Filter counter reached the configured threshold value|0 (Ignore)|
|"|2|SE watchdog|Internal SE watchdog expired|4 (Reset)|
|"|3|Crypto error|HostSymCrypto (1)|4 (Reset)|
|"|4|SE RAM ECC2|A 2-bit, non-correctable error in the SE RAM has occurred.|4 (Reset)|
|"|5|Reserved|--|-|
|"|6|SE major fault|SE major fault detected(2)|4 (Reset)|
|SE Software|7|L2 ICACHE|L2 instruction cache error|4 (Reset)|
|"|8|Reserved|--|-|
|"|9|User secure boot|Secure boot of host firmware failed|0 (Ignore)|
|"|10|Mailbox authorization|Unauthorized command received over the Mailbox interface. This can be triggered by either (1) an incorrectly signed debug unlock or tamper disable token or (2) attempting to export a non-exportable key.|0 (Ignore)|
|"|11|DCI authorization|Unauthorized command received over the DCI interface. This can be triggered by either (1) an incorrectly signed debug unlock or tamper disable token or (2) attempting to export a non-exportable key.|0 (Ignore)|
|"|12|SE Software Assert|SE software triggers an assert|4 (Reset)|
|"|13|Reserved|—|—|
|"|14|Self test|A check of the integrity of the SE's internal storage failed during boot up.|4 (Reset)|
|"|15|TRNG monitor|The TRNG monitor performs a number of tests on the collected entropy data. If any of these tests fail, this tamper source is triggered.|0 (Ignore)|
|Hardware|16|Secure lock|This tamper source indicates that the guarding mechanism (comparing the locks with their logical complement) of the debug port locks has failed.|4 (Reset)|
|"|17|Glitch Detector|Any tamper detection|0 (Ignore)|
|"|18|OTP Alarm|OTP alarm triggered(3)|4 (Reset)|
|"|19|SE ICACHE|The SE's instruction cache uses a checksum to verify the integrity of the data. This tamper source is triggered if the checksum is invalid.|4 (Reset)|
|“|20|SE RAM ECC 1|SE RAM 1-bit ECC error|0 (Ignore)|
| |21|Brownout detect|Brown-out-detector threshold alert|4 (Reset)|
| |22|Temperature sensor|On-device temperature sensor|0 (Ignore)|
| |23|DPLL Lock|DPLL lock failure|0 (Ignore)|
| |24|SoC PLL|SoC PLL failure|0 (Ignore)|
| |25|eTamper detect|External tamper detect|0 (Ignore)|
| |26|KSU ECC 1|KSU ECC 1-bit error|0 (Ignore)|
| |27|KSU ECC 2|KSU ECC 2-bit error|4 (Reset)|
| |28|QSPI Reseed|QSPI reseed error|4 (Reset)|
| |29|PRS0|PRS channel 0 asserted|0 (Ignore)|
| |30|PRS1|PRS channel 1 asserted|0 (Ignore)|
| |31|PRS2|PRS channel 2 asserted|0 (Ignore)|

**Notes**:

1. HOSTSYMCRYPTO is the host cryptographic accelerator referred to as SYMCRYPTO in SixG301 reference manual.
2. The SE Major fault is triggered by any unrecoverable error in the SE code.
3. The OTP alarm is triggered if the OTP data cannot be read and verified.

#### Authenticating Silicon Labs Devices using Device Certificates

##### Authenticating Silicon Labs Devices Using Device Certificates

> **Note: This section replaces _AN1268: Authenticating Silicon Labs Devices Using Device Certificates_. Further updates to this application note will be provided here**.

This application note describes how to authenticate a device as a genuine Silicon Labs product at any time during its life. The digital certificates for secure identity are stored in the device and the Silicon Labs Server. This secure identity feature is only available on Secure Vault High devices.

###### Key Points

- Secure identity on Secure Vault High devices
- Device certificate options
- Entity Attestation Token (EAT)
- Remote authentication process
- Examples for certificate chain verification and remote authentication

##### Series 2 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

<table>
    <thead>
        <tr>
            <th>Level (1)</th>
            <th>SE Support</th>
            <th>Part (2)</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Secure Vault High (SVH)</p>
            </td>
            <td>
                <p>HSE only (HSE-SVH)</p>
            </td>
            <td>
                <p>EFR32xG2yB (3)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Mid (SVM)</p>
            </td>
            <td>
                <p>HSE (HSE-SVM)</p>
            </td>
            <td>
                <p>EFR32xG2yA (3)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>"</p>
            </td>
            <td>
                <p>VSE (VSE-SVM)</p>
            </td>
            <td>
                <p>EFR32xG2y, EFM32PG2y (4)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Base (SVB)</p>
            </td>
            <td>
                <p>N/A</p>
            </td>
            <td>
                <p>MCU Series 1 and Wireless SoC Series 1</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).
2. The x is a letter (B, F, M, or Z).
3. At the time of this writing, the y is a digit (1, 3, or 4).
4. At the time of this writing, the y is a digit (2).

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by "wrapping" or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

<table>
    <thead>
        <tr>
            <th>Key Name</th>
            <th>Customer Programmed</th>
            <th>Purpose</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Public Sign key (Sign Key Public)</p>
            </td>
            <td>
                <p>Yes</p>
            </td>
            <td>
                <p>Secure Boot binary authentication and/or OTA upgrade payload authentication</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Public Command key (Command Key Public)</p>
            </td>
            <td>
                <p>Yes</p>
            </td>
            <td>
                <p>Secure Debug Unlock or Disable Tamper command authentication</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>OTA Decryption key (GBL Decryption key) aka AES-128 Key</p>
            </td>
            <td>
                <p>Yes</p>
            </td>
            <td>
                <p>Decrypting GBL payloads used for firmware upgrades</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Attestation key aka Private Device Key</p>
            </td>
            <td>
                <p>No</p>
            </td>
            <td>
                <p>Device authentication for secure identity</p>
            </td>
        </tr>
    </tbody>
</table>

###### Device Compatibility

This application note applies to Series 2 HSE-SVH device families. Refer to [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for details on supporting devices.

##### Introduction

One of the biggest challenges for connected devices is post-deployment authentication. Silicon Labs’ factory trust provisioning service with optional secure programming provides a secure device identity certificate, analogous to a birth certificate, for each individual silicon die during integrated circuit (IC) manufacturing. This enables post-deployment security, authenticity, and attestation-based health checks. The device certificate guarantees the authenticity of the device for its lifetime. When the certificate is checked, a digital signature confirms that the certificate received has not been tampered with.

Certificates can now be used to authenticate Internet of Things (IoT) devices as well as Internet servers, now that Silicon Labs’ HSE-SVH devices have both cryptographic acceleration in hardware and tamper-resistant storage to handle digital certificate operations.

The digital signature and certificates are major cryptographic tools to verify the device is authentic. These tools are described in the following sections.

###### Digital Signature

The digital signature is used to protect integrity and authenticity of an electronic message.

###### Digital Signature Example (heading level 7)

Alice wants to give data to Bob, and Bob wants to make sure that the data came from Alice and has not been tampered with. Alice has a private/public key pair, and has previously given Bob her public key.

![Digital Signature](/authenticating-devices-using-device-certificates/0.2/images/sld790-digital-signature.png)

1. Alice  generates the hash (for example SHA256) of the data.
2. Alice's private key is used to sign the hash to create a signature. The hash is signed instead of the data itself because the signing operation is slow. Therefore it is more efficient to sign the hash instead of the arbitrarily large data.
3. The signature is attached to the end of the data.
4. The data and signature are given to Bob.
5. Bob independently generates the hash of the data.
6. The signature is verified with the hash and Alice’s public key, which results in a true or false outcome indicating if the data is valid.

> **Note**: This scheme requires distribution of Alice's public key.

###### Digital Certificates and Chain of Trust

In [Digital Signature Example](#digital-signature), Bob already had access to Alice’s public key, which he trusted. However, it is not always feasible to pre-share a public key with everyone for secure identity verification, and no mechanism exists to revoke or inactivate the public key in case it gets stolen.

A digital certificate is simply a small, verifiable data file that contains identity credentials and a public key. That data is then signed either with the corresponding private key, or a different private key. The digital certificate can be used to prove the ownership of a public key.

- If it is signed using the corresponding private key, it is called a self-signed certificate.
- If it is signed by another private key, the owner of that private key is acting as a Certificate Authority (CA).
- A Certificate Authority (CA) is a trusted third party by both the owner and party relying on the certificate.

Concatenation of digital certificates builds a chain of trust.

- At the root of the chain is a self-signed certificate called a root certificate or a CA certificate.
- The root or CA certificate can be used to sign another certificate.

![Digital Certificates and Chain of Trust](/authenticating-devices-using-device-certificates/0.2/images/sld790-digital-certificates-and-chain-of-trust.png)

> **Note**: The private key is never included as part of the certificate – it must be stored separately and kept private. The security of the scheme relies on protecting the private keys.

###### Digital Certificates Verification

This section illustrates the process shown in [Digital Signature Example](#digital-signature), but using digital certificates.

###### Digital Certificates Verification Example (heading level 7)

Alice wants to give data to Bob, signed with her private key. Alice has a digital certificate signed by a trusted third party (CA) in addition to her private key. Bob has a certificate from the trusted CA but nothing else is previously shared.

![Digital Certificate Verification](/authenticating-devices-using-device-certificates/0.2/images/sld790-digital-certificate-verification.png)

1. Alice uses her private key to sign the data.
2. Alice gives the data, signature, and her certificate to Bob.
3. Bob first verifies that Alice's certificate is valid, to prove Alice is the owner of the certificate's public key. This is done by verifying that Alice's certificate contains a valid signature created by the CA.
4. Bob then verifies the signature of the data using the public key in Alice's certificate.

> **Note**: The hash process in [Digital Signature Example](#digital-signature-example) is skipped in this example.

##### Secure Identification on HSE-SVH Devices

The goal of secure identification is to prove the ownership of a device's unique public key to an external service. It enables the external service to identify the device as legitimate and to authenticate device-generated data or messages.

###### Chain of Trust

The chain of trust on HSE-SVH devices is illustrated in the following figure.

![Chain of Trust](/authenticating-devices-using-device-certificates/0.2/images/sld790-chain-of-trust.png)

- Silicon Labs is a Certificate Authority (CA).
- The root certificate and factory certificate are stored in the Silicon Labs Server.
- The factory certificate is static per factory.
- The batch certificate and device certificate are stored on the device.
- The batch certificate is rolled per production batch.
- The device certificate is a unique cryptographic identity.
- All certificates are X.509 standard format.  
  - TLS-compliant: Standard endpoint authentication methods are used in internet communications  
  - Signature algorithm: ECDSA-prime256v1 with SHA256
- Each certificate in the chain is signed by the certificate above it ([Signing and Verification figure](#signing-and-verification)).

> **Note**: A certificate can be revoked if needed, for instance if security issues arise. The certificate revocation lists are stored in the Silicon Labs Server.

###### Device Certificate

The device certificate example is described in the following figure.

![Device Certificate Example](/authenticating-devices-using-device-certificates/0.2/images/sld790-device-certificate-example.png)

- The device certificate is in X.509 DER format (~0.5 kB).
- The device certificate is stored in HSE one-time programmable memory (OTP). It cannot be modified once programmed.
- The batch number (`Issuer: CN = Batch` field) identifies the factory and batch in which the device was produced.
- The validity period is 100 years from device manufacture date.
- The device 64-bit hard-coded unique ID (EUI) is encoded in the `Subject: CN` field, which blinds this certificate to the device.
- The device-specific public key is embedded in the device certificate and the corresponding private key is securely stored in the Secure Key Storage on the chip.
- The Issuer's private key is used to sign the hash of the certificate data to create a device certificate signature.

###### Signing and Verification

Signing and verification for certificates on HSE-SVH devices are described in the following figures.

![Signing for Certificates](/authenticating-devices-using-device-certificates/0.2/images/sld790-signing-for-certificates.png)

![Verification for Certificates](/authenticating-devices-using-device-certificates/0.2/images/sld790-verification-for-certificates.png)

##### Device Certificate Options

The HSE-SVH devices are each programmed with a device certificate during IC production. The device certificate is signed with a Public Device Key, using a Private Batch Key that can be validated against a Silicon Labs certificate chain [Verification for Certificates](03-r-secureidentity#signing-and-verification) and [Certificate Chain Verification](08-r-examples#certificate-chain-verification). The device private key never leaves the Secure Key Storage on the chip. Customers can create their own device certificates during their production.

Three device certificate options (standard, modified, and external) are provided to meet different requirements. Silicon Labs provides [Custom Part Manufacturing Service (CPMS)](https://www.silabs.com/developers/custom-part-manufacturing-service) to program custom certificates on your chips at the Silicon Labs factories. For more information about CPMS, see [Custom Part Manufacturing Service User's Guide](https://docs.silabs.com/iot-security/latest/iot-security-cpms/).

###### Standard Device Certificate

- Comes standard with HSE-SVH devices.
- Cryptographically proves the device is an authentic Silicon Labs device.
- Does not protect against overproduction or counterfeit products that are built with authentic Silicon Labs devices.
- Signed to a Silicon Labs Certificate Authority (CA).
- The device can prove that it possesses the private key associated with the public key in its certificate by signing the response to a given challenge ([Remote Authentication Process](06-r-remoteauthenticationprocess) and [Certificate Chain Verification and Remote Authentication](08-r-examples#certificate-chain-verification-and-remote-authentication)).

![Standard Device Certificate](/authenticating-devices-using-device-certificates/0.2/images/sld790-standard.png)

###### Modified Device Certificate

- Available as a customization service on HSE-SVH devices (OEM custom part number).
- Cryptographically proves the device is an authentic Silicon Labs device that was produced for a specific OEM.
- Protects against overproduction by Contract Manufacturer (CM).
- Device Certificate X.509 fields can be specified, with restrictions.
- Signed to a Silicon Labs Certificate Authority (CA).

![Modified Device Certificate](/authenticating-devices-using-device-certificates/0.2/images/sld790-modified.png)

###### External Device Certificate

- Available as a customization service on HSE-SVH devices (OEM custom part number).
- Cryptographically proves the device is an authentic Silicon Labs device that was produced for a specific OEM.
- Protects against overproduction by Contract Manufacturer (CM).
- Factory Certificate is custom for each OEM.
- Device Certificate and Factory Certificate X.509 fields can be specified, with restrictions.
- Signed to a OEM Certificate Authority (CA).
- Root Certificate Authority is OEM-specified and is optional.
- Electronic delivery of all batch and device certificates signed under this OEM factory certificate is supported.

![External Device Certificate](/authenticating-devices-using-device-certificates/0.2/images/sld790-external.png)

##### Entity Attestation Token (EAT)

The device attestation service creates a token that contains a fixed set of device-specific data when requested from the caller. The device must contain an attestation key pair, which is unique per device, to sign the token. The HSE-SVH device uses the [Private Device Key](01-series-2-security-features#key-reference) (aka attestation key) to sign the token, and the caller uses the Public Device Key to verify the token's authenticity.

An Entity Attestation Token (EAT) is a mini-report that is cryptographically signed. An EAT is encoded in either one of two standardized data formats: a Concise Binary Object Representation ([CBOR](https://www.rfc-editor.org/info/rfc7049)) or in the text-based format JSON. A digital signature is then used to protect its content. The technical specification defining the content of the EAT, which are claims about the hardware and the software running on a device, is specified by the Internet Engineering Task Force ([IETF](https://datatracker.ietf.org/doc/html/draft-ietf-rats-eat-11#ref-RATS.Architecture)).

An EAT is a collection of Key ID-Value pairs relating to device pedigree or any other information one wants the device to attest. Collected data can originate from the Root of Trust (RoT), any protected area, or non-protected areas.

The EAT must be signed following the structure of the CBOR Object Signing and Encryption ([COSE](https://www.rfc-editor.org/info/rfc8152)) specification. For asymmetric key algorithms, the signature structure must be COSE-Sign1. A COSE-Sign1 is a CBOR encoded, self-secured data blob that contains headers, a payload, and a signature.

The primary need for EAT verification is to check correct formatting and verify signatures as for any token. In addition, though, the verifier can operate a policy where values of some of the claims in this profile can be compared to reference values, registered with the verifier for a given deployment, to confirm that the device is endorsed by the manufacturer supply chain.

The HSE can generate the [PSA attestation token or security configuration token](08-r-examples#entity-attestation-token-eat) when requested from the caller with a [challenge](06-r-remoteauthenticationprocess) (Auth challenge claim below). The following tables describe EAT claims that are used in the [PSA attestation token](https://www.ietf.org/archive/id/draft-tschofenig-rats-psa-token-08.txt) and security configuration token.

> **Note**: The actual claims returned from the tokens are HSE firmware version dependent.

<table>
    <caption>Claims of PSA Attestation Token</caption>
    <thead>
        <tr>
            <th>Key ID</th>
            <th>Claim</th>
            <th>Description</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>-75000</p>
            </td>
            <td>
                <p>Profile definition</p>
            </td>
            <td>
                <p>Name of a document that describes the profile of the report.</p>
            </td>
            <td>
                <p>PSA_IOT_PROFILE_1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75001</p>
            </td>
            <td>
                <p>Client ID</p>
            </td>
            <td>
                <p>Represents the Partition ID of the caller.</p>
            </td>
            <td>
                <p>See note below</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75002</p>
            </td>
            <td>
                <p>Security lifecycle</p>
            </td>
            <td>
                <p>Represents the current life cycle stage of the PSA RoT.</p>
            </td>
            <td>
                <p>Device dependent</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75003</p>
            </td>
            <td>
                <p>Implementation ID</p>
            </td>
            <td>
                <p>Uniquely identifies the underlying immutable PSA RoT.</p>
            </td>
            <td>
                <p>Device dependent (32 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75004</p>
            </td>
            <td>
                <p>Boot seed</p>
            </td>
            <td>
                <p>Represents a random value created at system boot time.</p>
            </td>
            <td>
                <p>Random bytes (32 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75006</p>
            </td>
            <td>
                <p>Software components</p>
            </td>
            <td>
                <p>A list of Software components represents all the software loaded by PSA RoT.</p>
            </td>
            <td>
                <p>See the software components table below.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75008</p>
            </td>
            <td>
                <p>Auth challenge</p>
            </td>
            <td>
                <p>Input object from the caller. For example, this can be a cryptographic nonce or a hash of locally attested data. The length must be 32, 48, or 64 bytes.</p>
            </td>
            <td>
                <p>Random bytes or hash (32/48/64 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75009</p>
            </td>
            <td>
                <p>Instance ID</p>
            </td>
            <td>
                <p>Unique identifier of the instance.</p>
            </td>
            <td>
                <p>Device EUI-64 unique ID with type byte 0x06 (9 bytes)</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - Key ID 75001: Client ID if present. Otherwise the value 1 for a token requested by a secure bus master and -1 for a non-secure master.
> - Key ID 75002 (For the definitions of these lifecycle states, please refer to the ARM [Platform Security Model](https://developer.arm.com/documentation/den0128/0100/)):
>   - UNKNOWN (`0x0000`)
>   - ASSEMBLY_AND_TEST (`0x1000`)
>   - PSA_ROT_PROVISIONING (`0x2000`)
>   - SECURED (`0x3000`)
>   - NON_PSA_ROT_DEBUG (`0x4000`)
>   - RECOVERABLE_PSA_ROT_DEBUG (`0x5000`)
>   - DECOMMISSIONED (`0x6000`)
> - Key ID 75003:
>   - Word[0]: Die revision
>   - Word[1]: HSE OTP version
>   - Word[2]: Bit indicating it is an HSE-SVH device
>   - Word[3]: Production version
>   - Word[4:7]: Reserved (zeros)

<table>
    <caption>Software Components</caption>
    <thead>
        <tr>
            <th>Key ID</th>
            <th>Type</th>
            <th>Description</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Measurement type</p>
            </td>
            <td>
                <p>A short string represents the role of this software component.</p>
            </td>
            <td>
                <p>See note below</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Measurement value</p>
            </td>
            <td>
                <p>Represents a hash of the invariant software component in memory at startup time.</p>
            </td>
            <td>
                <p>See note below</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Version</p>
            </td>
            <td>
                <p>The issued software version is in the form of a text string.</p>
            </td>
            <td>
                <p>See note below</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- Key ID 1:  
  - HSE always exists — **PRoT**  
  - If secure booted Gecko Bootloader exists at flash starting address — **BL**  
  - If secure booted application exists at flash starting address — **ARoT**
- Key ID 2: SHA-256 hash (32 bytes) of the firmware (HSE, Gecko Bootloader, or application)
- Key ID 4: Version of the firmware (HSE, Gecko Bootloader, or application)

<table>
    <caption>Claims of Security Configuration Token</caption>
    <thead>
        <tr>
            <th>Key ID</th>
            <th>Claim</th>
            <th>Description</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>-75000</p>
            </td>
            <td>
                <p>Profile definition</p>
            </td>
            <td>
                <p>Name of a document that describes the profile of the report.</p>
            </td>
            <td>
                <p>SILABS_1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75008</p>
            </td>
            <td>
                <p>Auth challenge</p>
            </td>
            <td>
                <p>Input object from the caller. For example, this can be a cryptographic nonce or a hash of locally attested data. The length must be 32 bytes.</p>
            </td>
            <td>
                <p>Random bytes or hash (32 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-75009</p>
            </td>
            <td>
                <p>Instance ID</p>
            </td>
            <td>
                <p>Unique identifier of the instance.</p>
            </td>
            <td>
                <p>Device EUI-64 unique ID with type byte 0x06 (9 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-76000</p>
            </td>
            <td>
                <p>SE status</p>
            </td>
            <td>
                <p>Device HSE status.</p>
            </td>
            <td>
                <p>Device dependent (36 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-76001</p>
            </td>
            <td>
                <p>OTP configuration</p>
            </td>
            <td>
                <p>Device HSE OTP configuration if provisioned.</p>
            </td>
            <td>
                <p>Device dependent (24 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-76002</p>
            </td>
            <td>
                <p>Sign Key</p>
            </td>
            <td>
                <p>Public Sign Key in HSE OTP if provisioned.</p>
            </td>
            <td>
                <p>Device dependent (64 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-76003</p>
            </td>
            <td>
                <p>Command Key</p>
            </td>
            <td>
                <p>Public Command Key in HSE OTP if provisioned.</p>
            </td>
            <td>
                <p>Device dependent (64 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>-76004</p>
            </td>
            <td>
                <p>Tamper settings</p>
            </td>
            <td>
                <p>Current applied tamper settings.</p>
            </td>
            <td>
                <p>Device dependent (16 bytes)</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- All custom Silicon Labs claims will have a base of 76000.
- Key ID 76000: Refer to the _Get Status_ section in [Programming Series 2 Devices using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/05-se-command-list#get-status) for the description (HSE-SVH) of the value.
- Key ID 76001: Refer to the _Read User Configuration_ section in [Programming Series 2 Devices using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/05-se-command-list#read-user-configuration) for the description (HSE-SVH) of the value.
- Key ID 76002 and 76003: Refer to [Key Reference](01-series-2-security-features#key-reference-key-reference) for Public Sign Key and Public Command Key.
- Key ID 76004: One nibble per tamper source. Refer to the _Anti-Tamper Configuration_ section in [Programming Series 2 Devices using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/05-se-command-list#anti-tamper-configuration) for the description of the value.

##### Remote Authentication Process

Remote authentication is used to manage attestation by requesting that the device sign a challenge or [EAT](05-r-entityattestationtoken) based on its secure identity.

![Remote Authentication Process](/authenticating-devices-using-device-certificates/0.2/images/sld790-remote-authentication-process.png)

1. The remote device requests the device certificate and batch certificate from the HSE-SVH device.
2. The remote device looks up the factory certificate and root certificate from the Silicon Labs Server.
3. The remote device validates each certificate in the chain using the public key of each Issuer ([Verification for Certificates](03-r-secureidentity#signing-and-verification-signing-and-verification)).
4. The remote device then sends an attestation challenge (random number) to the HSE-SVH device. The HSE-SVH device uses the Private Device Key in the Secure Key Storage on the chip to sign the challenge or EAT and sends the signature of challenge or EAT to the remote device.
5. The remote device requires a small library to validate the signature of challenge or EAT using the Public Device Key in the device certificate.

##### Secure Engine Manager

The Secure Engine Manager provides thread-safe APIs for the SE's mailbox interface. The following table lists the SE Manager APIs related to secure identity. The SE Manager API document can be found at [https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager).

For the SE's mailbox interface, see section _Secure Engine Subsystem_ in [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/03-r-secureelement).

<table>
    <caption>SE Manager API for Security Identity</caption>
    <thead>
        <tr>
            <th>SE Manager API</th>
            <th>Usage</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sl_se_read_pubkey</p>
            </td>
            <td>
                <p>Read stored Public Device Key in the HSE-SVH device.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_read_cert</p>
            </td>
            <td>
                <p>Read stored certificates (DER format) in the HSE-SVH device.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_read_cert_size</p>
            </td>
            <td>
                <p>Read the size of stored certificates in the HSE-SVH device.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_attestation_get_psa_iat_token</p>
            </td>
            <td>
                <p>Get the PSA attestation token from the HSE with the given nonce.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_attestation_get_psa_iat_token_size</p>
            </td>
            <td>
                <p>Get the size of a PSA attestation token with the given nonce.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_attestation_get_config_token</p>
            </td>
            <td>
                <p>Get the security configuration token from the HSE with the given nonce.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_attestation_get_config_token_size</p>
            </td>
            <td>
                <p>Get the size of a security configuration token with the given nonce.</p>
            </td>
        </tr>
    </tbody>
</table>

##### Examples

###### Overview

The secure device authentication examples are described in the following table.

<table>
    <caption>Secure Device Authentication Examples</caption>
    <thead>
        <tr>
            <th>Example</th>
            <th>Device (Radio Board)</th>
            <th>HSE Firmware</th>
            <th>Tool</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Certificate chain verification</p>
            </td>
            <td>
                <p>EFR32MG21B010F1024IM32 (BRD4181C)</p>
            </td>
            <td>
                <p>Version 1.2.9</p>
            </td>
            <td>
                <p>Simplicity Commander and OpenSSL</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Certificate chain verification</p>
            </td>
            <td>
                <p>EFR32MG21B010F1024IM32 (BRD4181C)</p>
            </td>
            <td>
                <p>Version 1.2.9</p>
            </td>
            <td>
                <p>Simplicity Commander</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Certificate chain verification</p>
            </td>
            <td>
                <p>EFR32MG21B010F1024IM32 (BRD4181C)</p>
            </td>
            <td>
                <p>Version 1.2.9</p>
            </td>
            <td>
                <p>Simplicity Studio 5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Certificate chain verification &amp; Remote authentication</p>
            </td>
            <td>
                <p>EFR32MG21B010F1024IM32 (BRD4181C)</p>
            </td>
            <td>
                <p>Version 1.2.9</p>
            </td>
            <td>
                <p>SE Manager and Mbed TLS</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Entity Attestation Token (EAT)</p>
            </td>
            <td>
                <p>EFR32MG21B010F1024IM32 (BRD4181C)</p>
            </td>
            <td>
                <p>Version 1.2.9</p>
            </td>
            <td>
                <p>SE Manager</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Entity Attestation Token (EAT)</p>
            </td>
            <td>
                <p>EFR32MG21B010F1024IM32 (BRD4181C)</p>
            </td>
            <td>
                <p>Version 1.2.9</p>
            </td>
            <td>
                <p>Simplicity Commander</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: Unless specified in the example, these examples can apply to other HSE-SVH devices.

Users can download the device root certificate (`Device-Root-CA-chain.pem`) and factory certificate (`Factory-chain.pem`) from [https://www.silabs.com/certificate-authority](https://www.silabs.com/certificate-authority).

![Cert Server](/authenticating-devices-using-device-certificates/0.2/images/sld790-cert-server.png)

For Simplicity Studio v5.3.0.0 and higher, the device root certificate (`device-root-prod.pem`) and factory certificate (`factory-prod.pem`) can be found in the Window folder below.

C:\SiliconLabs\SimplicityStudio\v5\offline\common\certificates

###### Using Simplicity Commander (heading level 7)

1. This application note uses Simplicity Commander v1.11.2. The procedures and console output may be different on the other versions of Simplicity Commander. The latest version of Simplicity Commander can be downloaded from [https://www.silabs.com/developers/mcu-programming-options](https://www.silabs.com/developers/mcu-programming-options).  
   ```sh  
   commander --version  
   ```  
   ```sh  
   Simplicity Commander 1v11p2b998  
     
   JLink DLL version: 6.94d  
   Qt 5.12.1 Copyright (C) 2017 The Qt Company Ltd.  
   EMDLL Version: 0v17p18b581  
   mbed TLS version: 2.6.1  
     
     
   DONE  
   ```
2. The Simplicity Commander's Command Line Interface (CLI) is invoked by `commander.exe` in the Simplicity Commander folder. The location for Simplicity Studio 5 in Windows is `C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander`. For ease of use, it is highly recommended to add the path of `commander.exe` to the system `PATH` in Windows.
3. If more than one Wireless Starter Kit (WSTK) is connected via USB, the target WSTK must be specified using the `--serialno \<J-Link serial number>` option.
4. If the WSTK is in debug mode OUT, the target device must be specified using the `--device \<device name>` option.

For more information about Simplicity Commander, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### Using an External Tool (heading level 7)

The [certificate chain verification](#certificate-chain-verification) example uses the **OpenSSL** to validate the certificate chain. The Windows version of OpenSSL can be downloaded from [https://slproweb.com/products/Win32OpenSSL.html](https://slproweb.com/products/Win32OpenSSL.html). This application note uses OpenSSL Version 1.1.1h (Win64).

```sh
openssl version
```

```sh
OpenSSL 1.1.1h  22 Sep 2020
```

The OpenSSL's Command Line Interface (CLI) is invoked by `openssl.exe` in the OpenSSL folder. The location in Windows (Win64) is `C:\Program Files\OpenSSL-Win64\bin`. For ease of use, it is highly recommended to add the path of `openssl.exe` to the system `PATH` in Windows.

###### Using Platform Examples (heading level 7)

Simplicity Studio 5 includes the [SE Manager platform examples](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/start-a-project#examples) for secure identity and attestation. This application note uses platform example of GSDK v3.2.3. The console output may be different on the other versions of GSDK.

Refer to the corresponding `readme.html` file for details about each SE Manager platform example. This file also includes the procedures to create the project and run the example.

###### Certificate Chain Verification

Certificate chain verification is the process of making sure a given certificate chain is well-formed, valid, properly signed, and trustworthy. The certificate signature is verified using the public key in the issuer certificate ([Verification for Certificates](03-r-secureidentity#signing-and-verification)).

###### Simplicity Commander and OpenSSL (heading level 7)

1. Run the `security readcert` command to save the batch certificate in PEM format.  
   ```sh  
   commander security readcert batch -o batch.pem --serialno 440030580  
   ```  
   ```sh  
   Writing certificate to batch.pem...  
   DONE  
   ```
2. Run the `security readcert` command to save the device certificate in PEM format.  
   ```sh  
   commander security readcert mcu -o device.pem --serialno 440030580  
   ```  
   ```sh  
   Writing certificate to device.pem...  
   DONE  
   ```
3. Get the root certificate (`device-root-prod.pem`) and factory certificate (`factory-prod.pem`) from the certificate folder in [Simplicity Studio](#examples).
4. Use OpenSSL to display the certificate information (e.g., `device.pem`).  
   ```sh  
   openssl x509 -in device.pem -text -noout  
   ```  
   ```sh  
   Certificate:  
       Data:  
           Version: 3 (0x2)  
           Serial Number:  
               66:f8:5a:e6:b4:ef:6e:49:d3:36:95:63:c9:c3:99:13:e4:71:93:f6  
           Signature Algorithm: ecdsa-with-SHA256  
           Issuer: CN = Batch 1001317, O = Silicon Labs Inc., C = US  
           Validity  
               Not Before: Nov 19 15:10:33 2019 GMT  
               Not After : Nov 19 15:10:33 2119 GMT  
           Subject: C = US, O = Silicon Labs Inc., CN = EUI:14B457FFFE0F77CE DMS:086AEC3C645836BFB04D312F S:SE0 ID:MCU  
           Subject Public Key Info:  
               Public Key Algorithm: id-ecPublicKey  
                   Public-Key: (256 bit)  
                   pub:  
                       04:5c:4b:c9:b0:b3:ff:fa:99:81:c5:99:be:ff:ae:  
                       77:74:1a:f4:30:f1:1e:0e:2d:df:96:4b:ff:d2:46:  
                       fa:fa:e7:23:4b:79:cb:0a:c7:71:13:fa:7c:39:5f:  
                       e2:18:9e:4e:06:43:88:a7:9c:65:53:f3:a3:a1:06:  
                       81:e6:06:f2:11  
                   ASN1 OID: prime256v1  
                   NIST CURVE: P-256  
           X509v3 extensions:  
               X509v3 Basic Constraints: critical  
                   CA:FALSE  
               X509v3 Key Usage: critical  
                   Digital Signature, Non Repudiation, Key Encipherment  
               X509v3 Extended Key Usage: critical  
                   TLS Web Client Authentication  
       Signature Algorithm: ecdsa-with-SHA256  
           30:44:02:20:57:12:a4:84:d8:37:b8:c0:44:8f:16:ac:c1:a3:  
           be:a9:f1:16:38:9f:b9:a2:57:e6:12:49:bf:96:a9:a9:d2:b8:  
           02:20:5f:ae:22:f5:00:05:49:b1:da:ee:4a:84:48:70:27:97:  
           1c:40:2d:85:5f:f2:12:b3:8b:4a:d7:9a:ee:60:81:7c  
   ```
5. Use OpenSSL to verify the certificate chain from steps 1 to 3.

```sh
openssl verify -show_chain -CAfile device-root-prod.pem -untrusted factory-prod.pem -untrusted batch.pemdevice.pem
```

```sh
device.pem: OKChain:
depth=0: C = US, O = Silicon Labs Inc., CN = EUI:14B457FFFE0F7777 DMS:086AEC3CE650543EE73568DA S:SE0 ID:MCU (untrusted)
depth=1: CN = Batch 1001317, O = Silicon Labs Inc., C = US (untrusted)
depth=2: CN = Factory, O = Silicon Labs Inc., C = US (untrusted)
depth=3: CN = Device Root CA, O = Silicon Labs Inc., C = US
```

###### Simplicity Commander (heading level 7)

Run the `security readcert` command to display the key information about the on-chip certificates (e.g., mcu).

```sh
commander security readcert mcu --serialno 440030580
```

```sh
Version            : 3
Subject            : C=US  O=Silicon Labs Inc.  CN=EUI:14B457FFFE0F77CE DMS:086AEC3C645836BFB04D312F S:SE0 ID:MCU
Issuer             : CN=Batch 1001317  O=Silicon Labs Inc.  C=US
Valid From         : November 19 2019
Valid To           : November 19 2119
Signature algorithm: SHA256
Public Key Type    : ECDSA
Public key         : 5c4bc9b0b3fffa9981c599beffae77741af430f11e0e2ddf964bffd246fafae7
                     234b79cb0ac77113fa7c395fe2189e4e064388a79c6553f3a3a10681e606f211
DONE
```

Run the `security attestation` command to verify the on-chip batch and device certificates with root and factory certificates.

```sh
commander security attestation --serialno 440030580
```

```sh
Certificate chain successfully validated up to Silicon Labs device root certificate.
-75008 ARM PSA nonce                   : 05a88aeef627dd663058e3d758fe9a827942da0793da72af81c79a4f60fa9824
-75000 ARM PSA Profile ID              : SILABS_1
-75009 ARM PSA/IETF EAT UEID           : 0614b457fffe0f77ce
-76000 SE status                       : 000000010000000000000000000003a90000002000010209ffffffff0000002500000000
-76001 OTP configuration               : 00000000100444400401041411224477242204420a060005
-76002 MCU sign key                    : c4af4ac69aab9512db50f7a26ae5b4801183d85417e729a56da974f4e08a562c
                                         de6019dea9411332dc1a743372d170b436238a34597c410ea177024de20fc819
-76003 MCU command key                 : b1bc6f6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc08440f0a4e1dca4
                                         7c04119ed6a1be31b7707e5f9d001a659a051003e95e1b936f05c37ea793ad63
-76004 Current applied tamper settings : 15044440040104141122447714220442
Successfully validated signature of attestation token.
DONE
```

###### Simplicity Studio (heading level 7)

This application note uses Simplicity Studio v5.2.1.1. The procedures and pictures may be different on the other versions of Simplicity Studio 5.

1. Right-click the selected debug adapter **RB (ID:J-Link serial number)** to display the context menu.  
   ![Device Config](/authenticating-devices-using-device-certificates/0.2/images/sld790-device-config.png)
2. Click **Device configuration...** to open the **Configuration of device: J-Link Silicon Labs (serial number)** dialog box. Click the **Security Settings** tab to get the selected device configuration.
3. The **MCU Certificate:** will display **Validated Successfully** if it passed the certificate chain verification process.  
   ![Cert Studio](/authenticating-devices-using-device-certificates/0.2/images/sld790-cert-studio.png)
4. Click **Certificate Details...** to browse the details of different certificates (e.g., Device MCU Certificate in the figure below).

![Device Cert](/authenticating-devices-using-device-certificates/0.2/images/sld790-device-cert.png)

###### Certificate Chain Verification and Remote Authentication

The SE Manager Secure Identity platform example uses APIs in [SE Manager](07-r-secureenginemanager) and Mbed TLS to emulate the processes in [Remote Authentication Process](06-r-remoteauthenticationprocess).

Click the `View Project Documentation` link to open the `readme.html` file.

![Si Example](/authenticating-devices-using-device-certificates/0.2/images/sld790-si-example.png)

The HSE-SVH device simulates the operations in the remote device to eliminate the communications between different parties in this example. The factory certificate and root certificate are hard-coded in the `app_mbedtls_x509.c` file.

The Private Device Key in the Secure Key Storage on the chip is used to sign the challenge from the remote device. Therefore this example can only run on a chip with the [Standard Device Certificate](04-r-devicecertoptions).

###### Step 1 in the Remote Authentication Process (heading level 7)

```sh
SE Manager Secure Identity Example - Core running at 38000 kHz.
  . SE manager initialization... SL_STATUS_OK (cycles: 6 time: 0 us)

  . Secure Vault High device:
  + Read size of on-chip certificates... SL_STATUS_OK (cycles: 5296 time: 139 us)
  + Read on-chip device certificate... SL_STATUS_OK (cycles: 5138 time: 135 us)
  + Parse the device certificate (DER format)... SL_STATUS_OK (cycles: 167043 time: 4395 us)
  + Get the public device key in device certificate... OK
  + Read on-chip batch certificate... SL_STATUS_OK (cycles: 5080 time: 133 us)
  + Parse the batch certificate (DER format)... SL_STATUS_OK (cycles: 173151 time: 4556 us)
```

###### Steps 2 and 3 in the Remote Authentication Process (certificate chain printout is disabled) (heading level 7)

```sh
. Remote device:
  + Parse the factory certificate (PEM format)... SL_STATUS_OK (cycles: 5373122 time: 141 ms)
  + Parse the root certificate (PEM format)... SL_STATUS_OK (cycles: 5448802 time: 143 ms)
  + Verify the certificate chain with root certificate... SL_STATUS_OK (cycles: 958730 time: 25229 us)
```

###### Steps 2 and 3 in the Remote Authentication Process (certificate chain printout is enabled) (heading level 7)

```sh
. Remote device:
  + Parse the factory certificate (PEM format)... SL_STATUS_OK (cycles: 5373935 time: 141 ms)
  + Parse the root certificate (PEM format)... SL_STATUS_OK (cycles: 5449622 time: 143 ms)
  + Verify requested for (Depth 3) ... OK
      cert. version     : 3
      serial number     : 12:E6:A2:A5:9C:AA:27:F9
      issuer name       : CN=Device Root CA, O=Silicon Labs Inc., C=USsubject name      : CN=Device Root CA, O=Silicon Labs Inc., C=US
      issued  on        : 2018-10-10 17:32:00
      expires on        : 2118-09-16 17:32:00
      signed using      : ECDSA with SHA256
      EC key size       : 256 bits
      basic constraints : CA=true, max_pathlen=2
      key usage         : Digital Signature, Key Cert Sign, CRL Sign
  + Verify requested for (Depth 2) ... OK
      cert. version     : 3
      serial number     : 24:DC:7B:40:0C:32:9C:0A
      issuer name       : CN=Device Root CA, O=Silicon Labs Inc., C=USsubject name      : CN=Factory, O=Silicon Labs Inc., C=US
      issued  on        : 2018-10-10 17:33:00
      expires on        : 2118-09-16 17:32:00
      signed using      : ECDSA with SHA256
      EC key size       : 256 bits
      basic constraints : CA=true, max_pathlen=1
      key usage         : Digital Signature, Key Cert Sign, CRL Sign
  + Verify requested for (Depth 1) ... OK
      cert. version     : 3
      serial number     : 23:09:DA:39:B4:78:05:AA
      issuer name       : CN=Factory, O=Silicon Labs Inc., C=USsubject name      : CN=Batch 1001317, O=Silicon Labs Inc., C=US
      issued  on        : 2019-10-17 21:20:20
      expires on        : 2118-09-16 17:32:00
      signed using      : ECDSA with SHA256
      EC key size       : 256 bits
      basic constraints : CA=true, max_pathlen=0
      key usage         : Digital Signature, Key Cert Sign
  + Verify requested for (Depth 0) ... OK
      cert. version     : 3
      serial number     : 66:F8:5A:E6:B4:EF:6E:49:D3:36:95:63:C9:C3:99:13:E4:71:93:F6
      issuer name       : CN=Batch 1001317, O=Silicon Labs Inc., C=USsubject name      : C=US, O=Silicon Labs Inc., CN=EUI:14B457FFFE0F77CE DMS:086AEC3C645836BFB04D312F S:SE0 ID:MCU
      issued  on        : 2019-11-19 15:10:33
      expires on        : 2119-11-19 15:10:33
      signed using      : ECDSA with SHA256
      EC key size       : 256 bits
      basic constraints : CA=false
      key usage         : Digital Signature, Non Repudiation, Key Encipherment
      ext key usage     : TLS Web Client Authentication
  + Verify the certificate chain with root certificate... SL_STATUS_OK (cycles: 9703861 time: 255 ms)
```

> **Note**: The longer processing time (255 ms) is due to the certificate chain printout.

###### Steps 4 and 5 (signature of a challenge) in the Remote Authentication Process (heading level 7)

```sh
. Remote authentication:
  + Create a 16 bytes challenge (random number) in remote device for signing... SL_STATUS_OK (cycles: 3700 time: 97 us)
  + Sign challenge with private device key in Secure Vault High device... SL_STATUS_OK (cycles: 221983 time: 5841 us)
  + Get public device key in Secure Vault High device... SL_STATUS_OK (cycles: 199788 time: 5257 us)
  + Verify signature with public device key in Secure Vault High device... SL_STATUS_OK (cycles: 229054 time: 6027 us)
  + Verify signature with public device key in remote device... SL_STATUS_OK (cycles: 230442 time: 6064 us)

  . SE manager deinitialization... SL_STATUS_OK (cycles: 6 time: 0 us)
```

###### Entity Attestation Token (EAT)

These examples demonstrate how to retrieve the [EAT tokens](05-r-entityattestationtoken) from the HSE-SVH device.

###### SE Manager - Attestation Platform Example (heading level 7)

The SE Manager Attestation platform example uses APIs in [SE Manager](07-r-secureenginemanager) to retrieve the PSA attestation token and security configuration token from the HSE.

Click the `View Project Documentation` link to open the `readme.html` file.

![Att Example](/authenticating-devices-using-device-certificates/0.2/images/sld790-att-example.png)

Press `SPACE` to cycle the challenge size for the PSA attestation token. Press `ENTER` to make a selection and run the program.

```sh
SE Manager Attestation Example - Core running at 38000 kHz.
Initializing SE Manager...
SL_STATUS_OK (cycles: 10 time: 0 us)

Select nonce size for the IAT token (32, 48 or 64 bytes).
Press SPACE to cycle through the options.
Press ENTER to make a selection.
    Current nonce size:  32
    Selected nonce size: 32
Calling sl_se_attestation_get_psa_iat_token...

SL_STATUS_OK (cycles: 661072 time: 17396 us)
```

**PSA Attestation Token** ([Entity Attestation Token (EAT)](05-r-entityattestationtoken) and [Entity Attestation Token (EAT)](05-r-entityattestationtoken))

```sh
PSA IAT token
=============
-------------------------------------------------------------------
Raw token:
d28443a10126a058e4a83a000124ff58204ca14d0bc8601cad2e511de1964e93
9338b6fc20f8231aa178ca79519b0ffae73a000124f7715053415f494f545f50
524f46494c455f313a00012500490614b457fffe0f77ce3a000124f8013a0001
24f91920003a000124fa5820011c00010600000001000000f2030f0000000000
0000000000000000000000003a000124fb58204922b7bbd31c0c81c9b0485ccf
b5396ec24ffa877ece441e11c947b791218cf83a000124fd81a3016450526f54
046830303031303230390258206d39caedba129297062b820ba6d85b3e432c44
3c8a8a31d3c6232be6906d38dc584030f9d61523204793965fc9eb2be788db9d
2b02692d877673c86ebffbfb6769984515d2f1a287a92d2c134c1024f20f018d
be952a2ccae7ed2980a9f242d02c9c

COSE_Sign1 structure:
d2    ; tag(18)
  84    ; array(4)
    43    ; byte_str(3)
      a10126
    a0    ; map(0)
    58    ; byte_str(228)
      a83a000124ff58204ca14d0bc8601cad2e511de1964e939338b6fc20f8231aa1
	  78ca79519b0ffae73a000124f7715053415f494f545f50524f46494c455f313a
	  00012500490614b457fffe0f77ce3a000124f8013a000124f91920003a000124
	  fa5820011c00010600000001000000f2030f0000000000000000000000000000
	  0000003a000124fb58204922b7bbd31c0c81c9b0485ccfb5396ec24ffa877ece
	  441e11c947b791218cf83a000124fd81a3016450526f54046830303031303230
	  390258206d39caedba129297062b820ba6d85b3e432c443c8a8a31d3c6232be6
	  906d38dc
    58    ; byte_str(64)
      30f9d61523204793965fc9eb2be788db9d2b02692d877673c86ebffbfb676998
	  4515d2f1a287a92d2c134c1024f20f018dbe952a2ccae7ed2980a9f242d02c9c
-------------------------------------------------------------------
Token claims:
a8    ; map(8)
  3a    ; int(-75008)
  58    ; byte_str(32)
    4ca14d0bc8601cad2e511de1964e939338b6fc20f8231aa178ca79519b0ffae7
  3a    ; int(-75000)
  71    ; text_str(17)
    "PSA_IOT_PROFILE_1"
  3a    ; int(-75009)
  49    ; byte_str(9)
    0614b457fffe0f77ce
  3a    ; int(-75001)
  01    ; int(1)
  3a    ; int(-75002)
  19    ; int(8192)
  3a    ; int(-75003)
  58    ; byte_str(32)
    011c00010600000001000000f2030f0000000000000000000000000000000000
  3a    ; int(-75004)
  58    ; byte_str(32)
    4922b7bbd31c0c81c9b0485ccfb5396ec24ffa877ece441e11c947b791218cf8
  3a    ; int(-75006)
  81    ; array(1)
    a3    ; map(3)
      01    ; int(1)
      64    ; text_str(4)
        "PRoT"
      04    ; int(4)
      68    ; text_str(8)
        "00010209"
      02    ; int(2)
      58    ; byte_str(32)
        6d39caedba129297062b820ba6d85b3e432c443c8a8a31d3c6232be6906d38dc

List of claims printed with human-friendly names:
  ARM PSA Nonce, Claim ID: -75008
  58    ; byte_str(32)
    4ca14d0bc8601cad2e511de1964e939338b6fc20f8231aa178ca79519b0ffae7

  ARM PSA Profile ID, Claim ID: -75000
  71    ; text_str(17)
    "PSA_IOT_PROFILE_1"

  ARM PSA / IETF EAT UEID, Claim ID: -75009
  49    ; byte_str(9)
    0614b457fffe0f77ce

  ARM PSA Partition ID, Claim ID: -75001
  01    ; int(1)

  ARM PSA Lifecycle, Claim ID: -75002
  19    ; int(8192)

  ARM PSA Implementation ID, Claim ID: -75003
  58    ; byte_str(32)
    011c00010600000001000000f2030f0000000000000000000000000000000000

  ARM PSA Boot seed, Claim ID: -75004
  58    ; byte_str(32)
    4922b7bbd31c0c81c9b0485ccfb5396ec24ffa877ece441e11c947b791218cf8

  ARM PSA Software components, Claim ID: -75006
  81    ; array(1)
    a3    ; map(3)
      01    ; int(1)
      64    ; text_str(4)
        "PRoT"
      04    ; int(4)
      68    ; text_str(8)
        "00010209"
      02    ; int(2)
      58    ; byte_str(32)
        6d39caedba129297062b820ba6d85b3e432c443c8a8a31d3c6232be6906d38dc
```

**Security Configuration Token** ([Entity Attestation Token (EAT)](05-r-entityattestationtoken))

```sh
-------------------------------------------------------------------

Calling sl_se_attestation_get_config_token...
SL_STATUS_OK (cycles: 541281 time: 14244 us)

Config token
============
-------------------------------------------------------------------
Raw token:
d28443a10126a0590133a83a000124ff5820c3e3664dcc47711bf81734bc95f0
87d81dd841d73fc805fc9237c7b3dfa25c503a000124f76853494c4142535f31
3a00012500490614b457fffe0f77ce3a000128df582400000001000000000000
0000000000000000002000010209ffffffff00000025000000003a000128e058
1800000000100444400401041411224477242204420a0600053a000128e15840
c4af4ac69aab9512db50f7a26ae5b4801183d85417e729a56da974f4e08a562c
de6019dea9411332dc1a743372d170b436238a34597c410ea177024de20fc819
3a000128e25840b1bc6f6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc0
8440f0a4e1dca47c04119ed6a1be31b7707e5f9d001a659a051003e95e1b936f
05c37ea793ad633a000128e350150444400401041411224477142204425840b7
47d98be9cef8a91af0292a479a3fa499527018b97ac1188ddefb0fa6fcb9b3d1
d4159240a8663c8803a2ef7cebdf7644fa3394cf1057d612e1b3977d9de92d

COSE_Sign1 structure:
d2    ; tag(18)
  84    ; array(4)
    43    ; byte_str(3)
      a10126
    a0    ; map(0)
    59    ; byte_str(307)
	  a83a000124ff5820c3e3664dcc47711bf81734bc95f087d81dd841d73fc805fc
	  9237c7b3dfa25c503a000124f76853494c4142535f313a00012500490614b457
	  fffe0f77ce3a000128df58240000000100000000000000000000000000000020
	  00010209ffffffff00000025000000003a000128e05818000000001004444004
	  01041411224477242204420a0600053a000128e15840c4af4ac69aab9512db50
	  f7a26ae5b4801183d85417e729a56da974f4e08a562cde6019dea9411332dc1a
	  743372d170b436238a34597c410ea177024de20fc8193a000128e25840b1bc6f
	  6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc08440f0a4e1dca47c0411
	  9ed6a1be31b7707e5f9d001a659a051003e95e1b936f05c37ea793ad633a0001
	  28e35015044440040104141122447714220442
    58    ; byte_str(64)
      b747d98be9cef8a91af0292a479a3fa499527018b97ac1188ddefb0fa6fcb9b3
	  d1d4159240a8663c8803a2ef7cebdf7644fa3394cf1057d612e1b3977d9de92d
-------------------------------------------------------------------
Token claims:
a8    ; map(8)
  3a    ; int(-75008)
  58    ; byte_str(32)
    c3e3664dcc47711bf81734bc95f087d81dd841d73fc805fc9237c7b3dfa25c50
  3a    ; int(-75000)
  68    ; text_str(8)
    "SILABS_1"
  3a    ; int(-75009)
  49    ; byte_str(9)
    0614b457fffe0f77ce
  3a    ; int(-76000)
  58    ; byte_str(36)
    000000010000000000000000000000000000002000010209ffffffff0000002500000000
  3a    ; int(-76001)
  58    ; byte_str(24)
    00000000100444400401041411224477242204420a060005
  3a    ; int(-76002)
  58    ; byte_str(64)
    c4af4ac69aab9512db50f7a26ae5b4801183d85417e729a56da974f4e08a562c
	de6019dea9411332dc1a743372d170b436238a34597c410ea177024de20fc819
  3a    ; int(-76003)
  58    ; byte_str(64)
    b1bc6f6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc08440f0a4e1dca4
	7c04119ed6a1be31b7707e5f9d001a659a051003e95e1b936f05c37ea793ad63
  3a    ; int(-76004)
  50    ; byte_str(16)
    15044440040104141122447714220442

List of claims printed with human-friendly names:
  ARM PSA Nonce, Claim ID: -75008
  58    ; byte_str(32)
    c3e3664dcc47711bf81734bc95f087d81dd841d73fc805fc9237c7b3dfa25c50

  ARM PSA Profile ID, Claim ID: -75000
  68    ; text_str(8)
    "SILABS_1"

  ARM PSA / IETF EAT UEID, Claim ID: -75009
  49    ; byte_str(9)
    0614b457fffe0f77ce

  SE Status, Claim ID: -76000
  58    ; byte_str(36)
    000000010000000000000000000000000000002000010209ffffffff0000002500000000

  OTP Configuration, Claim ID: -76001
  58    ; byte_str(24)
    00000000100444400401041411224477242204420a060005

  OTP MCU Boot key, Claim ID: -76002
  58    ; byte_str(64)
    c4af4ac69aab9512db50f7a26ae5b4801183d85417e729a56da974f4e08a562c
	de6019dea9411332dc1a743372d170b436238a34597c410ea177024de20fc819

  OTP MCU Auth key, Claim ID: -76003
  58    ; byte_str(64)
    b1bc6f6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc08440f0a4e1dca4
	7c04119ed6a1be31b7707e5f9d001a659a051003e95e1b936f05c37ea793ad63

  Current applied tamper settings, Claim ID: -76004
  50    ; byte_str(16)
    15044440040104141122447714220442
-------------------------------------------------------------------

Exiting...
SL_STATUS_OK (cycles: 8 time: 0 us)
```

> **Note**: The reserved tamper source in ID 76004 returns a value of 0 or 5.

###### Simplicity Commander (heading level 7)

Run the `security attestation` command to retrieve and validate the security configuration token ([Entity Attestation Token (EAT)](05-r-entityattestationtoken)) from the HSE.

```sh
commander security attestation --serialno 440030580
```

```sh
Certificate chain successfully validated up to Silicon Labs device root certificate.

-75008 ARM PSA nonce                   : 05a88aeef627dd663058e3d758fe9a827942da0793da72af81c79a4f60fa9824
-75000 ARM PSA Profile ID              : SILABS_1
-75009 ARM PSA/IETF EAT UEID           : 0614b457fffe0f77ce
-76000 SE status                       : 000000010000000000000000000003a90000002000010209ffffffff0000002500000000
-76001 OTP configuration               : 00000000100444400401041411224477242204420a060005
-76002 MCU sign key                    : c4af4ac69aab9512db50f7a26ae5b4801183d85417e729a56da974f4e08a562c
                                         de6019dea9411332dc1a743372d170b436238a34597c410ea177024de20fc819
-76003 MCU command key                 : b1bc6f6fa56640ed522b2ee0f5b3cf7e5d48f60be8148f0dc08440f0a4e1dca4
                                         7c04119ed6a1be31b7707e5f9d001a659a051003e95e1b936f05c37ea793ad63
-76004 Current applied tamper settings : 15044440040104141122447714220442

Successfully validated signature of attestation token.
DONE
```

> **Note**: The reserved tamper source in ID 76004 returns a value of 0 or 5.

#### Secure Key Storage

##### Secure Key Storage

> **Note: This section replaces _AN1271: Secure Key Storage_. Further updates to this application note will be provided here**.

Secure Key Storage is a feature in  High devices that allows for the protection of cryptographic keys by key wrapping. User keys are encrypted by the device's root key for non-volatile storage for later usage. This prevents the need for a key to be stored in plaintext format on the device, preventing attackers from gaining access to the keys through traditional flash-extraction or application attacks, and allowing for a potentially unlimited number of keys to be securely stored in any available storage.

Series 2 devices can use TrustZone to implement Secure Key Storage, so this feature is now also available on  Mid devices.

This document describes the operation and usage of this feature, and provides comparisons with other key storage methods.

###### Key Points

- Keys are encrypted or 'wrapped' with a  root key
- root key is not stored on the device, instead it is generated on each reset
- Wrapped keys are confidential to the , and can be stored in non-volatile memory safely
- Wrapped keys can be cached into  for usage at a later time
- TrustZone Secure Key Storage

##### Series 2 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

<table>
    <thead>
        <tr>
            <th>Level (1)</th>
            <th>SE Support</th>
            <th>Part (2)</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Secure Vault High (SVH)</p>
            </td>
            <td>
                <p>HSE only (HSE-SVH)</p>
            </td>
            <td>
                <p>Refer to <a href="https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/">IoT Endpoint Security Fundamentals</a> for details on supporting devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Mid (SVM)</p>
            </td>
            <td>
                <p>HSE (HSE-SVM)</p>
            </td>
            <td>
                <p>"</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>"</p>
            </td>
            <td>
                <p>VSE (VSE-SVM)</p>
            </td>
            <td>
                <p>"</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Base (SVB)</p>
            </td>
            <td>
                <p>N/A</p>
            </td>
            <td>
                <p>"</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).
2. [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/).

Secure Vault Mid consists of two core security functions:

- Secure Boot: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- Secure Debug access control: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- Secure Key Storage: Protects cryptographic keys by "wrapping" or encrypting the keys using a root key known only to the HSE-SVH.
- Anti-Tamper protection: A configurable module to protect the device against tamper attacks.
- Device authentication: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Key Storage (this application note)</p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

<table>
    <thead>
        <tr>
            <th>Key Name</th>
            <th>Customer Programmed</th>
            <th>Purpose</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Public Sign key (Sign Key Public)</p>
            </td>
            <td>
                <p>Yes</p>
            </td>
            <td>
                <p>Secure Boot binary authentication and/or OTA upgrade payload authentication</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Public Command key (Command Key Public)</p>
            </td>
            <td>
                <p>Yes</p>
            </td>
            <td>
                <p>Secure Debug Unlock or Disable Tamper command authentication</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>OTA Decryption key (GBL Decryption key) aka AES-128 Key</p>
            </td>
            <td>
                <p>Yes</p>
            </td>
            <td>
                <p>Decrypting GBL payloads used for firmware upgrades</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Attestation key aka Private Device Key</p>
            </td>
            <td>
                <p>No</p>
            </td>
            <td>
                <p>Device authentication for secure identity</p>
            </td>
        </tr>
    </tbody>
</table>

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 and Series 3 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 and Series 3 devices and modules.

##### Introduction

The HSE isolates cryptographic functions and data from the host Cortex-M33 core. It is used to accelerate cryptographic operations as well as to provide a method to securely store keys. This application note will cover the Secure Key Storage feature of the HSE-SVH devices.

The HSE contains one-time programmable memory (OTP) key storage slots for three specific keys:

1. The Public Sign Key, used for Secure Boot and Secure Upgrades
2. The Public Command Key, used for Secure Debug unlock and tamper disable
3. The Symmetric OTA Decryption Key, used for Over-The-Air updates

These keys are one-time programmable, and, after programming, are persistent for the lifetime of the device.

HSE-SVH devices also contain four volatile storage slots for any other user keys. These slots are not persistent through a reset. In the case where a key needs persistent storage, the key must be stored outside of the HSE in non-volatile storage. After a device reset, the key can be loaded into the HSE volatile key storage for usage by index, or used in-place (passed to the HSE on every requested operation). Without any secure key storage mechanism, the user key stored in non-volatile storage is opened to storage-extraction attacks (such as gaining access to and downloading device flash), as well as application-level attacks (i.e., taking control of the user application or privileges in a manner that allows access to the keys).

With Secure Key Storage, a user can only access a key from the HSE in a 'wrapped' format. In this format, the key is encrypted by a device-unique root key, only available to the HSE. This allows a user to store a key confidentially in non-volatile storage to provide key persistence. Using Secure Key Storage, the plaintext key is never stored in non-volatile memory, preventing storage-extraction attacks from obtaining the key. After a device reset, the wrapped key can be loaded into the HSE for usage without ever exposing the plaintext key to the application, which also prevents application-level attacks from exposing the key.

SVM devices can only support Secure Key Storage through the use of [TrustZone](04-r-storagecomparisons-trustzone). GSDK v4.2.2 is the first version to support TrustZone software development on Series 2 devices.

Silicon Labs provides [Custom Part Manufacturing Service (CPMS)](https://www.silabs.com/developers/custom-part-manufacturing-service) to inject custom secret keys on the chips during manufacturing. For more information about CPMS, see the [Custom Part Manufacturing Service User's Guide](https://docs.silabs.com/iot-security/latest/iot-security-cpms/).

##### HSE Secure Key Storage

The following sections demonstrate three methods for key storage: ARM® TrustZone®, plaintext, and Secure Key Storage.

> **Note**: In the following examples, AES key usage is demonstrated. However, any other key types supported by the device can also be used for key storage.

###### Key Generation and Usage

In HSE-SVH devices, cryptographic functions are performed by the HSE. In order to perform these functions, the HSE must have access to any user keys needed. Keys can be generated and used by the HSE in multiple ways:

1. External storage, in-place usage:  
   1. A user generates a plaintext key and stores it in device memory.  
   2. The user provides a key descriptor to the HSE that points to this key for a specific cryptographic operation.  
   3. The HSE performs the cryptographic operation using this key, but does not store it in any HSE volatile storage slot.
2. External storage with HSE import:  
   1. A user generates a plaintext key and stores it in device memory.  
   2. The user provides a key descriptor to the HSE that points to this key, as well as a slot number to store the key.  
   3. The HSE imports this key into a volatile key storage slot or can optionally save it in wrapped form in device memory.  
   4. The user requests that the HSE performs a cryptographic function by providing the index of the storage slot or a pointer to the wrapped key in device memory.
3. Internal HSE key generation:  
   1. The user commands the HSE to generate a new key within one of the HSE's volatile key slots or can optionally save it in wrapped form in device memory.  
   2. The user requests that the HSE performs a cryptographic function by providing the index of the storage slot or a pointer to the wrapped key in device memory.

**Notes**:

- In each case, to provide persistent storage for the key, the key must be stored in non-volatile memory.
- [Plain Key Storage](#plaintext-key-storage) and [Secure Key Storage](#secure-key-storage) provide details on key generation and usage with HSE-SVH device.

###### Plaintext Key Storage

###### Plaintext Key Import (heading level 7)

The simplest manner to store a key is to save it in plaintext form. The steps to store and use a key stored in plaintext form are as follows:

1. A user key is generated and imported into device memory. For persistent storage, this must be non-volatile storage, such as device flash.
2. After a device reset, the HSE volatile key storage will be empty. The plaintext key is imported ([method 2](#key-generation-and-usage)) into a slot for usage. Alternatively, the key could be used in place ([method 1](#key-generation-and-usage)) from non-volatile storage on a per-operation basis.  
   ![Plaintext Key Import](/efr32-secure-key-storage/0.2/images/sld791-plaintext-key-import.png)

###### Plaintext Key Usage (heading level 7)

In order to use the key for a cryptographic operation, the following procedure is used.

1. The user passes data to be processed (in this specific example, AES encrypted data) to the HSE.
2. The user requests that a cryptographic operation be performed on this data using one of the keys stored in the HSE volatile key storage slots ([method 2](#key-generation-and-usage)). Alternatively, the key can be passed to the HSE directly for a singular cryptographic operation ([method 1](#key-generation-and-usage)).
3. The HSE performs the cryptographic operation.
4. The output of the cryptographic operation is passed back to the user for processing.  
   ![Plaintext Key Usage](/efr32-secure-key-storage/0.2/images/sld791-plaintext-key-usage.png)

This method exposes the keys to two major vulnerabilities:

1. Access to device storage gives access to the keys. In this case, an attack that gains access to the flash contents will expose the user key.
2. Since the application has access to the keys, compromising the application or device privileges can compromise the keys. Such an attack might not directly access device memory, but take control of the application in a way that causes the application to expose the key to an attacker.

###### Secure Key Storage

With Secure Key Storage, the user key, using the HSE, can be accessed in an encrypted, or 'wrapped' form. Only the HSE has access to the HSE root key used to decrypt, or 'unwrap', the wrapped key. This HSE root key is not stored on the device during power-down, but rather reconstructed after each reset. Key wrapping allows a user to securely store a key in non-volatile memory, limiting the number of keys that can be stored only by the amount of storage the user has available.

> **Note**: The reconstructed root key after each reset is IDENTICAL and UNIQUE on each HSE-SVH device.

###### Wrap an External Key (heading level 7)

To wrap an externally-generated key:

1. After power-on, the device's unique root key is reconstructed with output from the Physically Unclonable Function (PUF).
2. A user key is generated and imported into device memory. In this example, the key is imported into RAM for easy deletion, and the added security that, if device power is removed, the key will be lost.
3. The user key is passed to the HSE, where it is encrypted with the HSE's root key.
4. The wrapped key is passed back to the user application for storage in non-volatile memory (in this case, device flash).
5. The plaintext key can now be deleted from the device. From this point forward, only the HSE will have access to the plaintext key.  
   ![External Key Import, Wrapping, and Storage](/efr32-secure-key-storage/0.2/images/sld791-external-key-import-wrapping-and-storage.png)

###### Generate an Internal Wrapped Key (heading level 7)

Instead of importing an external key, the HSE can generate a new key directly into one of its volatile key storage slots. This key can then be exported in wrapped form for secure persistent storage.

1. The user requests that the HSE generates a new key into one of its storage slots using the True Random Number Generator (TRNG).
2. The key is encrypted with the HSE's root key.
3. The wrapped key is passed back to the user application for non-volatile storage (flash, in this case).  
   ![Internally Generated Key Wrapping and Storage](/efr32-secure-key-storage/0.2/images/sld791-internally-generated-key-wrapping-and-storage.png)

###### Wrapped Key Import (heading level 7)

In order to import a wrapped key into the HSE for usage:

1. The wrapped key is passed to the HSE.
2. The wrapped key is decrypted ("unwrapped") with the HSE's root key.
3. The plaintext key is stored in a volatile key storage slot.  
   ![Wrapped Key Import](/efr32-secure-key-storage/0.2/images/sld791-wrapped-key-import.png)

###### Wrapped Key Usage (heading level 7)

In order to use the key for a cryptographic operation, the same steps are followed as when using a plaintext key that has been imported into the HSE:

1. The user passes data to be processed (in this specific example, AES encrypted data) to the HSE.
2. The user requests that a cryptographic operation be performed on this data using one of the keys stored in the HSE volatile key storage slots. Alternatively, the wrapped key can be passed to the HSE directly for a singular cryptographic operation. In this case, the key will be unwrapped before being used, but will not be stored for future operations.
3. The HSE performs the cryptographic operation.
4. The output of the cryptographic operation is passed back to the user for processing.  
   ![Wrapped Key Usage](/efr32-secure-key-storage/0.2/images/sld791-wrapped-key-usage.png)

###### Secure Key Storage Advantages

Secure Key Storage confers the following benefits over other key storage methods:

1. Access to device memory does not expose user keys.
2. Compromising the user application does not expose user keys, since the user application itself does not have access to the plaintext keys.
3. The number of user keys that can be securely stored is only limited by the amount of storage available to the user, including external storage.

###### Operation Details

###### Root Key Generation (heading level 7)

Secure Key Storage depends on the HSE to encrypt / decrypt (wrap / unwrap) user keys with its own symmetric root key. The symmetric key used for this wrapping and unwrapping must be highly secure as it can expose all other key material in the system. The HSE key Management system uses a Physically Unclonable Function (PUF) to generate a persistent device-unique seed on power up to dynamically reconstruct this critical root key. The key is only visible to the AES encryption engine, and it is not retained when the device loses power.

###### Access a Wrapped Key (heading level 7)

By default, a key in an HSE storage slot can be exported to the application as a plaintext key. To prevent this, the user can use the key descriptor to set a user key to [non-exportable](05-r-securekeystorageimplementation#secure-key-storage-implementations). This option prevents any request to export the wrapped key in plaintext from HSE, so the user application can only access the key encrypted by the HSE's root key. The HSE also tags the key with information to identify the wrapped key. Since only the HSE can access the root key to unwrap the user key, the plaintext key is non-accessible to the user application.

> **Note**: Wrapped keys are slightly larger than the equivalent plaintext key, as some additional metadata is required to identify the wrapped key to the HSE.

###### Wrapped Key Storage and Usage (heading level 7)

Once a key has been wrapped, it can be safely stored anywhere - device flash, RAM, external storage, etc. The number of keys that can be securely stored is only limited by the available storage space. A wrapped key can later be imported into a HSE volatile storage slot for usage, or used in-place. Once the key is wrapped and stored, the plaintext key available to the application can be deleted. From here, only the HSE will have the ability to unwrap and use the key.

With access to the wrapped key, the HSE can use this key in one of two ways:

1. A user can request that a cryptographic operation be performed using the key stored in memory. In this case, the HSE will import the key, unwrap it, and then perform the cryptographic operation. The key will not be stored within the HSE.
2. A user can import the wrapped key into a HSE volatile storage slot. In this case, the key is unwrapped by the HSE and stored in plaintext in a volatile slot. The user can then later request that a cryptographic function be performed by the HSE by referencing the volatile slot index. This provides a performance increase over using wrapped keys in place, as the HSE does not need to import and unwrap the key on each requested operation.

###### Password Protection (heading level 7)

When defining a key descriptor for a new key, or when importing an existing key into HSE, the user can choose to require a password to allow use of the key. The password field in the key descriptor structure is eight bytes in length. If unspecified, the key will use the default password of all zeros.

After importing a key with a password, failing to provide the correct password when performing a cryptographic operation will result in HSE returning an invalid credentials error, and no operation will be performed.

##### TrustZone Secure Key Storage

In Series 2 devices, key management can be handled by a feature called TrustZone. TrustZone divides the device memory map into a Secure Processing Environment (SPE) and a Non-secure Processing Environment (NSPE). User code is executed from the NSPE, which cannot access any part of the SPE. The SPE is used to store cryptographic keys securely and to control other Secure operations.

The following sections describe using TrustZone on Series 2 devices for Secure Key Storage. Refer to [Series 2 TrustZone](https://docs.silabs.com/mcu-bootloader/latest/series2-trustzone/) for details about TrustZone implementation on Series 2 devices.

###### TrustZone Root Key Generation (HSE and VSE)

![Wrapped TRK](/efr32-secure-key-storage/0.2/images/sld791-wrapped-trk.png)

1. The TrustZone Root Key (TRK) is generated by the True Random Number Generator (TRNG) in Series 2 devices.
2. The PUF-derived key (HSE and xG27 VSE devices) or padded unique device serial number (xG22 VSE devices) is used to wrap (AES-GCM) the TRK.
3. The wrapped TRK is stored in the SE Non-volatile memory (NVM), and the TRK in RAM is deleted.  
   - The wrapped TRK already existed if the shipped Series 2 device with SE firmware version supports this key.  
   - The wrapped TRK will be generated when upgrading from a SE firmware version that did not support this key to the one that does.  
   - The wrapped TRK will be renewed after performing a Device Erase.

> **Note**: The Physically Unclonable Function (PUF) is not retained when the device loses power, so the TRK wrapped by the PUF-derived key is not vulnerable to a storage-extraction attack.

###### TrustZone Root Key Usage (HSE)

![HSE Unwrapped TRK](/efr32-secure-key-storage/0.2/images/sld791-hse-unwrapped-trk.png)

1. The Secure application in the host uses a non-exportable built-in key to access the wrapped TRK in HSE NVM for cryptographic operations.
2. The PUF-derived key is used to decrypt (AES-GCM) the wrapped TRK in HSE NVM.
3. The unwrapped TRK in the HSE is the master key of a Key Derivation Function (KDF).
4. The encryption key in SPE for Secure Key Storage is derived from the KDF CMAC.

**Notes**:

- All cryptographic operations are performed by the HSE (security co-processor).
- Only the HSE can access the unwrapped TRK for KDF, so this key will not expose the Secure application in the host.

###### TrustZone Root Key Usage (VSE)

![VSE Unwrapped TRK](/efr32-secure-key-storage/0.2/images/sld791-vse-unwrapped-trk.png)

1. The wrapped TRK in VSE NVM is accessed by the VSE Root mode firmware.
2. The PUF-derived key (xG27) or padded unique device serial number (xG22) is used to decrypt (AES-GCM) the wrapped TRK in VSE NVM.
3. Unwrapped TRK is transferred to the shared RAM when switching from VSE Root mode to User mode. The VSE user mode Secure application stores this key to the Secure RAM in SPE and deletes this key in the shared RAM.
4. The unwrapped TRK in the Secure RAM is the master key of a Key Derivation Function (KDF).
5. The encryption key in SPE for Secure Key Storage is derived from the KDF CMAC.

> **Note**: On VSE devices, all cryptographic operations are performed by the Cryptographic Accelerator (CRYPTOACC) peripheral.

For more information about the HSE and VSE, refer to the section _Secure Engine Subsystem_ in [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/03-r-secureelement).

###### TrustZone Secure Key Storage (HSE and VSE)

The TRK allows a user to securely store a key in the Non-secure flash, limiting the number of keys that can be saved only by the amount of Non-secure storage. The following figure describes using the TRK to encrypt a plaintext key and store it in Non-secure NVM.![TZ SKS](/efr32-secure-key-storage/0.2/images/sld791-tz-sks.png)

1. After power-on, the device's TRK (wrapped in HSE NVM and unwrapped in VSE Secure RAM) is available for the SPE.
2. A user key is generated and imported into the device's Non-secure memory. In this example, the key is imported into Non-secure RAM for easy deletion, and the key is lost if device power is removed.
3. Call the PSA Crypto API (`psa_import_key()` or `psa_generate_key()`) through the Secure Gateway (SG) in Non-secure Callable (NSC) memory to generate a key for crypto operations.
4. The plaintext key is passed in the PSA Crypto API to the SPE, where it is encrypted (AES-GCM) with the encryption key derived (KDF CMAC) from the TRK.
5. The encrypted key is stored to the NVM region in the NSPE through the PSA Internal Trusted Storage (ITS) and [NVM3](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3) drivers.
6. The plaintext key can now be deleted from the Non-secure RAM.
7. Only the PSA Crypto API in the SPE can retrieve the encrypted key from NVM in the NSPE and decrypt it for crypto operations in the SPE.

> **Note**: Ignore steps 2 and 6 if the plaintext key is randomly generated by the PSA Crypto.

##### Secure Key Storage Implementations

Users can use Secure Engine Manager (SE Manager) or PSA Crypto in the following figure to access the secure key storage on HSE-SVH devices. SE Manager APIs for secure key storage and crypto are usually not considered external APIs. PSA Crypto API abstracts the entropy sources, crypto primitives, and even advanced security features like secure key storage from the calling functions.

Silicon Labs recommends using PSA Crypto API for secure key storage and cryptography whenever possible. It makes the solution more portable and hardware agnostic. In some cases, however, setting up tamper and initializing the secure boot can only be implemented by the SE Manager APIs.

![Secure Engine Manager and PSA Crypto](/efr32-secure-key-storage/0.2/images/sld791-secure-engine-manager-and-psa-crypto.png)

<table>
    <thead>
        <tr>
            <th>Component</th>
            <th>Functionality</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>EMLIB (em_se.c)</p>
            </td>
            <td>
                <p>Abstracts the mailbox interface: how to construct, send and receive low-level HSE mailbox commands.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SE Manager</p>
            </td>
            <td>
                <p>On top of EMLIB, it abstracts the HSE command set: translates function calls into mailbox messages. The SE Manager also provides thread synchronization.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Accelerator Drivers</p>
            </td>
            <td>
                <p>A translation layer to map the PSA Crypto HSE interface and crypto acceleration calls to SE Manager calls.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Crypto API</p>
            </td>
            <td>
                <p>Platform independent cryptographic hardware acceleration support by implementing standardized APIs.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA ITS Driver</p>
            </td>
            <td>
                <p>The key management functionality in PSA Crypto needs access to non-volatile memory for persistent storage of plaintext or wrapped keys. NVM3 gets wrapped by this translation layer, mapping the PSA ITS (Internal Trusted Storage) interface to NVM3 calls.</p>
            </td>
        </tr>
    </tbody>
</table>

For the SE's mailbox interface, see section _Secure Engine Subsystem_ in [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/03-r-secureelement).

For more information about NVM3, see [https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3).

For more information about PSA Crypto, see [Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS](https://docs.silabs.com/iot-security/latest/mbedtls-psa-crypto-porting-guide/).

###### SE Manager API

The following table lists the SE Manager APIs related to Secure Key Storage operations. The SE Manager API document can be found at [https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager).

<table>
    <thead>
        <tr>
            <th>SE Manager API</th>
            <th>Usage</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sl_se_generate_key</p>
            </td>
            <td>
                <p>Generate a new key and store it either in a volatile HSE storage slot or as a wrapped key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_import_key</p>
            </td>
            <td>
                <p>Import a plaintext key and store it either in a volatile HSE storage slot or as a wrapped key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_export_key</p>
            </td>
            <td>
                <p>Export a volatile or wrapped key back to plaintext if allowed. It will fail for a key that has been flagged as SL_SE_KEY_FLAG_NON_EXPORTABLE.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_transfer_key</p>
            </td>
            <td>
                <p>Transfer a volatile or wrapped key to another storage option (volatile HSE storage slot or a wrapped key) if allowed.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_delete_key</p>
            </td>
            <td>
                <p>Delete a key from a volatile HSE storage slot.</p>
            </td>
        </tr>
    </tbody>
</table>

###### PSA Crypto API

The following table lists the PSA Crypto APIs related to Secure Key Storage operations. The PSA Crypto API document can be found at [https://docs.silabs.com/mbed-tls/latest/](https://docs.silabs.com/mbed-tls/latest/).

For more information about PSA Crypto APIs on Secure Key Storage, see [Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS](https://docs.silabs.com/iot-security/latest/mbedtls-psa-crypto-porting-guide/).

<table>
    <thead>
        <tr>
            <th>PSA Crypto API</th>
            <th>Usage</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>psa_generate_key</p>
            </td>
            <td>
                <p>Generate a new plaintext or wrapped key and store it either in volatile or non-volatile memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>psa_import_key</p>
            </td>
            <td>
                <p>Import a plaintext key and save it in plaintext or wrapped form. It can store either in volatile or non-volatile memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>psa_export_key</p>
            </td>
            <td>
                <p>Export a key back to plaintext if allowed. The policy on the key must have the usage flag<code>PSA_KEY_USAGE_EXPORT</code>set.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>psa_copy_key</p>
            </td>
            <td>
                <p>Copy key material from one location to another, which may have a different lifetime (e.g., volatile to non-volatile).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>psa_destroy_key</p>
            </td>
            <td>
                <p>Destroy a key from both volatile memory and, if applicable, non-volatile storage.</p>
            </td>
        </tr>
    </tbody>
</table>

###### SE Manager API Versus PSA Crypto API

The following table compares the SE Manager APIs with PSA Crypto APIs on Secure Key Storage.

<table>
    <thead>
        <tr>
            <th>Item</th>
            <th>SE Manager API</th>
            <th>PSA Crypto API</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Availability</p>
            </td>
            <td>
                <p>Only on HSE devices</p>
            </td>
            <td>
                <p>Platform independent</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>API</p>
            </td>
            <td>
                <p>Silicon Labs proprietary</p>
            </td>
            <td>
                <p>Standardized by ARM®</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Key Storage</p>
            </td>
            <td>
                <p>Volatile (RAM) memory only</p>
            </td>
            <td>
                <p>Volatile (RAM) or non-volatile (flash) memory</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Wrapped Key Cache</p>
            </td>
            <td>
                <p>Can use a volatile HSE storage slot</p>
            </td>
            <td>
                <p>Not yet implemented</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Password Protection</p>
            </td>
            <td>
                <p>Can define in a key descriptor</p>
            </td>
            <td>
                <p>Not yet defined in PSA Crypto</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Custom ECC Curve</p>
            </td>
            <td>
                <p>Can define in a key descriptor</p>
            </td>
            <td>
                <p>Not yet defined in PSA Crypto</p>
            </td>
        </tr>
    </tbody>
</table>

###### PSA Crypto Key Types with TrustZone Secure Key Storage

The following tables describes the storage differences between key storage with and without TrustZone on SVM and SVH devices.

**Table: TrustZone Secure Key Storage (SKS) on SVM Devices**

<table>
    <thead>
        <tr>
            <th>Key Type</th>
            <th>Storage without TrustZone SKS</th>
            <th>Storage with TrustZone SKS</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Volatile Plaintext</p>
            </td>
            <td>
                <p>RAM</p>
            </td>
            <td>
                <p>Secure RAM (2)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Plaintext</p>
            </td>
            <td>
                <p>NVM</p>
            </td>
            <td>
                <p>Encrypted in NS NVM (2)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Volatile Wrapped</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Wrapped</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
        </tr>
    </tbody>
</table>

**Table: TrustZone Secure Key Storage (SKS) on SVH Devices**

<table>
    <thead>
        <tr>
            <th>Key Type</th>
            <th>Storage without TrustZone SKS</th>
            <th>Storage with TrustZone SKS</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Volatile Plaintext</p>
            </td>
            <td>
                <p>Plaintext key in RAM</p>
            </td>
            <td>
                <p>Plaintext key in Secure RAM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Plaintext</p>
            </td>
            <td>
                <p>Plaintext key in NVM</p>
            </td>
            <td>
                <p>Encrypted plaintext key in NS NVM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Volatile Wrapped</p>
            </td>
            <td>
                <p>Wrapped key in RAM (1)</p>
            </td>
            <td>
                <p>Wrapped key in Secure RAM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Wrapped</p>
            </td>
            <td>
                <p>Wrapped key in NVM (1)</p>
            </td>
            <td>
                <p>Encrypted wrapped key in NS NVM</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- The NVM or NS NVM is at the last part of the main flash.
- It is possible to replace the wrapped key solution on the SVH device (1) with TrustZone Secure Key Storage on the SVM device (2), but this is a less secure approach.

##### Examples

Simplicity Studio 5 includes the [SE Manager and PSA Crypto platform examples](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/start-a-project#examples) for Secure Key Storage. Refer to the corresponding `readme` file for details about each SE Manager and PSA Crypto platform example. This file also includes the procedures to create the project and run the example.

**Table: Platform Examples for Secure Key Storage**

<table>
    <thead>
        <tr>
            <th>Category</th>
            <th>SE Manager Platform Example</th>
            <th>PSA Crypto Platform Example</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td rowspan="2">
                <p>Key Handling</p>
            </td>
            <td>
                <p>SE Manager Symmetric Key Handling</p>
            </td>
            <td>
                <p>PSA Crypto Symmetric Key</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SE Manager Asymmetric Key Handling</p>
            </td>
            <td>
                <p>PSA Crypto Asymmetric Key</p>
            </td>
        </tr>
        <tr>
            <td rowspan="4">
                <p>Symmetric Key Usage</p>
            </td>
            <td rowspan="4">
                <p>SE Manager Block Cipher</p>
            </td>
            <td>
                <p>PSA Crypto AEAD</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Crypto Cipher</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Crypto KDF</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Crypto MAC</p>
            </td>
        </tr>
        <tr>
            <td rowspan="2">
                <p>Asymmetric Key Usage</p>
            </td>
            <td>
                <p>SE Manager Digital Signature (ECDSA and EdDSA)</p>
            </td>
            <td>
                <p>PSA Crypto DSA</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SE Manager Key Agreement (ECDH)</p>
            </td>
            <td>
                <p>PSA Crypto ECDH</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>X.509 Certificate</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>PSA Crypto X.509</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>TrustZone Secure Key Storage</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>tz_psa_crypto_ecdh_ws</p>
            </td>
        </tr>
    </tbody>
</table>

#### Programming Series 2 Devices Using DCI and SWD

##### Programming Series 2 Devices using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)

> **Note: This section replaces _AN1303: Programming Series 2 Devices using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)_. Further updates to this Quick-Start Guide will be provided here**.

This application note describes how to provision and configure Series 2 devices through the dedicated Debug Challenge Interface (DCI). The process to use the Serial Wire Debug (SWD) interface for programming the internal flash memory of Series 2 devices is also included.

For details on how to use the SWD interface to program devices, see [AN0062: Programming Internal Flash over the Serial Wire Debug Interface](https://www.silabs.com/documents/public/application-notes/an0062.pdf).

###### Key Points

- DCI overview
- SWD interface overview
- DCI programming examples to provision and configure Series 2 devices
- SWD programming examples to program Series 2 devices
- How to add a new Series 2 device to the programmer

##### Series 2 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level (1)**|**SE Support**|**Part (2)**|
|---|---|---|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|Refer to _IoT Endpoint Security Fundamentals_ for details on supporting devices.|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|"|
|"|VSE (VSE-SVM)|"|
|Secure Vault Base (SVB)|N/A|"|

Notes:

1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).
2. [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/).

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.
- Advanced cryptographic acceleration (i.e., ChaCha20/Poly1305)

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th><strong>Document</strong></th>
            <th><strong>Summary</strong></th>
            <th><strong>Applicability</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/mbedtls-psa-crypto-porting-guide/">Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS</a></p>
            </td>
            <td>
                <p>How to port firmware from the Mbed TLS cryptographic library to PSA Crypto</p>
            </td>
            <td>
                <p>Secure Vault Mid and High</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-trustzone/">Series 2 TrustZone</a></p>
            </td>
            <td>
                <p>How to TrustZone to separate trusted and non-trusted firmware.</p>
            </td>
            <td>
                <p>Secure Vault Mid and High</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 devices and modules.

##### Introduction

The latest SE firmware image (`.seu` and `.hex`) and release notes can be found in the Windows folder below. For GSDK v3.2 and lower:

`C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION>\util\se_release\public`

For GSDK v4.0 and higher:

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public`

Silicon Labs provides [Custom Part Manufacturing Service (CPMS)](https://www.silabs.com/developers/custom-part-manufacturing-service) to customize the users' security features and settings.

The Debug Challenge Interface (DCI) is used to configure the security features of the Series 2 devices, whereas the Serial Wire Debug (SWD) interface is used to program the flash memory of Series 2 devices. A general overview of the DCI and SWD programming steps is described in the following sections.

##### Debug Challenge Interface (DCI)

Interaction with the SE is performed over a command interface that is available through a dedicated Debug Challenge Interface (DCI). The DCI is intended to be used for various [SE commands](05-se-command-list#se-command-list). The DCI is open while the SE is running.

###### DCI Connection

The DCI is made available through a connection on the Serial Wire Debug (SWD) port. The steps involved in connecting the DCI through the SWD port are as follows.

1. Send the JTAG-to-SWD switching sequence.
2. Read the IDCODE register (SWD DP register 0) to retrieve an identification value. On the Series 2 devices with a Cortex-M33 core, this value is `0x6BA02477`.
3. Use the ABORT register (SWD DP register 0 = `0x0000001E`) to clear the error and sticky flag conditions.
4. Use the STAT register (SWD DP register 1 = `0x50000000`) to generate a system and debug domain power-up request.
5. Use the SELECT register (SWD DP register 2 = `0x01000000`) to set the SWD interface in the chip to communicate with the DCI.
6. Use the CSW register (SWD AP register 0 = `0x22000002`) to set the transfer size to 32-bit.

See [AN0062: Programming Internal Flash over the Serial Wire Debug Interface](https://www.silabs.com/documents/public/application-notes/an0062.pdf) for more information about the SWD port registers.

![CI Connection Flowchart](/efr32-dci-swd-programming/0.1/images/sld815-dci-connection-flowchart.png)

###### DCI Registers

The following table lists three registers to interact with the DCI through the SWD interface.

**DCI Register**

|**Register**|**Description**|**Fields**|**Address**|**Remarks**|
|---|---|---|---|---|
|DCI_WDATA|Write data to the DCI|WDATA [31:0]|0x1000|Command|
|DCI_RDATA|Read data from the DCI|RDATA [31:0]|0x1004|Response|
|DCI_STATUS|Status of DCI accesses|Bit 0 = WPENDING|0x1008|Write Request to the DCI is pending. Additional writes to DCI_WDATA are discarded when this bit is asserted.|
|"|"|Bit 8 = RDATAVALID|"|Response from the DCI is valid when this bit is asserted. Cleared on a read of DCI_RDATA.|

###### DCI Calls

###### Command (heading level 7)

All DCI calls start by writing a 32-bit word containing the length of the DCI data followed by the 32-bit Command ID into the DCI. The length includes the length word itself, so the minimum value is 8 (4 bytes of length and 4 byes of Command ID). Then a variable length command payload (if applicable) is transferred into the DCI.

**DCI Command**

|**Command Word**|**Description**|
|---|---|
|Word 0|Length of packet in bytes (including word 0)|
|Word 1|Command ID|
|Words 2 – N|Command payload if applicable|

###### Response (heading level 7)

On completion, a 32-bit word consisting of the response length [15:0] in bytes and response code [31:16] is read from the DCI followed by the response payload, if present.

**DCI Response**

|**Response Word**|**Description**|
|---|---|
|Word 0|Total response length (including word 0) and response code: [15:0] – Total length in bytes; [31:16] – Response code|
|Words 1 – N|Response payload if applicable|

All executed commands return a response code that classifies the result of the operation. The basic meaning of these response codes is given in the following table.

**DCI Response Codes**

|**Response Code**|**Status**|**Description**|
|---|---|---|
|0|SE_RESPONSE_OK|Command executed successfully or signature was successfully validated.|
|1|SE_RESPONSE_INVALID_COMMAND|Command was not recognized as a valid command, or is not allowed in the current context.|
|2|SE_RESPONSE_AUTHORIZATION_ERROR|User did not provide the required credentials to be allowed to execute the command.|
|3|SE_RESPONSE_INVALID_SIGNATURE|Signature validation command failed to verify the given signature as being correct.|
|4|SE_RESPONSE_BUS_ERROR|A command started in non-secure mode is trying to access secure memory.|
|5|SE_RESPONSE_INTERNAL_ERROR|Internal SE error.|
|6|SE_RESPONSE_CRYPTO_ERROR|Error in crypto operation.|
|7|SE_RESPONSE_INVALID_PARAMETER|One of the passed parameters is deemed invalid (for example, out of bounds), or the number of parameters is incorrect.|
|8|SE_RESPONSE_INTEGRITY_ERROR|Operation cannot be completed due to the SE having an invalid internal state.|
|9|SE_RESPONSE_SECUREBOOT_ERROR|The host application failed secure boot check.|
|10|SE_RESPONSE_SELFTEST_ERROR|Failure during self-test.|
|11|SE_RESPONSE_NOT_INITIALIZED|Feature or item is not present or not initialized.|

###### DCI Operation

###### DCI Write (heading level 7)

The user can write the DCI_WDATA register to pass command to the SE. The steps involved in writing a command to DCI are as follows.

1. Connect to DCI according to [DCI Connection Flowchart](#dci-connection).
2. For each word in the command, follow these steps in sequence:  
   1. Set the DCI to read from [DCI_STATUS](#dci-calls) by setting SWD AP register 1 to 0x1008.  
   2. Read DCI_STATUS by reading from SWD AP register 3.  
   3. If [WPENDING](#dci-calls) is high, go back to step (a). If WPENDING is low, continue. If [RDATAVALID](#dci-registers) is high, then the SE has started issuing a reply and the current command needs to be aborted.  
   4. Set the DCI to write to [DCI_WDATA](#dci-registers) by setting SWD AP register 1 to 0x1000.  
   5. Write the command word to SWD AP register 3.  
   ![DCI Write Flowchart](/efr32-dci-swd-programming/0.1/images/sld815-dci-write-flowchart.png)

###### DCI Read (heading level 7)

The user can read the DCI_RDATA register to retrieve responses from the SE to a previously written command. If a user has sent a command according to [DCI Write Flowchart on page 8](#dci-write), the steps to read the response from the DCI are as follows.

1. Set the DCI to read from [DCI_STATUS](#dci-registers) by setting SWD AP register 1 to 0x1008.
2. Read DCI_STATUS by reading from SWD AP register 3.
3. If [RDATAVALID](#dci-registers) is high, a response word is available to be read from DCI_RDATA. If RDATAVALID is low, go back to step (2) because the SE has not begun to reply.
4. Set the DCI to read from [DCI_RDATA](#dci-registers) by setting SWD AP register 1 to 0x1004.
5. Read the first response word from the command to SWD AP register 3.
6. Total length of the response (including the first word) is in the lower 16 bits of that word. If this is larger than 4, for each response word:  
   a. Set the DCI to read from DCI_STATUS by setting SWD AP register 1 to 0x1008.  
   b. Read DCI_STATUS by reading from SWD AP register 3.  
   c. If RDATAVALID is high, a response word is available to be read from DCI_RDATA. If RDATAVALID is low, go back to step (a) because the process is polling faster than the SE can send data.  
   d. Set the DCI to read from DCI_RDATA by setting SWD AP register 1 to 0x1004.  
   e. Read the sequential response word to SWD AP register 3.

![DCI Read Flowchart](/efr32-dci-swd-programming/0.1/images/sld815-dci-read-flowchart.png)

##### Serial Wire Debug (SWD) Interface

The flash memory on Series 2 devices is divided into two blocks: the main block and the information block. Program code is normally written to the main block. The information block is available for special user data. Throughout this document, the flash or main flash is referred to as the main block and user data is referred to as the information block.

Program the Series 2 flash memory by writing directly to the device's Memory System Controller (MSC) registers over the Serial Wire Debug (SWD) interface. This method is simple and easy to upgrade to support new Series 2 devices.

The program must set the MSC bit in the CMU CLKEN1 register (if available) to enable the clock source for the Memory System Controller (MSC).

Series 2 devices with a Cortex-M33 core return the value `0x84770001` when reading the AP Identification Register (IDR) through SWD.

See [AN0062: Programming Internal Flash over the Serial Wire Debug Interface](https://www.silabs.com/documents/public/application-notes/an0062.pdf) for more information on how to access the SWD interface of the target device and how to use this interface to program devices.

###### Flash Erase

There are two ways to erase the flash of the target device through SWD interface:

###### Page Erase (heading level 7)

A page erase can be initiated from software using the ERASEPAGE bit in the MSC WRITECMD register. The page erase operations require that the address of main flash or user data is written into the MSC ADDRB register. To reduce the time needed for the flash erase process, the program should avoid erasing the target main flash page by page, especially for devices with larger flash memories.

###### Mass Erase (heading level 7)

A mass erase can be initiated from software using the ERASEMAIN0 bit in the MSC WRITECMD register. This erases the entire flash (excluding the user data).

![Flash-Erase-Flowchart](/efr32-dci-swd-programming/0.1/images/sld815-flash-erase-flowchart.png)

The flash base address of the Series 2 device is either `0x00000000` or `0x08000000.` The timing for page erase or mass erase on each Series 2 device might vary. Refer to the device-specific datasheets for details.

###### Flash Write

The write operation requires that the address be written into the MSC ADDRB register. After each 32-bit word is written, the internal address register is incremented automatically by 4. When a word is written to the MSC WDATA register, the WDATAREADY bit of the MSC STATUS register is cleared. When this status bit is set, software can write the next word.

The flash program time (32-bit word) of each Series 2 device might vary. Refer to the device-specific datasheets for details.

To reduce the time for the flash write process, the program can omit polling the WDATAREADY bit in the MSC STATUS register after writing each 32-bit word, because the register read process is time consuming. The alternative is to add a fixed microseconds delay between each write to make sure the maximum write time can be met.

![Flash-Write-Flowchart](/efr32-dci-swd-programming/0.1/images/sld815-flash-write-flowchart.png)

###### Flash Verify (heading level 7)

The program verifies the target flash contents with a buffer to make sure that no errors occurred during the programming process. The autoincrement of the Transfer Address Register (TAR) is for burst reads within the TAR wraparound boundary. The TAR must be initialized at every TAR wraparound boundary to set up the next flash read address.

![Flash Verify Flowchart](/efr32-dci-swd-programming/0.1/images/sld815-flash-verify-flowchart.png)

##### SE Command List

This application note does not include a complete list of commands for DCI. The following sections contain information about each command's operation and arguments for DCI production programming. The [command](03-debug-challenge-interface-dci#command) and [response](03-debug-challenge-interface-dci#response) payload may be device-specific (e.g., Initialize OTP and Get Status).

For more information about secure boot, see [Series 2 Secure Boot with RTSL](https://docs.silabs.com/iot-security/latest/series2-secure-boot-with-rtsl/). For more information about debug lock and secure debug, see [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

###### SE Image Check

This command can be used to check the SE image before starting the upgrade process, in order to be able to abort early if the image is invalid or inapplicable.

> **Note**: This command is only available on SE firmware version ≥ v1.2.2 (xG21 or xG22 devices).

**SE Image Check Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x4302|0x00|0x00|Address in internal flash where the SE upgrade image is stored - 4 bytes:|None|

###### SE Image Apply

This command can be used to perform an upgrade of the SE firmware where the existing firmware will be overwritten with the one stored in the internal flash if the upgrade image is valid and applicable. The system is restarted and no [response code](03-debug-challenge-interface-dci) is returned if the SE image is successfully upgraded.

> **Note**: This command is only available on SE firmware version ≥ v1.2.2 (xG21 or xG22 devices).

**SE Image Apply Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x4303|0x00|0x00|Address in internal flash where the SE upgrade image is stored - 4 bytes:|None|

###### Apply Lock

This command enables the debug lock for the part.

**Apply Lock Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x430C|0x00|0x00|None|None|

###### Enable Secure Debug

This command enables the secure debug functionality. This command must be used before the debug port is locked and will fail if executed after locking debug access.

**Enable Secure Debug Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x430D|0x00|0x00|None|None|

###### Disable Secure Debug

This command disables the secure debug functionality and is available even after the debug port has been locked.

**Disable Secure Debug Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x430E|0x00|0x00|None|None|

###### Erase Device

This command performs a device mass erase and resets the debug configuration to its initial unlocked state. It is only available if the [Disable Device Erase](#disable-device-erase) command has not been executed.

This command clears and verifies the main flash and RAM of the system, excluding the user data and one-time programmable (OTP) commissioning information in the SE.

**Erase Device Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x430F|0x00|0x00|None|None|

###### Disable Device Erase

This command disables the [Erase Device](#erase-device) command. This command does not lock the debug interface to the part, but it is a permanent action for the part. This is a one-time command.

**Disable Device Erase Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x4310|0x00|0x00|None|None|

###### Read Serial Number

This command is used to read the Silicon Labs-provisioned serial number of the device.

**Read Serial Number Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFE00|0x00|0x00|None|16 bytes serial number|

###### Get Status

This command is used to read out the status information from the SE.

**Get Status Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFE01|0x00|0x00|None|Varies by SE type, see following.|

**VSE-SVM - total 20 bytes:**

- Boot status - 4 bytes
- VSE firmware version - 4 bytes
- MCU firmware version - 4 bytes
- Debug lock status - 4 bytes
- Secure boot configuration - 4 bytes

**HSE-SVM or HSE-SVH - total 36 bytes**:

- 16 bytes for HSE-SVM: Reserved
- 16 bytes for HSE-SVH:  
  - Tamper status - 4 bytes  
  - Tamper time stamp - 4 bytes  
  - Tamper raw status - 4 bytes  
  - Time stamp - 4 bytes
- Boot status - 4 bytes
- HSE firmware version - 4 bytes
- MCU firmware version - 4 bytes
- Debug lock status - 4 bytes
- Secure boot configuration - 4 bytes

> **Note**:
> 
> - Tamper status is a set of 32 flags that indicate which tamper events have occurred.
> - Tamper time stamp is a HSE timer counter value for the last tamper event.
> - Tamper raw status is encoded the same as tamper status but is an immediate value of the tamper event sources.
> - The time stamp is a HSE timer counter value.
> - Boot status:
> - Bit [7:0] - 0x20 if boot is successful.
> - Bit [:] (for xG21 or xG22 devices only) - The [response code](03-debug-challenge-interface-dci) if SE firmware version ≥ v1.2.0
> - VSE or HSE firmware version:
> - Bit [7:0] - Patch version
> - Bit [15:8] - Minor version
> - Bit [23:16] - Major version
> - Bit [31:24] - Series 2 device family (0 for xG21, 1 for xG22, 2 for xG23, etc.)
> - MCU firmware version: Bit [31:0] - The MCU firmware version is not available if all set to 1 (0xFFFFFFFF)
> - Debug lock status:
> - Bit [0] - Debug lock (configuration status) is enabled if set.
> - Bit [1] - Device erase is enabled if set.
> - Bit [2] - Secure debug is enabled if set.
> - Bit [5] - Debug lock (hardware status) is enabled if set.
> - Secure boot configuration:
> - Bit [31:0] - SE OTP is not yet configured if all set to 1 (0xFFFFFFFF)
> - Bit [31:0] - SE OTP has been configured if Bit [31:1] are 0, secure boot is enabled if Bit [0] is set

###### Read User Configuration

This command is used to read non-reconfigurable user settings on the SE OTP for secure boot and tamper response.

> **Note**: This command is only available on SE firmware versions ≥ v1.2.2 (xG21 or xG22 devices).

**Read User Configuration Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFE04|0x00|0x00|None|Varies by SE type, see following.|

**VSE-SVM - total 4 bytes**:

- [MCU flags](#mcu-flags) - 4 bytes

**HSE-SVM - total 24 bytes**:

- [MCU flags](#mcu-flags) - 4 bytes
- Reserved - 20 bytes

**HSE-SVH - total 24 bytes**:

- [MCU flags](#mcu-flags) - 4 bytes
- [Tamper response levels]() (2 signals per byte) - 16 bytes
- [Filter reset period]() - 1 byte
- [Filter trigger threshold]() - 1 byte
- [Tamper flags]() - 1 byte
- [Tamper reset threshold]() - 1 byte

###### Initialize OTP

This command is used during factory initialization, to upload device-specific settings to the SE OTP. This is a one-time command.

**Initialize OTP Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFF00|0x00|0x01|Varies by SE type, see following.|None|

**VSE-SVM - total 12 bytes**:

1. Parity (equal to item 3) - 4 bytes
2. Length of the following content - 4 bytes
3. [MCU flags](#mcu-flags) - 4 bytes

**HSE-SVM - total 32 bytes**:

1. Parity (the XOR of 32-bit words from item 3 and 4) - 4 bytes
2. Length of the following content - 4 bytes
3. [MCU flags](#mcu-flags) - 4 bytes
4. Reserved - 20 bytes

**HSE-SVH - total 32 bytes**:

1. Parity (the XOR of 32-bit words from item 3 to 8) - 4 bytes
2. Length of the following content - 4 bytes
3. [MCU flags](#mcu-flags) - 4 bytes
4. [Tamper response levels]() (2 signals per byte) - 16 bytes
5. [Filter reset period]() - 1 byte
6. [Filter trigger threshold]() - 1 byte
7. [Tamper flags]() - 1 byte
8. [Tamper reset threshold]() - 1 byte

###### MCU Flags (heading level 7)

The parameters of the MCU flags are described in the following tables.

**Parameters of MCU Flags**

|**Fields**|**Description**|
|---|---|
|Bit [15:0]|Reserved|
|Bit [16]|SECURE_BOOT_ENABLE|
|Bit [17]|SECURE_BOOT_VERIFY_CERTIFICATE|
|Bit [18]|SECURE_BOOT_ANTI_ROLLBACK|
|Bit [19]|SECURE_BOOT_PAGE_LOCK_NARROW|
|Bit [20]|SECURE_BOOT_PAGE_LOCK_FULL|
|Bit [31:21]|Reserved|

**MCU Flags for Series 2 Devices**

|**Name**|**Description**|
|---|---|
|SECURE_BOOT_ENABLE|If set, verifies the image on the Cortex-M33 before releasing the Cortex-M33 from reset.|
|SECURE_BOOT_VERIFY_CERTIFICATE|If set, requires certificate-based signing of the host application.|
|SECURE_BOOT_ANTI_ROLLBACK|If set, prevents secure upgrading to a host image with a lower version than the image that is currently stored in flash.|
|SECURE_BOOT_PAGE_LOCK_NARROW|If set, locks flash pages that have been validated by the secure boot process to prevent re-flashing by means other than through the SE.|
|"|Write/erase locks pages from 0 through the page where the secure boot signature of the application is located, not including the last page if the signature is not on a page boundary.|
|SECURE_BOOT_PAGE_LOCK_FULL|If set, locks flash pages that have been validated by the secure boot process to prevent re-flashing by means other than through the SE.|
|"|Write/erase locks pages from 0 through the page where the secure boot signature of the application is located, including the last page if the signature is not on a page boundary.|

###### Anti-Tamper Configuration (heading level 7)

The 16 bytes of tamper response levels on HSE-SVH devices are described in the following tables.

**Tamper Source Response Level on HSE-SVH (xG21B) Devices**

![Tamper Source Response Level on HSE-SVH (xG21B) Devices](/efr32-dci-swd-programming/0.1/images/sld815-tamper-source-response-level-on-hse-svh-xg21b-devices.png)

**Tamper Source Response Level on Other HSE-SVH Devices**

![Tamper Source Response Level on Other HSE-SVH Devices](/efr32-dci-swd-programming/0.1/images/sld815-tamper-source-response-level-on-other-hse-svh-devices.png)

###### Initialize Public Key

This command is used to initialize the user public key(s) to the SE OTP. This is a one-time command.

**Initialize Public Key Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFF07|Key type, see following|0x01|See following|None|

**Key type:**

- 0x01 - Public Sign Key
- 0x02 - Public Command Key

**Command payload - total 68 bytes**:

1. Parity (the XOR of 32-bit words from item 2) - 4 bytes
2. Public key in option 1 - 64 bytes

###### Read Public Key

This command can be used to read out one of the public keys that are permanently stored in SE OTP.

**Read Public Key Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFF08|Key type, see following|0x01|None|64 bytes: public key in option 1|

**Key type:**

- 0x01 - Public Sign Key
- 0x02 - Public Command Key

###### Initialize AES Key

This command is used to initialize a 128-bit symmetric key to the SE OTP. This is a one-time command.

> **Note**: This command is only available on HSE devices.

**Initialize AES Key Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0xFF0B|Key type, see following|0x01|See following|None|

**Key type:**

- 0x05 - AES-128 key

**Command payload - total 20 bytes**:

1. Parity (the XOR of 32-bit words from item 2) - 4 bytes
2. Symmetric key in option 1 - 16 bytes

###### Set Debug Restrictions

This command is used to set the restrictions for the debug port.

**Set Debug Restrictions Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x4312|0x00|0x00|See following|None|

Command Payload – total 4 bytes. Debug restriction bit mask is defined in the table below.

**Debug Port Restriction Bits**

<table>
    <thead>
        <tr>
            <th><strong>Bit</strong></th>
            <th><strong>Name</strong></th>
            <th><strong>Description</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0</p>
            </td>
            <td>
                <p>DBGLOCK</p>
            </td>
            <td>
                <p>Non-secure, invasive debug lock.<br>
                    If this bit is set, it is not possible to debug the non-secure state in a way that is intrusive to program execution.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>NIDLOCK</p>
            </td>
            <td>
                <p>Non-secure, non-invasive debug lock.<br>
                    If this bit is set, it is not possible to observe the non-secure state of the M33 using trace.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>SPIDLOCK</p>
            </td>
            <td>
                <p>Secure, invasive debug lock.<br>
                    If this bit is set, it is not possible to debug the secure state in a way that is intrusive to program execution.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>3</p>
            </td>
            <td>
                <p>SPNIDLOCK</p>
            </td>
            <td>
                <p>Secure, non-invasive debug lock.<br>
                    If this bit is set, it is not possible to observe the secure state of the M33 using trace.<br>
                    (If SPIDLOCK is open, SPNIDLOCK will also remain open.)</p>
            </td>
        </tr>
    </tbody>
</table>

###### Read Lock Status

This command is used to read the lock status of the debug port.

**Read Lock Status Command**

|**ID [31:16]**|**Option 1 [15:8]**|**Option 2 [7:0]**|**Command payload**|**Response payload**|
|---|---|---|---|---|
|0x4311|0x00|0x00|See following|None|

Debug port lock status – total 4 bytes:

- Bit [0] - Debug lock (configuration status) is enabled if set
- Bit [1] - Device erase enabled is enabled if set
- Bit [2] – Secure debug lock enabled is enabled if set
- Bit [3:4] – Reserved
- Bit [5] – Debug lock hardware status is enabled if set
- Bit [6] – Invasive debug lock is enabled if set
- Bit [7] – Non-invasive debug lock is enabled if set
- Bit [8] - Secure invasive debug lock is enabled if set
- Bit [9] - Secure non-invasive debug lock is enabled if set

##### Series 2 DCI and SWD Programming Examples

The programming examples in this application note use the [Series 2 DCI and SWD Programming](#software-overview) platform example of GSDK v4.0.1. The hardware and software implementation may be different on other versions of the GSDK.

For more information about production programming steps, see section "_Overview_" in [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/).

###### Hardware Overview

The Wireless Starter Kit (WSTK) with the [BRD4182A Radio Board](https://www.silabs.com/documents/public/user-guides/ug430-brd4182a-user-guide.pdf) (EFR32MG22C224F512IM40) is used as the hardware platform of the DCI and SWD programmer.

The programmer uses GPIO to emulate the DCI and SWD to program the target device. The UART interface handles the user interface. The VCOM_TX and VCOM_RX are routed to the WSTK virtual COM port by setting the VCOM_ENABLE line high.

![Block Diagram of DCI and SWD Programmer](/efr32-dci-swd-programming/0.1/images/sld815-block-diagram-of-dci-and-swd-programmer.png)

**Resources of BRD4182A Used by Programmer**

|**GPIO (SoC Peripheral)**|**WSTK Peripheral**|**Function**|**EXP Header Connection**|
|---|---|---|---|
|PA01 (DBG_SWCLK)|DBG_TCK_SWCLK|Programmer debug SWCLK|—|
|PA02 (DBG_SWDIO)|DBG_TCK_SWDIO|Programmer debug SWDIO|—|
|PA05 (US1_TX)|VCOM_TX|WSTK Virtual COM port TX|Pin 12|
|PA06 (US1_RX)|VCOM_RX|WSTK Virtual COM port RX|Pin 14|
|PB04|VCOM_ENABLE|WSTK Virtual COM port enable|—|
|PC03|—|Target device RESETn|Pin 10|
|PD02|UIF_LED0|Target device SWCLK (shared with WSTK LED0)|Pin 11|
|PD03|UIF_LED1|Target device SWDIO (shared with WSTK LED1)|Pin 13|

The following figure shows the interconnection between programmer and target device. The programmer is the WSTK with the BRD4182A Radio Board and the target device is the WSTK with one of the Series 2 radio boards below.

- EFR32MG21A — BRD4181A (J101 P16 for SWCLK)
- EFR32MG21B — BRD4181C (J101 P16 for SWCLK)
- EFR32MG22 — BRD4182A (J101 P16 for SWCLK)
- EFR32FG23A — BRD4263B (J101 P20 for SWCLK)
- EFR32FG23B — BRD4263C (J101 P20 for SWCLK)

![Programmer Connection Diagram](/efr32-dci-swd-programming/0.1/images/sld815-programmer-connection-diagra.png)

The programmer powers the target device on the Series 2 radio board through VMCU. Therefore power switch (SW700) of the target device WSTK should be in the BAT position.

**Programmer Connection Diagram**

The programmer can work on other Series 2 radio boards or kits. However, the following limitations may apply.

- Some firmware images (`xg2*_app_image[] and xg2*_signed_imag[]`) in [Hard-coded Firmware Images](#firmware-images) are hardware-dependent (GPIOs for LEDs, push buttons, and UART). Therefore, they may not function properly on other radio boards or kits.
- The SWCLK and SWDIO of the target radio boards or kits may be on different pins or connectors. Therefore, the connection diagram above may not apply (refer to the board-specific schematics for details).

###### Software Overview

Users must select the BRD4182A radio board to access the `Series 2 DCI and SWD Programming` platform example in Simplicity Studio 5. Click the `View Project Documentation` link to open the `readme` file. This file includes the procedures to create the project and run the example.

![View Project Documentation](/efr32-dci-swd-programming/0.1/images/sld815-image19.jpg)

###### Bit-Bang (heading level 7)

The main overhead on writing directly to MSC registers is to emulate the [SWCLK and SWDIO](#hardware-overview) signals by bit-banging GPIO pins. The programmer must use the GPIOs in the same port group (0-7 or 8-15) for SWCLK and SWDIO to speed up this emulation process. The software writes to the entire port at once when bit-banging the SWCLK and SWDIO signals. Therefore, the programmer cannot use the spare pins of this port for other purposes.

###### Security Keys (heading level 7)

The following table describes the security keys (hard-coded in `app_dci_task.c`) used in the programming examples. Users can modify these keys to adapt to the application requirements. The files (`.prv` and `.pem`) of security keys can be found in the Windows folder `C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\secmgr\scripts\offline.`

**Hard-Coded Security Keys**

|**Array**|**Usage**|**Source**|
|---|---|---|
|aes_key[]|Decrypt GBL payloads|A 16 bytes AES-128 key in encrypt-unsafe-key.prv (binary file).|
|public_sign_key[]|Secure boot|A 64 bytes Public Sign Key, the corresponding Private Sign Key in root-sign-unsafe-privkey.pem.|
|public_command_key[]|Secure debug unlock and Disable tamper|A 64 bytes Public Command Key, the corresponding Private Command Key in cmd-unsafe-privkey.pem.|

The public key can be derived from the private key by using [OpenSSL](https://slproweb.com/products/Win32OpenSSL.html).

```sh
openssl ec -in rootsign-unsafe-privkey.pem -pubout -text > public_sign_key.txt
```

```sh
openssl ec -in cmd-unsafe-privkey.pem -pubout -text > public_command_key.txt
```

###### OTP Settings (heading level 7)

The following table describes the OTP settings (hard-coded in `app_dci_task.c`) used in the programming examples. Users can modify these values to adapt to the application requirements.

**Hard-Coded OTP Settings**

|**Array**|**OTP Settings**|**Value**|
|---|---|---|
|vse_svm_conf[]|VSE-SVM|MCU flags: Secure boot enable and Secure boot anti-rollback (0x00050000)|
|hse_svm_conf[]|HSE-SVM|MCU flags: Secure boot enable and Secure boot anti-rollback (0x00050000)|
|"|"|Reserved: 0x00000000, 0x00000000, 0x00000000, 0x00000000|
|hse_svh_xg21b_conf[]|HSE-SVH (xG21B)|MCU flags: Secure boot enable and Secure boot anti-rollback (0x00050000)|
|"|"|Tamper source levels: 0x40440410, 0x14040104, 0x77442211, 0x42042224|
|"|"|Filter reset period: 10|
|"|"|Filter trigger threshold: 6|
|"|"|Tamper flags: 0|
|"|"|Tamper reset threshold: 5|
|hse_svh_other_conf[]|HSE-SVH (others)|MCU flags: Secure boot enable and Secure boot anti-rollback (0x00050000)|
|"|"|Tamper source levels: 0x40440410, 0x14040104, 0x22414224, 0x74422112|
|"|"|Filter reset period: 10|
|"|"|Filter trigger threshold: 6|
|"|"|Tamper flags: 0|
|"|"|Tamper reset threshold: 5|

> **Note**: Refer to the tables below for details about OTP settings.

- [Parameters of MCU Flags](05-se-command-list#mcu-flags)
- [Tamper Source Response Level on HSE-SVH (xG21B) Devices](05-se-command-list#anti-tamper-configuration)
- [Tamper Source Response Level on Other HSE-SVH Devices](05-se-command-list#anti-tamper-configuration)
- [Anti-Tamper Configuration Settings](05-se-command-list#anti-tamper-configuration)

###### Firmware images (heading level 7)

The following table describes the firmware images (hard-coded in `app_firmware_image.c`) used in the programming examples. Users can modify these images to adapt to the application requirements.

**Hard-Coded Firmware Images**

|**Array**|**Size (Bytes)**|**Usage**|
|---|---|---|
|xg21_hse_image[]|41125|The xG21 HSE upgrade firmware image (v1.2.9)|
|xg21_app_image[]|9212|The xG21 application firmware image (Blink Bare-metal platform example)|
|xg21_signed_image[]|11192|A signed xG21 UART XMODEM Bootloader image (v1.12.0)|
|erase_xg21_userdata[]|3068|Application firmware image to erase xG21 user data|
|write_xg21_userdata[]|4228|Application firmware image to program xG21 user data|
|prog_xg21_hse_upgrade[]|6956|Application firmware image to upgrade xG21 HSE firmware|
|xg22_vse_image[]|16549|The xG22 VSE upgrade firmware image (v1.2.7)|
|xg22_app_image[]|10756|The xG22 application firmware image (Blink Bare-metal platform example)|
|xg22_signed_image[]|14128|A signed xG22 UART XMODEM Bootloader image (v1.12.0)|
|prog_xg22_vse_upgrade[]|9320|Application firmware image to upgrade xG22 VSE firmware|
|xg23_hse_image[]|88221|The xG23 HSE upgrade firmware image (v2.1.4)|
|xg23_app_image[]|13560|The xG23 application firmware image (Blink Bare-metal platform example)|
|xg23_signed_image[]|16248|A signed xG23 UART XMODEM Bootloader image (v1.12.0)|
|prog_xg23_hse_upgrade[]|11696|Application firmware image to upgrade xG23 HSE firmware|

> **Note**:
> 
> - The HSE or VSE upgrade firmware image must be stored to the device's internal flash in [.seu](02-introduction#introduction) format.
> - The firmware image (`.seu` format) can be converted to a C source file using the SEGGER free utility [`Bin2C.exe`](https://www.segger.com/free-utilities/bin2c/). The last **NULL** (`0x00`) character in the converted firmware image array should be discarded.
> 
> ![Bin2C.exe](/efr32-dci-swd-programming/0.1/images/sld815-image20.png)
> 
> - The programmer uses the bootloader image signed by the Private Sign Key ([rootsign-unsafe-privkey.pem](#security-keys)) to recover a secure boot failure device.
> - Refer to [Add a New Series Device to the Programmer](07-add-a-new-series-2-device-to-the-programmer#add-a-new-series-2-device-to-the-programmer) for instructions on adding firmware images for newer devices.

###### Compile Options (heading level 7)

The following tables describe the compile options in header files to set up the software and hardware environment for the programming examples.

**Compile Options in app_dci_swd.h**

|**Parameter**|**Usage**|**Default Setting**|
|---|---|---|
|RESET_PULSE|Pin reset pulse width in microseconds|1000 µs (1 ms)|
|RESET_DELAY|Delay in microseconds after issuing a soft or pin reset|50000 µs (50 ms)|
|DCI_RETRY_COUNT|Number of times to retry a DCI read or write operation. It must be high enough to receive a response from the SE command.|1001000|
|SWCLK_PORT|GPIO port for SWCLK|3 (Port D)|
|SWCLK_PIN|GPIO pin for SWCLK|2 (PD02)|
|SWDIO_PORT|GPIO port for SWDIO|3 (Port D)|
|SWDIO_PIN|GPIO pin for SWDIO|3 (PD03)|
|RESET_PORT|GPIO port for RESETn|2 (Port C)|
|RESET_PIN|GPIO pin for RESETn|3 (PC03)|

**Compile Options in app_firmware_image.h**

|**Parameter**|**Usage**|**Default Setting**|
|---|---|---|
|SE_START_ADDR|SE upgrade firmware image start address (aligned with 8 kB flash page size)|0x00060000|
|SE_UPGRADE_DELAY|Delay in microseconds after issuing a command to upgrade the SE firmware|2500000 µs (2.5 s)|
|USER_DATA_DELAY|Delay in microseconds after issuing a soft reset to run the application to erase or write the user data on xG21 devices|1000000 µs (1 s)|

> **Note**: Make sure the device has enough flash space to accommodate the SE firmware image when setting the SE_START_ADDR.

**Compile Options in app_swd_task.h**

|**Parameter**|**Usage**|**Default Setting**|
|---|---|---|
|ERASE_DELAY|Delay in microseconds after a flash page erase or mass erase|12000 µs (12 ms)|
|ERASE_LOOPCNT|It must be high enough to cover the page erase or mass erase time|1000|
|SKIP_POLLING|Skip polling WDATAREADY bit in the MSC STATUS register after writing 32-bit word to target device flash|1 (Skip)|
|WRITE_DELAY|Fix delay in microseconds after writing a 32-bit word to target device flash (if SKIP_POLLING = 1)|11 µs|

> **Note**:
> 
> - Refer to [Flash Erase](04-serial-wire-debug-swd-interface#flash-erase) for details about page erase and mass erase.
> - Refer to [Flash Write](04-serial-wire-debug-swd-interface#flash-write) for details about `SKIP_POLLING` and `WRITE_DELAY`.

###### Menu Operation

The `SPACE` and `ENTER` presses from the terminal program are used to manipulate the menu of the programmer.

###### Interface Menu (heading level 7)

```sh
Series 2 DCI and SWD Programming Examples - Core running at 80000 kHz.
 . Current interface selection is DEBUG CHALLENGE INTERFACE (DCI).
 + Press SPACE to pick an interface (DCI/SWD), press ENTER to select the task of the chosen interface.
```

**DCI Menu**

```sh
. Current DCI task is GET SE STATUS.
 + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.
 + Current DCI task is READ SE OTP CONFIGURATION.
 + Current DCI task is READ SERIAL NUMBER.
 + Current DCI task is READ PUBLIC SIGN KEY.
 + Current DCI task is READ PUBLIC COMMAND KEY.
 + Current DCI task is READ LOCK STATUS.
 + Current DCI task is SET DEBUG RESTRICTIONS.
 + Current DCI task is ENABLE SECURE DEBUG.
 + Current DCI task is DISABLE SECURE DEBUG.
 + Current DCI task is LOCK DEVICE.
 + Current DCI task is ERASE DEVICE (UNLOCK).
 + Current DCI task is RECOVER SECURE BOOT FAILURE DEVICE.
 + Current DCI task is UPGRADE SE FIRMWARE THROUGH DCI.
 + Current DCI task is INITIALIZE AES-128 KEY (HSE).
 + Current DCI task is INITIALIZE PUBLIC SIGN KEY.
 + Current DCI task is INITIALIZE PUBLIC COMMAND KEY.
 + Current DCI task is INITIALIZE SE OTP.
 + Current DCI task is DISABLE DEVICE ERASE.
```

From task `ENABLE SECURE DEBUG` to task `UPGRADE SE FIRMWARE THROUGH DCI`:

```sh
 + Current DCI task is ENABLE SECURE DEBUG.
 + Press ENTER to confirm or press SPACE to abort.
```

From task `INITIALIZE AES-128 KEY (HSE)` to task `DISABLE DEVICE ERASE`:

```sh
+ Current DCI task is DISABLE DEVICE ERASE.
 + Warning: This is a ONE-TIME command and the operation is IRREVERSIBLE!
 + Press ENTER to confirm or press SPACE to abort.
```

**SWD Interface Menu**

```sh
Series 2 DCI and SWD Programming Examples - Core running at 80000 kHz.
 . Current interface selection is DEBUG CHALLENGE INTERFACE (DCI).
 + Press SPACE to pick an interface (DCI/SWD), press ENTER to select the task of the chosen interface.
 + Current interface selection is SERIAL WIRE DEBUG (SWD) INTERFACE.

 . Current SWD task is ERASE MAIN FLASH.
 + Press SPACE to cycle through the SWD tasks, press ENTER to run the selected SWD task.
 + Current SWD task is PROGRAM MAIN FLASH.
 + Current SWD task is ERASE USER DATA.
 + Current SWD task is PROGRAM USER DATA.
 + Current SWD task is UPGRADE SE FIRMWARE THROUGH APPLICATION FIRMWARE.
```

```sh
 + Current SWD task is ERASE MAIN FLASH.
 + Press ENTER to confirm or press SPACE to abort.
```

**Error Handling**

```sh
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

###### DCI Programming Examples (heading level 7)

The following DCI programming examples are based on EFR32MG21B (BRD4181C) as the target device [Programmer Connection Diagram on page 23](#hardware-overview). Software is compiled with -O2 optimization in Simplicity IDE of Simplicity Studio 5.

**Get SE Status**

- To get the current [SE status](05-se-command-list#get-status).

```sh
 . Current DCI task is GET SE STATUS.
 + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

###### Read SE OTP Configuration (heading level 7)

- To read the current [SE OTP configuration](05-se-command-list#read-user-configuration).  
  ```sh  
  . Current DCI task is READ SE OTP CONFIGURATION.  
  + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.  
    
  . Read target device user (SE OTP) configuration... OK  
  + Secure boot : Disabled  
  + Secure boot verify certificate : Disabled  
  + Secure boot anti-rollback : Disabled  
  + Secure boot page lock narrow : Disabled  
  + Secure boot page lock full : Disabled  
  + Tamper source level  
  Filter counter : 1  
  SE watchdog : 4  
  SE RAM CRC : 4  
  SE hard fault : 4  
  SE software assertion : 4  
  SE secure boot : 4  
  User secure boot : 0  
  Mailbox authorization : 1  
  DCI authorization : 0  
  OTP read : 4  
  Self test : 4  
  TRNG monitor : 1  
  PRS0 : 1  
  PRS1 : 1  
  PRS2 : 2  
  PRS3 : 2  
  PRS4 : 4  
  PRS5 : 4  
  PRS6 : 7  
  PRS7 : 7  
  Decouple BOD : 4  
  Temperature sensor : 2  
  Voltage glitch falling : 2  
  Voltage glitch rising : 2  
  Secure lock : 4  
  SE debug : 0  
  Digital glitch : 2  
  SE ICACHE : 4  
  + Reset period for the tamper filter counter: ~32 ms x 1024  
  + Activation threshold for the tamper filter: 4  
  + Digital glitch detector always on: Disabled  
  + Tamper reset threshold: 5  
  ```
- SE will return the [SE_RESPONSE_INVALID_COMMAND](03-debug-challenge-interface-dci#response) code if the SE OTP data has not been initialized or SE firmware version is less than v1.2.2 (xG21 or xG22 devices).

```sh
 . Read target device user (SE OTP) configuration... Failed - Unsupported command.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Read Serial Number**

- To read the [serial number](05-se-command-list#read-serial-number) of the Series 2 device.

```sh
 . Current DCI task is READ SERIAL NUMBER.
 + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.
 . Read target device serial number... OK
 + The serial number (16 bytes): 000000000000000014B457FFFE0F77CE
```

###### Read Public Sign Key (heading level 7)

- To read the [Public Sign Key](05-se-command-list#read-public-key) in SE OTP.

```sh
 . Current DCI task is READ PUBLIC COMMAND KEY.
 + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.
 . Read target device public command key... OK
 + The public command key (64 bytes): B1BC6F6FA56640ED522B2EE0F5B3CF7E5D48F60BE8148F0DC08440F0A4E1DCA4
 7C04119ED6A1BE31B7707E5F9D001A659A051003E95E1B936F05C37EA793AD63
```

- SE will return the [SE_RESPONSE_INTERNAL_ERROR](03-debug-challenge-interface-dci#response) code if the Public Sign Key has not been provisioned.

```sh
 . Read target device public command key... Failed - Internal SE error.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Read Public Command Key**

- To read the [Public Command Key](05-se-command-list#read-public-key) in SE OTP.

```sh
 . Current DCI task is READ PUBLIC COMMAND KEY.
 + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.
 . Read target device public command key... OK
 + The public command key (64 bytes): B1BC6F6FA56640ED522B2EE0F5B3CF7E5D48F60BE8148F0DC08440F0A4E1DCA4
 7C04119ED6A1BE31B7707E5F9D001A659A051003E95E1B936F05C37EA793AD63
```

- SE will return the [SE_RESPONSE_INTERNAL_ERROR](03-debug-challenge-interface-dci#response) code if the Public Command Key has not been provisioned.

```sh
 . Read target device public command key... Failed - Internal SE error.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Read Lock Status**

- To read the lock state of the debug port.

```sh
+ Current DCI task is READ LOCK STATUS.
 . Debug port lock state
 + Debug Locked, config status : Disabled.
 + Device erase : Enabled.
 + Secure debug unlock : Enabled.
 + Debug port : Unlocked.
 + Invasive Debug Lock : Unlocked.
 + Non-invasive Debug Lock : Unlocked.
 + Secure Invasive Debug Lock : Unlocked.
 + Secure Non-invasive Debug Lock : Unlocked.
```

**Set Debug Restrictions**

- To set debug restrictions.

```sh
 + Setting the lockbit for Secure, Non-Invasive Debug
 . Set the debug restriction bits of the target device... OK
 . Read target device SE status... OK
 + SE firmware version : 0001020E
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Enabled
 + Secure boot : Disabled and SE OTP is not configured
 + Boot status : 0x20 - Command successful.
Series 2 DCI and SWD Programming Examples - Core running at 80000 kHz.
 . Current interface selection is DEBUG CHALLENGE INTERFACE (DCI).
 + Press SPACE to pick an interface (DCI/SWD), press ENTER to select the task of the chosen interface.
```

###### Enable Secure Debug (heading level 7)

- To [enable](05-se-command-list#enable-secure-debug) the secure debug functionality.

```sh
 + Current DCI task is ENABLE SECURE DEBUG.
 + Press ENTER to confirm or press SPACE to abort.
 . Enable secure debug of the target device... OK
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Enabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

- SE will return the [SE_RESPONSE_INVALID_PARAMETER](03-debug-challenge-interface-dci#response) code if the Public Command Key has not been provisioned.

```sh
 . Enable secure debug of the target device... Failed - Parameters are invalid or buffer is too small.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

- SE will return the [SE_RESPONSE_INVALID_COMMAND](03-debug-challenge-interface-dci#response) code if the secure debug has already enabled.

```sh
 . Enable secure debug of the target device... Failed - Unsupported command.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Disable Secure Debug**

- To [disable](05-se-command-list#disable-secure-debug) the secure debug functionality.

```sh
 + Current DCI task is DISABLE SECURE DEBUG.
 + Press ENTER to confirm or press SPACE to abort.
 . Disable secure debug of the target device... OK
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

**Lock Device**

- To enable the [debug lock](05-se-command-list#apply-lock) of the Series 2 device.

```sh
 + Current DCI task is LOCK DEVICE.
 + Press ENTER to confirm or press SPACE to abort.
 . Lock target device... OK
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Enabled
 + Debug lock state : True
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

**Erase Device (Unlock)**

- To perform a device mass erase and [unlock](05-se-command-list#erase-device) the standard debug lock of the Series 2 device.

```sh
 + Current DCI task is ERASE DEVICE (UNLOCK).
 + Press ENTER to confirm or press SPACE to abort.
 . Erase (unlock) target device... OK
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

- SE will return the [SE_RESPONSE_INVALID_COMMAND](03-debug-challenge-interface-dci#erase-device) code if the [Device Erase](05-se-command-list#disable-device-erase) is disabled.

```sh
 . Erase (unlock) target device... Failed - Unsupported command.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Recover Secure Boot Failure Device**

- To get the current [SE status](05-se-command-list#get-status).

```sh
 . Current DCI task is GET SE STATUS.
 + Press SPACE to cycle through the DCI tasks, press ENTER to run the selected DCI task.
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Enabled
 + Boot status : 0x14 - Failure while checking the host for secure boot.
```

- Issue a [device erase](05-se-command-list#erase-device) to unlock the target device through DCI.

```sh
 + Current DCI task is RECOVER SECURE BOOT FAILURE DEVICE.
 + Press ENTER to confirm or press SPACE to abort.

 . Issue a device erase through DCI.
 + Erase target device... OK
```

- A correctly-signed firmware image [xg21_signed_image[]](#firmware-images) is programmed to the target device main flash through the SWD interface to recover a secure boot failure device.

```sh
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x14B457FFFE0F7762
 . Program a correctly-signed image to recover device.
 + The xG21 signed firmware image size is 11192 bytes and start address is 0x00000000.
 + Erase-Program-Verify the xG21 main flash for signed firmware image... OK (cycles: 13616519 time: 170 ms)
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : 010C0000
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Enabled
 + Boot status : 0x20 - Command successful.
```

- The device cannot be recovered if the image is not correctly-signed.

```sh
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : 010C0000
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Enabled
 + Boot status : 0x12 - Failure while checking the host for secure boot.
```

**Upgrade SE Firmware Through DCI**

- A SE upgrade firmware image [xg21_hse_image[]](#firmware-images) is programmed to the target device main flash at [SE_START_ADDR](#compile-options) through the SWD interface. It will overwrite the data from `SE_START_ADDR` to `SE_START_ADDR` + the size of `xg21_hse_image[]`.

```sh
 + Current DCI task is UPGRADE SE FIRMWARE THROUGH DCI.
 + Press ENTER to confirm or press SPACE to abort.
 . Program a SE firmware image to the target device.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x588E81FFFE7034E5
 + The xG21 HSE firmware image version: 00010209
 + The xG21 HSE firmware image size is 41125 bytes and start address is 0x00060000.
 + Erase-Program-Verify the xG21 main flash for HSE firmware image... OK (cycles: 52365323 time: 654 ms)
```

- [Validate](05-se-command-list#se-image-check) the SE upgrade firmware image and start the [upgrade](05-se-command-list#se-image-apply) process if the image is valid.

```sh
 . Validate SE firmware image in the target device... OK
 . Upgrade SE firmware image, delay few seconds to check SE status... Done
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

- SE will return the [SE_RESPONSE_INVALID_PARAMETER](03-debug-challenge-interface-dci#response) code if the SE upgrade firmware image is invalid.

```sh
 . Validate SE firmware image in the target device... Failed - Parameters are invalid or buffer is too small.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

- SE will return the [SE_RESPONSE_INVALID_COMMAND](03-debug-challenge-interface-dci#response) code if the current SE firmware version is less than v1.2.2 (xG21 or xG22 devices).

```sh
 . Validate SE firmware image in the target device... Failed - Unsupported command.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.

```

###### Initialize AES-128 Key (HSE) (heading level 7)

- To [initialize](05-se-command-list#initialize-aes-key) the [aes_key[]](#security-keys) to HSE OTP.

```sh
 + Current DCI task is INITIALIZE AES-128 KEY (HSE).
 + Warning: This is a ONE-TIME command and the operation is IRREVERSIBLE!
 + Press ENTER to confirm or press SPACE to abort.
 . Initialize AES-128 key of the target device... OK
```

- SE will return the [SE_RESPONSE_INVALID_PARAMETER](03-debug-challenge-interface-dci#response) code if the AES-128 key has already been initialized.

```sh
 . Initialize AES-128 key of the target device... Failed - Parameters are invalid or buffer is too small.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Initialize Public Sign Key**

- To [initialize](05-se-command-list#initialize-public-key) the [public_sign_key[]](#security-keys) to SE OTP.

```sh
 + Current DCI task is INITIALIZE PUBLIC SIGN KEY.
 + Warning: This is a ONE-TIME command and the operation is IRREVERSIBLE!
 + Press ENTER to confirm or press SPACE to abort.
 . Initialize public sign key of the target device... OK
 . Read target device public sign key... OK
 + The public sign key (64 bytes): C4AF4AC69AAB9512DB50F7A26AE5B4801183D85417E729A56DA974F4E08A562C
 DE6019DEA9411332DC1A743372D170B436238A34597C410EA177024DE20FC819
```

- SE will return the [SE_RESPONSE_INVALID_PARAMETER](03-debug-challenge-interface-dci#response) code if the Public Sign Key has already been initialized.

```sh
 . Initialize public sign key of the target device... Failed - Parameters are invalid or buffer is too small.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Initialize Public Command Key**

- To [initialize](05-se-command-list#initialize-public-key) the [public_command_key[]](#security-keys) to SE OTP.

```sh
 + Current DCI task is INITIALIZE PUBLIC COMMAND KEY.
 + Warning: This is a ONE-TIME command and the operation is IRREVERSIBLE!
 + Press ENTER to confirm or press SPACE to abort.
 . Initialize public command key of the target device... OK
 . Read target device public command key... OK
 + The public command key (64 bytes): B1BC6F6FA56640ED522B2EE0F5B3CF7E5D48F60BE8148F0DC08440F0A4E1DCA4
 7C04119ED6A1BE31B7707E5F9D001A659A051003E95E1B936F05C37EA793AD63
```

- SE will return the [SE_RESPONSE_INVALID_PARAMETER](03-debug-challenge-interface-dci#response) code if the Public Command Key has already been initialized.

```sh
 . Initialize public command key of the target device... Failed - Parameters are invalid or buffer is too small.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

###### Initialize SE OTP (heading level 7)

- To [initialize](05-se-command-list#initialize-otp) the [hse_svh_xg21b_conf[]](#otp-settings) to the HSE OTP.

```sh
 + Current DCI task is INITIALIZE SE OTP.
 + Warning: This is a ONE-TIME command and the operation is IRREVERSIBLE!
 + Press ENTER to confirm or press SPACE to abort.
 . Initialize SE OTP of the target device... OK
 . Read target device user (SE OTP) configuration... OK
 + Secure boot : Enabled
 + Secure boot verify certificate : Disabled
 + Secure boot anti-rollback : Enabled
 + Secure boot page lock narrow : Disabled
 + Secure boot page lock full : Disabled
 + Tamper source level
 Filter counter : 1
 SE watchdog : 4
 SE RAM CRC : 4
 SE hard fault : 4
 SE software assertion : 4
 SE secure boot : 4
 User secure boot : 0
 Mailbox authorization : 1
 DCI authorization : 0
 OTP read : 4
 Self test : 4
 TRNG monitor : 1
 PRS0 : 1
 PRS1 : 1
 PRS2 : 2
 PRS3 : 2
 PRS4 : 4
 PRS5 : 4
 PRS6 : 7
 PRS7 : 7
 Decouple BOD : 4
 Temperature sensor : 2
 Voltage glitch falling : 2
 Voltage glitch rising : 2
 Secure lock : 4
 SE debug : 0
 Digital glitch : 2
 SE ICACHE : 4
 + Reset period for the tamper filter counter: ~32 ms x 1024
 + Activation threshold for the tamper filter: 4
 + Digital glitch detector always on: Disabled
 + Tamper reset threshold: 5
```

- SE will return the [SE_RESPONSE_INVALID_COMMAND](03-debug-challenge-interface-dci#response) code if the SE OTP has already programmed.

```sh
 . Initialize SE OTP of the target device... Failed - Unsupported command.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

- SE will return the [SE_RESPONSE_INVALID_PARAMETER](03-debug-challenge-interface-dci#response) code if secure boot option is enabled and the Public Sign Key has not been provisioned.

```sh
 . Initialize SE OTP of the target device... Failed - Parameters are invalid or buffer is too small.
 + Press ENTER to issue a pin reset to the target, press SPACE to skip.
```

**Disable Device Erase**

- To [disable](05-se-command-list#disable-device-erase) the [Erase Device](05-se-command-list#erase-device) command.

```sh
 + Current DCI task is DISABLE DEVICE ERASE.
 + Warning: This is a ONE-TIME command and the operation is IRREVERSIBLE!
 + Press ENTER to confirm or press SPACE to abort.
 . Disable device erase of the target device... OK
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Disabled
 + Secure debug : Enabled
 + Secure boot : Disabled
 + Boot status : 0x20 - Command successful.
```

###### SWD Programming Examples

The following SWD programming examples are based on EFR32MG21B (BRD4181C) and EFR32MG22 (BRD4182A) as target devices ([Programmer Connection Diagram](#hardware-overview)). Software is compiled with -O2 optimization in the Simplicity IDE of Simplicity Studio 5.

If the secure boot option is enabled in the SE OTP or bootloader, the application firmware must be signed.

Some operations are implemented by the SE Manager APIs in an application firmware that is programmed to the target device.

- For more information about SE Manager, see [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).
- The SE Manager is available in Gecko SDK Suite 3.0.0 or later.
- The SE Manager APIs are fully described in the Silicon Labs online documentation located at [https://docs.silabs.com/gecko-plat-](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager) [form/latest/service/api/group-sl-se-manager](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager).

**Erase Main Flash**

- This example demonstrates the [mass erase](04-serial-wire-debug-swd-interface#flash-erase) operation through the SWD interface.

```sh
 + Current SWD task is ERASE MAIN FLASH.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x14B457FFFE0F77CE
 . Erase main flash of the target device... OK (cycles: 1511120 time: 18889 us)
```

**Program Main Flash**

- This example demonstrates the [flash erase](04-serial-wire-debug-swd-interface#flash-erase), [flash write](04-serial-wire-debug-swd-interface#flash-write), and [flash verify](04-serial-wire-debug-swd-interface) operations through the SWD interface. In this example, an application firmware image [xg21_app_image[]](#firmware-images) is programmed to the target device main flash.

```sh
 + Current SWD task is PROGRAM MAIN FLASH.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x14B457FFFE0F77CE
 . Program an application firmware image to the target device.
 + The xG21 application firmware image size is 9212 bytes and start address is 0x00000000.
 + Erase-Program-Verify the xG21 main flash for application firmware image... OK (cycles: 11388469 time: 142 ms)
 + Issue a soft reset to run the application firmware... OK
```

**Erase User Data (xG21 Devices)**

- For xG21 devices (BRD4181C), the user data can only be erased by issuing a command to the HSE through the SE Manager API.
- In this example, an application firmware image [erase_xg21_userdata[]](#firmware-images) (see source code below) is programmed to the target device main flash.

```sh
#include "em_chip.h"
#include "em_cmu.h"
#include "sl_se_manager.h"
#include "sl_se_manager_util.h"
/***************************************************************************//**
 * Main function
 ******************************************************************************/
int main(void)
{
 // Command context
 sl_se_command_context_t cmd_ctx;
 // Switch SYSCLK to 38 MHz HFRCO
 CMU_HFRCODPLLBandSet(cmuHFRCODPLLFreq_38M0Hz);
 // Initialize SE Manager
 sl_se_init();
 // Erase user page
 sl_se_erase_user_data(&cmd_ctx);
 
 while (1) ;
}
```

- The original application firmware image on the application start address will be overwritten.
- Issue a soft reset to run the application above to erase the user data.

```sh
 + Current SWD task is ERASE USER DATA.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x14B457FFFE0F77CE
 . Erase xG21 user data through application firmware.
 + The xG21 application firmware image size is 3068 bytes and start address is 0x00000000.
 + Erase-Program-Verify the xG21 main flash for application firmware image... OK (cycles: 4473314 time: 55916 us)
 + Issue a soft reset to run the application firmware to erase the xG21 user data... OK
```

**Erase User Data (non xG21 Devices)**

- For non xG21 devices (BRD4182A), the user data can be erased the same way as any page in the main flash.

```sh
 + Current SWD task is ERASE USER DATA.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG22C224F512 and unique ID is 0x680AE2FFFE287808
 . Erase xG22 user data... OK (cycles: 2027306 time: 25341 us)
```

**Program User Data (xG21 Devices)**

- For xG21 devices (BRD4181C), the user data can only be written by issuing a command to the HSE through the SE Manager API.
- In this example, an application firmware image write_xg21_userdata[] (see source code below) is programmed to the target device  
  main flash.

```sh
#include "em_chip.h"
#include "em_cmu.h"
#include "sl_se_manager.h"
#include "sl_se_manager_util.h"
// User data
SL_ALIGN(4) static const uint32_t user_data[256] SL_ATTRIBUTE_ALIGN(4) = {
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55, 0x55AA55AA, 0xAA55AA55,
};
/***************************************************************************//**
 * Main function
 ******************************************************************************/
int main(void)
{
 // Command context
 sl_se_command_context_t cmd_ctx;
 // Switch SYSCLK to 38 MHz HFRCO
 CMU_HFRCODPLLBandSet(cmuHFRCODPLLFreq_38M0Hz);
 // Initialize SE Manager
 sl_se_init();
 // Erase user data
 sl_se_erase_user_data(&cmd_ctx);
 
 // Write user data
 sl_se_write_user_data(&cmd_ctx, 0, (uint32_t *)user_data, sizeof(user_data));
 while (1) ;
}
```

- The original application firmware image on the application start address will be overwritten.
- Issue a soft reset to run the application above to write the user data.

```sh
 + Current SWD task is PROGRAM USER DATA.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x14B457FFFE0F77CE
 . Program xG21 user data through application firmware.
 + The xG21 application firmware image size is 4228 bytes and start address is 0x00000000.
 + Erase-Program-Verify the xG21 main flash for application firmware image... OK (cycles: 5777749 time: 72221 us)
 + Issue a soft reset to run the application firmware to program the xG21 user data... OK
```

**Program User Data (non xG21 Devices)**

- For non xG21 devices (BRD4182A), the user data can be written the same way as any page in the main flash.

```sh
 + Current SWD task is PROGRAM USER DATA.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG22C224F512 and unique ID is 0x680AE2FFFE287808
 . Program xG22 user data.
 + User data size is 1024 bytes and start address is 0x0FE00000.
 + Erase-Program-Verify the xG22 user data... OK (cycles: 2179418 time: 27242 us)
```

**Upgrade SE Firmware Through Application Firmware**

- For xG21 or xG22 target devices, the SE firmware can only be upgraded by issuing a command to the SE through the SE Manager API if the SE firmware version is less than v1.2.2.
- Connect to the target device through the SWD interface.
- An application firmware image [prog_xg21_hse_upgrade[]](#firmware-images) (see source code below) is programmed to the target device main flash.

```sh
#include "em_chip.h" #include "em_cmu.h" #include "sl_se_manager.h"

#include "sl_se_manager_util.h"

// SE firmware image start address

#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG) \ && (_SILICON_LABS_32B_SERIES_2_CONFIG \< 3)

#define SE_START_ADDR (**0x00060000UL**)

#else

#define SE_START_ADDR (**0x08060000UL**)

#endif

// Current SE firmware version static uint32_t current_version;

// Upgrade SE firmware version

static volatile uint32_t upgrade_version;

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*//\*\*

\* Main function

\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ int main(void)

{

// Command context sl_se_command_context_t cmd_ctx;

// Switch SYSCLK to 38 MHz HFRCO CMU_HFRCODPLLBandSet(cmuHFRCODPLLFreq_38M0Hz);

// Initialize SE Manager sl_se_init();

// Get current SE firmware version

if (sl_se_get_se_version(&cmd_ctx, &current_version) != 0) { goto exit;

}

// Get upgrade SE firmware version

upgrade_version = \*((uint32_t \*)SE_START_ADDR + 3);

// Check if upgrade version \> current version if (upgrade_version \<= current_version) {

goto exit;

}

#if !defined(CRYPTOACC_PRESENT)

// Validate the SE firmware image

if (sl_se_check_se_image(&cmd_ctx, (uint32_t \*)SE_START_ADDR) != 0) { goto exit;

}

#endif

// Upgrade the SE firmware image sl_se_apply_se_image(&cmd_ctx, (uint32_t \*)SE_START_ADDR);

exit:

while (1) ;

}
```

- The original application firmware image on the application start address will be overwritten.

```sh
 + Current SWD task is UPGRADE SE FIRMWARE THROUGH APPLICATION FIRMWARE.
 + Press ENTER to confirm or press SPACE to abort.
 . Connect to the target device through the SWD interface.
 + Initialize DP... OK - IDCODE = 0x6BA02477
 + Read AP... OK - IDR = 0x84770001
 + Set up AHB-AP and halt target... OK
 + Get device information... OK - Target device is EFR32MG21B010F1024 and unique ID is 0x60A423FFFEA0773C
 . Program an application firmware image to the target device to upgrade the SE firmware.
 + The xG21 HSE upgrade application firmware image size is 6956 bytes and start address is 0x00000000.
 + Erase-Program-Verify the xG21 main flash for application to upgrade
 HSE firmware... OK (cycles: 8840993 time: 110 ms)
```

- A SE upgrade firmware image [xg21_hse_image[]](#firmware-images) is programmed to the target device main flash at [SE_START_ADDR](#compile-options). The application start address cannot overlap with `SE_START_ADDR`. This means the `SE_START_ADDR` must be greater than the application start address plus the size [6956 bytes](#firmware-images) of the application firmware image (`prog_xg21_hse_upgrade[]`).

```sh
 . Program a SE firmware image to the target device.
 + The xG21 HSE firmware image version: 00010209
 + The xG21 HSE firmware image size is 41125 bytes and start address is 0x00060000.
 + Erase-Program-Verify the xG21 main flash for HSE firmware image... OK (cycles: 52363897 time: 654 ms)
```

- Issue a pin reset to run the application firmware in `prog_xg21_hse_upgrade[]`.
- Check the SE firmware version after a few seconds to verify the SE firmware has been upgraded.

```sh
 + Issue a pin reset to run the application to upgrade the SE firmware.
 + Delay few seconds to check SE status... Done
 . Read target device SE status... OK
 + SE firmware version : 00010209
 + MCU firmware version : NA
 + Debug lock : Disabled
 + Debug lock state : False
 + Device Erase : Enabled
 + Secure debug : Disabled
 + Secure boot : Disabled and SE OTP is not configured
 + Boot status : 0x20 - Command successful.
```

- The SE firmware cannot be downgraded so the upgrade will be ignored if SE firmware with the same or a lower version is applied to the device.

###### Benchmark

The application firmware in [Hard-coded Firmware Images on page 26](#firmware-images) is replaced by a 256 kB image for benchmarking. The test results in the following table are based on the conditions below.

- [Series 2 DCI and SWD Programming](#software-overview) platform example of GSDK v4.0.1
- Erase, program, and verify the main flash
- [Compile options](#compile-options) are set to default values
- Software is compiled with -O2 in Simplicity IDE (GNU ARM v10.2.1) of Simplicity Studio 5
- The programmer (EFR32MG22C224F512IM40) is running at 80 MHz

**Erase-Program-Verify Time for Different Target Devices**

|**Target Device**|**Application Firmware Image Size**|**Erase-Program-Verify Time**|
|---|---|---|
|EFR32MG21B (BRD4181C)|256 kB (xg21_app_image[])|3.68 s|
|EFR32MG22 (BRD4182A)|256 kB (xg22_app_image[])|3.68 s|
|EFR32FG23B (BRD4263C)|256 kB (xg23_app_image[])|3.74 s|

> **Note**: The following section describes how to add firmware images for newer devices. Users requiring performance data for devices not listed here can add their own 256 kb image to perform the test.

##### Add a New Series 2 Device to the Programmer

The programmer in this application note uses EFR32MG22C224F512IM40 as a host controller. The defines in the following table for EFR32MG22C224F512 should usually apply to the new Series 2 devices.

**Defines for EFR32MG22C224F512**

|**Item**|**Define**|**Value**|
|---|---|---|
|Main flash base address|FLASH_MEM_BASE in efr32mg22c224f512im40.h|0x00000000|
|User data base address|USERDATA_BASE in efr32mg22c224f512im40.h|0x0FE00000|
|MSC base address|MSC_BASE in efr32mg22c224f512im40.h|0x40030000|
|Offset and bitfields of MSC registers|MSC Register Map in xG22 reference manual|—|
|DEVINFO base address|DEVINFO_BASE in efr32mg22c224f512im40.h|0x0FE08000|
|Offset and bitfields of DEVINFO registers|DEVINFO Register Map in xG22 reference manual|—|
|CMU base address|CMU_BASE in efr32mg22c224f512im40.h|0x40008000|
|Offset of CMU_CLKEN1_SET register|CMU Register Map in xG22 reference manual|0x00001068|
|Bitmask to enable MSC clock|CMU_CLKEN1_MSC in efr32mg22_cmu.h|0x00020000|
|AP IDR (Cortex-M33)|S2_AHBAP_ID in app_dci_swd.h|0x84770001|
|TAR wrap mask (Cortex-M33)|TAR_WRAP_1K in app_swd_task.h|0x3FF|

Users need to define new items if any defines in the table above do not match the new Series 2 device. And users may require tuning the settings in [Compile Options](06-series-2-dci-and-swd-programming-examples#compile-options) for the new Series 2 device.

The following procedures describe how to add the xG23 device to the programmer.

1. Add `XG23_FAMILY` (`0x17` for 23) to `app_swd_task.h.` It is `0x15` for xG21, `0x16` for xG22, `0x17` for xG23, etc.  
   ```sh  
   /// Device family of xG23  
   #define XG23_FAMILY (0x00170000UL)  
   ```
2. The  items  below  are  different  from  the  EFR32MG22C224F512  after  checking  the  xG23  header  files  (e.g., efr32fg23b010f512im48.h) and reference manual.  
   - Main [flash base address](04-serial-wire-debug-swd-interface#flash-erase) — Add `FLASH_BASE_XG23` to `app_swd_task.h.`  
   ```sh  
   /// Flash start address of xG23  
   #define FLASH_BASE_XG23 (0x08000000UL)  
   ```  
   - Bitmask to enable MSC clock — Add `CLKEN1_MSC_XG23` to `app_swd_task.h.`  
   ```sh  
   /// MSC bit of xG23 CMU_CLKEN1_SET  
   #define CLKEN1_MSC_XG23 (0x00010000UL)  
   ```
3. Add code to `app_swd_task.c` to enable [MSC clock](04-serial-wire-debug-swd-interface#serial-wire-debug-swd-interface) and set flash base address.  
   ```sh  
   // Enable MSC clock if device is xG23  
   if (buf0 == XG23_FAMILY) {  
   write_mem((uint32_t)&(CMU->CLKEN1_SET), CLKEN1_MSC_XG23);  
   // Check UDLOCKBIT on xG23  
   if (read_mem((uint32_t)&(MSC->MISCLOCKWORD)) & MSC_MISCLOCKWORD_UDLOCKBIT) {  
   RAISE(SWD_ERROR_USERDATA_LOCK);  
   }  
   // Flash start address for xG23  
   flash_start_addr = FLASH_BASE_XG23;  
   }  
   ```
4. Add `DEVICE_XG23` (ASCII code of character "3") to `app_process.h.` It is "1" for xG21, "2" for xG22, "3" for xG23, etc.  
   ```sh  
   /// xG23 device  
   #define DEVICE_XG23 (0x33)  
   ```
5. The [hse_svm_conf[]](06-series-2-dci-and-swd-programming-examples#otp-settings) can apply to xG23A (HSE-SVM) devices. Add || `defined(DEVICE_XG23)` to `hse_svm_conf[]` in `app_dci_ta sk.c.`  
   ```sh  
   #if defined(DEVICE_XG21) || defined(DEVICE_XG23)  
   /// HSE-SVM user configuration  
   static const uint32_t hse_svm_conf[HSE_USER_CONF_SIZE] = {  
   0x00000018, // 24 bytes data below  
   SECURE_BOOT_ENABLE_MASK + ANTI_ROLLBACK_MASK, // MCU settings  
   0x00000000, // 20 bytes reserved data  
   0x00000000,  
   0x00000000,  
   0x00000000,  
   0x00000000  
   };  
   #endif  
   ```
6. The [hse_svh_xg21b_conf[]](06-series-2-dci-and-swd-programming-examples#otp-settings) cannot apply to xG23B (HSE-SVH) devices. Add [hse_svh_other_conf[]](06-series-2-dci-and-swd-programming-examples#otp-settings) to `app_dci_task.c.`  
   ```sh  
   #if defined(DEVICE_XG23)  
   /// Other HSE-SVH user configuration  
   static const uint32_t hse_svh_other_conf[HSE_USER_CONF_SIZE] = {  
   0x00000018, // 24 bytes data below  
   SECURE_BOOT_ENABLE_MASK + ANTI_ROLLBACK_MASK, // MCU settings  
   0x40440410, // Tamper settings  
   0x14040104,  
   0x22414224,  
   0x74422112,  
   0x0500060A  
   };  
   #endif  
   ```
7. Add code (based on `case DEVICE_XG21:`, replace `hse_svh_xg21b_conf` with `hse_svh_other_conf`) to `app_dci_task.c` to set up a command buffer for [OTP configuration](05-se-command-list#initialize-otp).  
   ```sh  
   #if defined(DEVICE_XG23)  
   case DEVICE_XG23:  
   // Check SVM or SVH  
   if (*(cmd_buf + 2) == 'A') {  
   *cmd_buf = INIT_HSE_OTP_LENGTH;  
   *(++cmd_buf) = COMMAND_INIT_OTP;  
   // Calculate parity of OTP configuration  
   *(++cmd_buf) = 0;  
   for (i = 1; i < HSE_USER_CONF_SIZE; i++) {  
   *cmd_buf ^= hse_svm_conf[i];  
   }  
   // Copy OTP configuration to buffer  
   memcpy((uint32_t *)(++cmd_buf), (uint32_t *)hse_svm_conf,  
   INIT_HSE_OTP_LENGTH);  
   } else if (*(cmd_buf + 2) == 'B') {  
   *cmd_buf = INIT_HSE_OTP_LENGTH;  
   *(++cmd_buf) = COMMAND_INIT_OTP;  
   // Calculate parity of OTP configuration  
   *(++cmd_buf) = 0;  
   for (i = 1; i < HSE_USER_CONF_SIZE; i++) {  
   *cmd_buf ^= hse_svh_other_conf[i];  
   }  
   // Copy OTP configuration to buffer  
   memcpy((uint32_t *)(++cmd_buf), (uint32_t *)hse_svh_other_conf,  
   INIT_HSE_OTP_LENGTH);  
   } else {  
   RAISE(SWD_ERROR_UNKNOWN_DEVICE);  
   }  
   break;  
   #endif  
   ```
8. Add [firmware images](06-series-2-dci-and-swd-programming-examples#firmware-images) to `app_firmware_image.c` and `app_firmware_image.h.`  
   ![Add firmware image](/efr32-dci-swd-programming/0.1/images/sld815-image21.png)
9. Add functions to `app_firmware_image.c` and `app_firmware_image.h` to get the address and size of firmware images.  
   ![Add functions](/efr32-dci-swd-programming/0.1/images/sld815-image22.png)
10. The `tamper_source_xg21b[]` cannot be applied to xG23B (HSE-SVH) devices. Add `tamper_source_other[]` to `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    /// Strings for tamper sources of other HSE-SVH devices  
    static const char *tamper_source_other[TAMPER_SIGNAL_NUM] = {  
    NULL,  
    "Filter counter : ",  
    "SE watchdog : ",  
    NULL,  
    "SE RAM ECC 2 : ",  
    "SE hard fault : ",  
    NULL,  
    "SE software assertion : ",  
    "SE secure boot : ",  
    "User secure boot : ",  
    "Mailbox authorization : ",  
    "DCI authorization : ",  
    "OTP Read : ",  
    NULL,  
    "Self test : ",  
    "TRNG monitor : ",  
    "Secure lock : ",  
    "Digital glitch : ",  
    "Voltage glitch : ",  
    "SE ICACHE : ",  
    "SE RAM ECC 1 : ",  
    "BOD : ",  
    "Temperature sensor : ",  
    "DPLL lock fail low : ",  
    "DPLL lock fail high : ",  
    "PRS0 : ",  
    "PRS1 : ",  
    "PRS2 : ",  
    "PRS3 : ",  
    "PRS4 : ",  
    "PRS5 : ",  
    "PRS6 : "  
    };  
    #endif  
    ```
11. Add  || `defined(DEVICE_XG23)` and  code  (based  on  `case DEVICE_XG21:`,  replace  `tamper_source_xg21b` with `tamper_source_other`) to function `print_otp_conf()` in `app_process.c` to print out the [tamper configuration](05-se-command-list#anti-tamper-configuration).  
    ```sh  
    #if defined(DEVICE_XG21) || defined(DEVICE_XG23)  
    uint32_t i;  
    uint32_t j;  
    uint32_t k;  
    #endif  
    ...  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    for (i = 0, j = 0, k = 2; i < TAMPER_SIGNAL_NUM; i++, j += 4) {  
    if (j == 32) {  
    j = 0;  
    k++;  
    }  
    cmd_resp_buf[8] = (cmd_resp_buf[k] >> j) & 0x0f;  
    if (tamper_source_other[i] != NULL) {  
    printf(" %s %lu\n", tamper_source_other[i], cmd_resp_buf[8]);  
    }  
    }  
    break;  
    #endif  
    ...  
    #if defined(DEVICE_XG21) || defined(DEVICE_XG23)  
    // Common tamper parameters  
    printf(" + Reset period for the tamper filter counter: ~32 ms x %u\n",  
    1 << (cmd_resp_buf[6] & COUNTER_PERIOD_MASK));  
    printf(" + Activation threshold for the tamper filter: %d\n",  
    256 / (1 << ((cmd_resp_buf[6] & COUNTER_THRESHOLD_MASK) >> COUNTER_THRESHOLD_SHIFT)));  
    if (cmd_resp_buf[6] & GLITCH_DETECTOR_MASK) {  
    printf(" + Digital glitch detector always on: Enabled\n");  
    } else {  
    printf(" + Digital glitch detector always on: Disabled\n");  
    }  
    if (device_name[DEVICE_INDEX] > DEVICE_XG22) {  
    if (cmd_resp_buf[6] & SLEEP_ALIVE_MASK) {  
    printf(" + Keep tamper alive during sleep: Enabled\n");  
    } else {  
    printf(" + Keep tamper alive during sleep: Disabled\n");  
    }  
    }  
    printf(" + Tamper reset threshold: %lu\n", cmd_resp_buf[6] >> TAMPER_RESET_SHIFT);  
    #endif  
    ```
12. Add code (take `case DEVICE_XG21:` as reference) to function `prog_main_flash_app()` in `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    printf(" + The xG23 application firmware image size is %lu bytes "  
    "and start address is 0x%08lX.\n", get_xg23_app_size(),  
    get_flash_start_addr());  
    printf(" + Erase-Program-Verify the xG23 main flash for "  
    "application firmware image... ");  
    cmd_resp_buf[0] = prog_flash(get_flash_start_addr(),  
    get_xg23_app_size(),  
    (uint32_t *)get_xg23_app_addr());  
    print_cycle_time();  
    break;  
    #endif  
    ```
13. Add code (take `case DEVICE_XG21:` as reference) to function `prog_main_flash_se()` in `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    printf(" + The xG23 HSE firmware image version: %08lX\n",  
    *((uint32_t *)get_xg23_hse_addr() + 3));  
    printf(" + The xG23 HSE firmware image size is %lu bytes and start "  
    "address is 0x%08lX.\n", get_xg23_hse_size(),  
    SE_START_ADDR + get_flash_start_addr());  
    printf(" + Erase-Program-Verify the xG23 main flash for HSE "  
    "firmware image... ");  
    cmd_resp_buf[0] = prog_flash(SE_START_ADDR + get_flash_start_addr(),  
    get_xg23_hse_size(),  
    (uint32_t *)get_xg23_hse_addr());  
    print_cycle_time();  
    break;  
    #endif  
    ```
14. Add code (take `case DEVICE_XG21:` as reference) to function `prog_main_flash_se_app()` in `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    printf(" + The xG23 HSE upgrade application firmware image size is "  
    "%lu bytes and start address is 0x%08lX.\n",  
    get_xg23_hse_upgrade_app_size(), get_flash_start_addr());  
    printf(" + Erase-Program-Verify the xG23 main flash for "  
    "application to upgrade \n");  
    printf(" HSE firmware... ");  
    cmd_resp_buf[0] = prog_flash(get_flash_start_addr(),  
    get_xg23_hse_upgrade_app_size(),  
    (uint32_t *)get_xg23_hse_upgrade_app_addr());  
    print_cycle_time();  
    break;  
    #endif  
    ```
15. Add code (take `case DEVICE_XG21:` as reference) to function `prog_main_flash_signed()` in `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    printf(" + The xG23 signed firmware image size is %lu bytes "  
    "and start address is 0x%08lX.\n",  
    get_xg23_signed_size(),  
    get_flash_start_addr());  
    printf(" + Erase-Program-Verify the xG23 main flash for "  
    "signed firmware image... ");  
    cmd_resp_buf[0] = prog_flash(get_flash_start_addr(),  
    get_xg23_signed_size(),  
    (uint32_t *)get_xg23_signed_addr());  
    print_cycle_time();  
    break;  
    #endif  
    ```
16. For xG23 devices, the user data can be erased the same way as any page in the main flash. Add code (take `case DEVICE_XG22:` as reference) to function `erase_user_data()` in `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    printf("\n . Erase xG23 user data... ");  
    cmd_resp_buf[0] = erase_flash(true);  
    print_cycle_time();  
    hard_reset_target();  
    break;  
    #endif  
    ```
17. For xG23 devices, the user data can be written the same way as any page in the main flash. Add code (take `case DEVICE_XG22:` as reference) to function `prog_user_data()` in `app_process.c.`  
    ```sh  
    #if defined(DEVICE_XG23)  
    case DEVICE_XG23:  
    printf("\n . Program xG23 user data.\n");  
    printf(" + User data size is %lu bytes and start address is 0x%08lX.\n",  
    get_userdata_size(), USERDATA_BASE);  
    printf(" + Erase-Program-Verify the xG23 user data... ");  
    cmd_resp_buf[0] = prog_flash(USERDATA_BASE,  
    get_userdata_size(),  
    (uint32_t *)get_userdata_addr());  
    print_cycle_time();  
    hard_reset_target();  
    break;  
    #endif  
    ```
18. There is no need to change the default settings in [Compile Options](06-series-2-dci-and-swd-programming-examples#compile-options) for xG23 devices.  
    > **Note**: The 512 kB flash of EFR32MG22C224F512 is not enough to store the [firmware images](06-series-2-dci-and-swd-programming-examples#firmware-images) when the programmer needs to support more Series 2 devices. Users can selectively comment out the defines in `app_process.h` to save memory for the required Series 2 devices.  
    ```sh  
    /// xG21 device  
    #define DEVICE_XG21 (0x31)  
      
    /// xG22 device  
    define DEVICE_XG22 (0x32)  
      
    /// xG23 device  
    #define DEVICE_XG23 (0x33)  
      
    ```

##### Use J-Link Commander to Run DCI Command

J-Link Commander from [Segger](https://www.segger.com/downloads/jlink/) is a command line-based utility that supports simple commands to verify and communicate with the target connection. There are two ways to run the DCI command through the J-Link Commander.

1. [J-Link Command File](https://wiki.segger.com/J-Link_Commander#Using_J-Link_Command_Files) (*.jlink)
2. [J-Link Script File](https://wiki.segger.com/J-Link_script_files#Using_J-Link_script_files) (*.JLinkScript)

This application note uses J-Link Commander v7.66g. The J-Link Commander's command line interface is invoked by JLink.exe located in `C:\Program Files\SEGGER\JLink_V766g` (Windows).

###### J-Link Command File (heading level 7)

The J-Link Command file below is an example to invoke the J-Link Commander in batch processing mode for the [Erase Device](05-se-command-list) operation. The delay (`sleep 500`) in milliseconds after writing the command word is device dependent. It may be shorter or longer.

```sh
connect
swdwritedp 2 0x01000000 ; Select DCI AP
swdwriteap 1 0x1008 ; DCI STATUS
swdreadap 3 
swdreaddp 3 ; Poll till DCI_STATUS.WPENDING (bit 0) is low
swdwriteap 1 0x1000 ; DCI WDATA
swdwriteap 3 0x08 ; Command word 0
sleep 500 ; Delay if necessary
swdwriteap 1 0x1008 ; DCI STATUS
swdreadap 3 
swdreaddp 3 ; Poll till DCI_STATUS.WPENDING (bit 0) is low
swdwriteap 1 0x1000 ; DCI WDATA
swdwriteap 3 0x430F0000 ; command word 1 (Erase Device)
sleep 500 ; Delay if necessary
swdwriteap 1 0x1008 ; DCI STATUS
swdreadap 3 
swdreaddp 3 ; Poll till DCI_STATUS.RDATAVALID (bit 8) is high
swdwriteap 1 0x1004 ; DCI RDATA
swdreadap 3 ; First word
swdreaddp 3 ; Status code is upper 16 bits, total length is lower 16 bits
exit
```

The example below is to run the J-Link Command file (assume `EraseDevice.jlink` is in the J-Link Commander folder) via the Windows DOS command prompt. The target device is EFR32MG21A, and the target interface is 1000 kHz SWD. The SWD speed is hardware dependent; for example, the length of the wires between the programmer and the device debug pins. The speed (frequency) can be higher for shorter wires and lower for longer wires.

```sh
JLink.exe -device EFR32MG21AXXXF1024 -if SWD -speed 1000 -CommandFile EraseDevice.jlink
```

```sh
SEGGER J-Link Commander V7.66g (Compiled Jul 7 2022 10:44:29)
DLL version V7.66g, compiled Jul 7 2022 10:42:43
J-Link Command File read successfully.
Processing script file...
J-Link>connect
J-Link connection not established yet but required for command.
Connecting to J-Link via USB...O.K.
Firmware: Silicon Labs J-Link Pro OB compiled Sep 16 2020 17:10:58
Hardware version: V4.00
S/N: 440048205
License(s): RDI, FlashBP
IP-Addr: DHCP (no addr. received yet)
VTref=3.326V
Device "EFR32MG21AXXXF1024" selected.
Connecting to target via SWD
Found SW-DP with ID 0x6BA02477
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[3]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x84770001)
AP[1]: APB-AP (IDR: 0x54770002)
AP[2]: AHB-AP (IDR: 0x84770001)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FE000
CPUID register: 0x410FD213. Implementer code: 0x41 (ARM)
Feature set: Mainline
Found Cortex-M33 r0p3, Little endian.
FPUnit: 8 code (BP) slots and 0 literal slots
Security extension: implemented
Secure debug: enabled
CoreSight components:
ROMTbl[0] @ E00FE000
[0][0]: E00FF000 CID B105100D PID 000BB4C9 ROM Table
ROMTbl[1] @ E00FF000
[1][0]: E000E000 CID B105900D PID 000BBD21 DEVARCH 47702A04 DEVTYPE 00 Cortex-M33
[1][1]: E0001000 CID B105900D PID 000BBD21 DEVARCH 47701A02 DEVTYPE 00 DWT
[1][2]: E0002000 CID B105900D PID 000BBD21 DEVARCH 47701A03 DEVTYPE 00 FPB
[1][3]: E0000000 CID B105900D PID 000BBD21 DEVARCH 47701A01 DEVTYPE 43 ITM
[1][5]: E0041000 CID B105900D PID 002BBD21 DEVARCH 47724A13 DEVTYPE 13 ETM
[1][6]: E0042000 CID B105900D PID 000BBD21 DEVARCH 47701A14 DEVTYPE 14 CSS600-CTI
[0][1]: E0040000 CID B105900D PID 000BBD21 DEVARCH 00000000 DEVTYPE 11 Cortex-M33
[0][2]: E00FD000 CID B105F00D PID 001BB101 TSG
Cortex-M33 identified.
J-Link>swdwritedp 2 0x01000000 ; Select DCI AP
Write DP register 2 = 0x01000000
J-Link>swdwriteap 1 0x1008 ; DCI STATUS
Write AP register 1 = 0x00001008
J-Link>swdreadap 3
Read AP register 3 = 0x000000B1
J-Link>swdreaddp 3 ; Poll till DCI_STATUS.WPENDING (bit 0) is low
Read DP register 3 = 0x00000000
J-Link>swdwriteap 1 0x1000 ; DCI WDATA
Write AP register 1 = 0x00001000
J-Link>swdwriteap 3 0x08 ; Command word 0
Write AP register 3 = 0x00000008
J-Link>sleep 500 ; Delay if necessary
Sleep(500)
J-Link>swdwriteap 1 0x1008 ; DCI STATUS
Write AP register 1 = 0x00001008
J-Link>swdreadap 3
Read AP register 3 = 0x00000000
J-Link>swdreaddp 3 ; Poll till DCI_STATUS.WPENDING (bit 0) is low
Read DP register 3 = 0x00000000
J-Link>swdwriteap 1 0x1000 ; DCI WDATA
Write AP register 1 = 0x00001000
J-Link>swdwriteap 3 0x430F0000 ; command word 1 (Erase Device)
Write AP register 3 = 0x430F0000
J-Link>sleep 500 ; Delay if necessary
Sleep(500)
J-Link>swdwriteap 1 0x1008 ; DCI STATUS
Write AP register 1 = 0x00001008
J-Link>swdreadap 3
Read AP register 3 = 0x00000000
J-Link>swdreaddp 3 ; Poll till DCI_STATUS.RDATAVALID (bit 8) is high
Read DP register 3 = 0x00000100
J-Link>swdwriteap 1 0x1004 ; DCI RDATA
Write AP register 1 = 0x00001004
J-Link>swdreadap 3 ; First word
Read AP register 3 = 0x00000100
J-Link>swdreaddp 3 ; Status code is upper 16 bits, total length is lower 16 bits
Read DP register 3 = 0x00000004
J-Link>exit
Script processing completed.
```

###### J-Link Script File (heading level 7)

The J-Link Script file below is an example to customize some actions performed by the J-Link Commander for the [Read Serial Number](05-se-command-list#read-serial-number) operation.

```sh
// Function to select DCI AP register bank 0
int SelectDciAp(void)
{
 int stat;
 int value;
 JLINK_SYS_Report("- Select DCI AP register bank 0\n");
 value = 0x01000000; 
 stat = JLINK_CORESIGHT_WriteDP(2, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- DP 2 write failed: ", value);
 }
 return stat;
}
// Function to write command to DCI_WDATA (0x1000) 
int WriteCommandWord(int command)
{
 int stat;
 int value;
 // Poll DCI_STATUS (0x1008) WPENDING bit (bit 0)
 do {
 value = 0x00001008;
 stat = JLINK_CORESIGHT_WriteAP(1, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 1 write failed: ", value);
 return stat;
 }
 JLINK_CORESIGHT_ReadAP(3);
 value = JLINK_CORESIGHT_ReadDP(3);
 if (value == -1) {
 JLINK_SYS_Report("- DP 3 read failed");
 return value;
 }
 if ((value & 0x0100) != 0) {
 JLINK_SYS_Report("- RDATAVALID is high, command aborted");
 return -1;
 } 
 } while ((value & 0x01) != 0);
 
 // Write command
 value = 0x00001000;
 stat = JLINK_CORESIGHT_WriteAP(1, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 1 write failed: ", value);
 return stat;
 }
 value = command;
 stat = JLINK_CORESIGHT_WriteAP(3, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 3 write failed: ", value);
 return stat;
 }
 JLINK_SYS_Report1("- Write command word ", command); 
 return stat;
}
// Function to read response from DCI_RDATA (0x1004)
int ReadResponse(void)
{
 int stat;
 int value;
 int count;
// Poll DCI_STATUS (0x1008) RDATAVALID bit (bit 8) 
 do {
 value = 0x00001008;
 stat = JLINK_CORESIGHT_WriteAP(1, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 1 write failed: ", value);
 return stat;
 }
 JLINK_CORESIGHT_ReadAP(3);
 value = JLINK_CORESIGHT_ReadDP(3);
 if (value == -1) {
 JLINK_SYS_Report("- DP 3 read failed");
 return value;
 }
 } while ((value & 0x0100) != 0x0100);
 
 // Read first 32-bit response word 
 value = 0x00001004;
 stat = JLINK_CORESIGHT_WriteAP(1, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 1 write failed: ", value);
 return stat;
 }
 JLINK_CORESIGHT_ReadAP(3);
 value = JLINK_CORESIGHT_ReadDP(3);
 if (value == -1) {
 JLINK_SYS_Report("- DP 3 read failed");
 return value;
 }
 // Get response count
 count = value & 0x00FF; 
 count = count >> 2;
 JLINK_SYS_Report1("- Number of 32-bit response word: ", count);
 // Get response code
 JLINK_SYS_Report1("- Response: ", value);
 stat = value >>16; 
 if (stat != 0) {
 JLINK_SYS_Report1("- Command error: ", stat);
 return -1;
 }
 
 // Read following 32-bit response word
 count = count - 1;
 while (count != 0) {
 // Poll DCI_STATUS (0x1008) RDATAVALID bit (bit 8) 
 do {
 value = 0x00001008;
 stat = JLINK_CORESIGHT_WriteAP(1, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 1 write failed: ", value);
 return stat;
 }
 JLINK_CORESIGHT_ReadAP(3);
 value = JLINK_CORESIGHT_ReadDP(3);
 if (value == -1) {
 JLINK_SYS_Report("- DP 3 read failed");
 return value;
 }
 } while ((value & 0x0100) != 0x0100);
 
 // Read 32-bit response word 
 value = 0x00001004;
 stat = JLINK_CORESIGHT_WriteAP(1, value);
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 1 write failed: ", value);
 return stat;
  }
 JLINK_CORESIGHT_ReadAP(3);
 value = JLINK_CORESIGHT_ReadDP(3);
 if (value == -1) {
 JLINK_SYS_Report("- DP 3 read failed");
 return value;
 }
 JLINK_SYS_Report1("- Response: ", value);
 count = count - 1;
 }
 return 0;
}
// Function to connect DCI
int ConnectDci(void)
{ 
 int stat;
 int value;
 
 JLINK_SYS_Report("\n******************************************************");
 JLINK_SYS_Report("Connect to Series 2 Device DCI\n");
 JLINK_SYS_Report("- Select SWD by sending SWD switching sequence\n");
 stat = JLINK_CORESIGHT_Configure(""); 
 if (stat < 0) {
 JLINK_SYS_Report("- SWD connection failed");
 return stat;
 }
 // Manually select debug interface 
 JLINK_SYS_Report("- Clear sticky error flags\n");
 value = 0x0000001E; 
 stat = JLINK_CORESIGHT_WriteDP(0, value); 
 if (stat < 0) {
 JLINK_SYS_Report1("- DP 0 write failed: ", value);
 return stat;
 }
 JLINK_SYS_Report("- Power up system and debug\n");
 value = 0x50000000; 
 stat = JLINK_CORESIGHT_WriteDP(1, value); 
 if (stat < 0) {
 JLINK_SYS_Report1("- DP 1 write failed: ", value);
 return stat;
 }
 
 value = JLINK_CORESIGHT_ReadDP(0); 
 if (value != 0x6BA02477) {
 JLINK_SYS_Report1("- The connected device does not have a Secure Element (ID Code): ", value);
 return -1;
 }
 JLINK_SYS_Report1("- Read SWD-DP ID code: ", value);
 JLINK_SYS_Report("- Select DCI AP register bank 0\n");
 value = 0x01000000; 
 stat = JLINK_CORESIGHT_WriteDP(2, value); 
 if (stat < 0) {
 JLINK_SYS_Report1("- DP 2 write failed: ", value);
 return stat;
 }
 
 JLINK_SYS_Report("- Set up AP defaults\n");
 value = 0x22000002; 
 stat = JLINK_CORESIGHT_WriteAP(0, value); 
 if (stat < 0) {
 JLINK_SYS_Report1("- AP 0 write failed: ", value); 
 return stat;
 }
 JLINK_SYS_Report("Connect to Series 2 Device DCI OK\n");
 JLINK_SYS_Report("******************************************************");
 return 0;
}
// Function to run DCI command
void RunDciCommand(void)
{
 JLINK_SYS_Report("\n******************************************************");
 JLINK_SYS_Report("Read Serial Number\n");
 if (SelectDciAp() == -1) {
 JLINK_SYS_Report("- Select DCI AP failed\n");
 JLINK_SYS_Report("******************************************************\n\n");
 return;
 }
 if (WriteCommandWord(0x00000008) == -1) {
 JLINK_SYS_Report("- Write DCI command (length) failed\n");
 JLINK_SYS_Report("******************************************************\n\n");
 return;
 }
 if (WriteCommandWord(0xFE000000) == -1) {
 JLINK_SYS_Report("- Write DCI command (ID) failed\n");
 JLINK_SYS_Report("******************************************************\n\n");
 return;
 }
 if (ReadResponse() == -1) {
 JLINK_SYS_Report("- Read DCI command response failed\n");
 JLINK_SYS_Report("******************************************************\n\n");
 return;
 }
 JLINK_SYS_Report("Read Serial Number Done\n");
 JLINK_SYS_Report("******************************************************\n\n");
}
// Replace ConfigTargetSettings() in J-Link DLL
void ConfigTargetSettings(void)
{
 if (ConnectDci() == -1) {
 JLINK_SYS_Report("- Connect to DCI failed\n");
 JLINK_SYS_Report("******************************************************\n\n");
 return;
 }
 RunDciCommand();
}
```

The example below is to run the J-Link Script file (assume `ReadSerialNo.JLinkScript` is in the J-Link Commander folder) via the Windows DOS command prompt. The target device is EFR32MG21A, and the target interface is 1000 kHz SWD. The SWD speed is hardware dependent; for example, the length of the wires between the programmer and the device debug pins. It can be higher for shorter wires and lower for longer wires.

```sh
JLink -device EFR32MG21AXXXF1024 -if SWD -speed 1000 -autoConnect 1 -JLinkScriptFile ReadSerialNo.JlinkScript

```

```sh
SEGGER J-Link Commander V7.66g (Compiled Jul 7 2022 10:44:29)
DLL version V7.66g, compiled Jul 7 2022 10:42:43
Connecting to J-Link via USB...O.K.
Firmware: Silicon Labs J-Link Pro OB compiled Sep 16 2020 17:10:58
Hardware version: V4.00
S/N: 440048205
License(s): RDI, FlashBP
IP-Addr: DHCP (no addr. received yet)
VTref=3.328V
Device "EFR32MG21AXXXF1024" selected.
Connecting to target via SWD
ConfigTargetSettings() start
******************************************************
Connect to Series 2 Device DCI
- Select SWD by sending SWD switching sequence
- Clear sticky error flags
- Power up system and debug
- Read SWD-DP ID code: 0x6BA02477
- Select DCI AP register bank 0
- Set up AP defaults
```

```sh
Connect to Series 2 Device DCI OK
******************************************************
******************************************************
Read Serial Number
- Select DCI AP register bank 0
- Write command word 0x00000008
- Write command word 0xFE000000
- Number of 32-bit response word: 0x00000005
- Response: 0x00000014
- Response: 0x00000000
- Response: 0x00000000
- Response: 0xFF818E58
- Response: 0xE53470FE
Read Serial Number Done
******************************************************
ConfigTargetSettings() end
```

#### Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS

##### Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS

> **Note: This section replaces _AN1311: Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS_. Further updates to this application note will be provided here**.

This application note describes how to integrate crypto functionality into applications using PSA Crypto compared to Mbed TLS. It includes a guide to migrating existing Mbed TLS implementations to PSA Crypto.

This document focuses on the Silicon Labs PSA Crypto implementations that support the RNG, symmetric and asymmetric keys, message digests, MAC, unauthenticated ciphers, AEAD, KDF, DSA, and ECDH.

This document assumes familiarity with the crypto algorithms discussed.

###### Key Points

- Overview of Mbed TLS and PSA Crypto
- Key management in PSA Crypto
- Migration guide
- PSA Crypto platform examples

##### Series 2 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level (1)**|**SE Support**|**Part (2)**|
|---|---|---|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|Refer to _IoT Endpoint Security Fundamentals_ for details on supporting devices.|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|"|
|"|VSE (VSE-SVM)|"|
|Secure Vault Base (SVB)|N/A|"|

> **Notes**:
> 
> 1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).
> 2. [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/).

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th><strong>Document</strong></th>
            <th><strong>Summary</strong></th>
            <th><strong>Applicability</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|

###### SE Firmware

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 devices and modules.

##### Device Capability

The following table lists the hardware related to cryptography hardware acceleration features on Series 1 and Series 2 devices (MCU and Wireless SoC).

|**Feature**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|
|---|---|---|---|
|TRNG|TRNG peripheral (1)|CRYPTOACC peripheral|HSE|
|Crypto Engine (2)|CRYPTO peripheral|CRYPTOACC peripheral|HSE|
|Advanced Crypto (3)|—|—|HSE-SVH|
|Secure Key Storage (4)|—|—|HSE-SVH|

> **Notes**:
> 
> 1. See [Table Entropy Source on Series 1 and Series 2 Devices](06-migration-guide#initialization-and-random-number-generation-rng) for details of TRNG (True Random Number Generator) on Series 1 devices.
> 2. Crypto engine supports up to 256-bit ciphers and elliptic curves.
> 3. Advanced crypto supports up to 512-bit ciphers and 521-bit elliptic curves.
> 4. See [Table PSA Crypto Key Lifetime Support on Series 1 and Series 2 Devices](04-key-management-in-psa-crypto#key-lifetimes) for details of Secure Key Storage support on HSE-SVH devices.

##### Overview

###### Mbed TLS

Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation, and the SSL/TLS and DTLS protocols.

ARM developed Mbed TLS, which was formerly known as PolarSSL. Mbed TLS has been handed over to [Trusted Firmware](https://www.trustedfirmware.org/projects/mbed-tls/) under open governance since March 2020.

For the time being, Trusted Firmware Mbed TLS is the project containing a reference implementation of the PSA Crypto API and the TLS portion of Mbed TLS. The following table lists different Mbed TLS versions supported in Simplicity Studio and Gecko SDK (GSDK) suites.

|**Mbed TLS**|**Gecko SDK Suite**|**PSA Crypto**|**Location in Windows**|
|---|---|---|---|
|v3.2.1|v4.3.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\mbedtls|
|v3.2.1|v4.2.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\mbedtls|
|v3.1.0|v4.1.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\mbedtls|
|v3.0.0|v4.0.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\mbedtls|
|v2.26.0|v3.2.x (Simplicity Studio 5)|Y|C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.2\util\third_party\crypto\mbedtls|
|v2.24.0|v3.1.x (Simplicity Studio 5)|Y|C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.1\util\third_party\crypto\mbedtls|
|v2.16.6|v3.0.x (Simplicity Studio 5)|—|C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.0\util\third_party\mbedtls|
|v2.7.12|v2.7.8 (Simplicity Studio 4)|—|C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.7\util\third_party\mbedtls|

###### PSA Crypto

**Platform Security Architecture (PSA)**

The [Platform Security Architecture](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) (PSA) is made up of four key stages:

- Threat modeling
- Predefined architectural choices
- Standardized implementation
- Certification

The PSA Crypto API is one of the standardized implementation features and is discussed in the following sections.

**PSA Root of Trust (PSA-RoT)**

For an IoT product to achieve its security goals, it must meet the requirements of one of the pillars known as Root of Trust. The following figure shows the four PSA-Certified key elements that make up the Root of Trust.

![Key Requirements of PSA-RoT](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image8.png)

The PSA Root of Trust (PSA-RoT) is a source of confidentiality (for example, crypto keys) and integrity. The PSA-RoT defines what it takes for a hardware or software system to be trusted.

The [Trusted Firmware-M](https://www.trustedfirmware.org/projects/tf-m/) (TF-M) offers an open-source firmware reference implementation and APIs. These resources provide developers with a trusted codebase that complies with PSA specifications and APIs that create a consistent interface to underlying Root of Trust hardware.

**PSA Functional APIs**

[PSA Certified](https://www.psacertified.org/) defines a set of PSA Functional APIs (which are implemented as part of TF-M) to access the Root of Trust features. The PSA Functional APIs provide a standardized set of vetted APIs to ensure portability and promote adherence to best practices.

- PSA Crypto APIs
- PSA Attestation APIs
- PSA Secure Storage (Internal Trusted Storage and Protected Storage) APIs

Since the Trusted boot (aka Secure boot) shown in [Figure Key Requirements of PSA-RoT](#psa-crypto) is used when booting up the device and is not used after the system is up and running, there is no need for a Trusted boot API.

The three APIs provide software developers with access to security functions to ensure interoperability across different hardware implementations of the Root of Trust. It means another hardware platform can reuse the applications in the following figure, because these APIs are standardized across various security hardware.

![PSA Functional APIs](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image9.png)

[PSA Functional API Certification](https://www.psacertified.org/getting-certified/functional-api-certification/) is part of [PSA Certified](https://www.psacertified.org/), and demonstrates that software is compatible with the PSA Functional API specification. PSA Functional API Certified does not imply that a device has a security capability or is robust. Only PSA Certified Levels 1–3 can achieve this.

This application note only focuses on the PSA Crypto API.

**PSA Crypto API**

The PSA Crypto API is a low-level cryptographic API optimized for MCU and Wireless SoC. It provides APIs related to [Random Number Generation](06-migration-guide#initialization-and-random-number-generation-rng) (RNG), cryptographic algorithm usage, and [key handling](06-migration-guide#key-handling) (symmetric and asymmetric).

The PSA Crypto API provides developers with an easy-to-use and easy-to-learn interface to crypto primitives. It is designed for usability and flexibility and is based on the idea of a key store. The store can isolate the keys from the rest of the applications, which means keys remain opaque in [storage](04-key-management-in-psa-crypto#key-lifetimes) and only accessible for usage through crypto primitives.

##### Key Management in PSA Crypto

Key attributes are managed in a `psa_key_attributes_t` object. These are used when a key is created, after which the key attributes are impossible to change.

The actual key material is not considered an attribute of a key. Key attributes do not contain information that is generally considered highly confidential. The individual attributes ([Key Types](#key-types), [Key Lifetimes](#key-lifetimes), [Key Identifiers](#key-identifiers), and [Key Policies](#key-policies)) are described in the following sections.

The `crypto_values.h` in the Windows folder below includes the defines for macros of key attributes.

For GSDK v3.1.x and v3.2.x: `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION\>\util\third_party\crypto\mbedtls\include\psa`

For GSDK v4.0.0 and higher: `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\mbedtls\include\psa`

###### Key Types

This attribute consists of information about the key: the type, and the size used by this type. The key type and size are encoded in

`psa_key_type_t` and `psa_key_bits_t` objects. The following table describes the type and size in symmetric and asymmetric keys.

<table>
    <thead>
        <tr>
            <th><strong>Category</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Size in Bits</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td rowspan="4">Symmetric Keys</td>
            <td>HMAC key<br>• <code>PSA_KEY_TYPE_HMAC</code></td>
            <td>Non-zero multiple of 8</td>
        </tr>
        <tr>
            <td>Key derivation<br>• <code>PSA_KEY_TYPE_DERIVE</code></td>
            <td>Non-zero multiple of 8</td>
        </tr>
        <tr>
            <td>Cipher/AEAD/MAC key<br>• <code>PSA_KEY_TYPE_AES</code></td>
            <td>
                <ul>
                    <li>128 (16-byte)</li>
                    <li>192 (24-byte)</li>
                    <li>256 (32-byte)</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>ChaCha20/ChaCha20-Poly1305 AEAD key<br>• <code>PSA_KEY_TYPE_CHACHA20</code></td>
            <td>256 (32-byte)</td>
        </tr>
        <tr>
            <td rowspan="4">Elliptic Curve Cryptography (ECC) Keys</td>
            <td>SEC random curves over prime fields<br>• <code>PSA_ECC_FAMILY_SECP_R1</code></td>
            <td>
                <ul>
                    <li>secp192r1 : 192</li>
                    <li>secp224r1 : 224</li>
                    <li>secp256r1 : 256</li>
                    <li>secp384r1 : 384</li>
                    <li>secp521r1 : 521</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>SEC Koblitz curve over prime fields<br>• <code>PSA_ECC_FAMILY_SECP_K1</code></td>
            <td>secp256k1 : 256</td>
        </tr>
        <tr>
            <td>Montgomery curves<br>• <code>PSA_ECC_FAMILY_MONTGOMERY</code></td>
            <td>
                <ul>
                    <li>Curve25519 : 255</li>
                    <li>Curve448 : 448</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>Twisted Edwards curve<br>• <code>PSA_ECC_FAMILY_TWISTED_EDWARDS</code></td>
            <td>Edwards25519 : 255</td>
        </tr>
    </tbody>
</table>

###### Key Lifetimes

The lifetime is encoded in the `psa_key_lifetime_t` object (`[31:0]`). This object consists of a persistence level (`psa_key_persistence_t`) and a location indicator (`psa_key_location_t`). The persistent level indicates whether the key is volatile, persistent, or read-only. The location indicator indicates where the key is stored and where operations on the key are performed.

|**Type**|**Persistence Level [7:0]**|**Location Indicator [31:8]**|**Storage**|
|---|---|---|---|
|Volatile Plain Key|PSA_KEY_PERSISTENCE_VOLATILE|Local (0x0)|RAM|
|Persistent Plain Key|PSA_KEY_PERSISTENCE_DEFAULT|Local (0x0)|Flash (2)|
|Volatile Wrapped Key|PSA_KEY_PERSISTENCE_VOLATILE|Secure (0x1) (1)|RAM|
|Persistent Wrapped Key|PSA_KEY_PERSISTENCE_DEFAULT|Secure (0x1) (1)|Flash (2)|
|Public Sign Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|Public Command Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|AES-128 Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|Private Device Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|PUF-derived Hardware Unique Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|PUF Module|

> **Notes**:
> 
> 1. If the key cannot be stored persistently inside the SE, it must be stored in a [wrapped form](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/) in RAM or flash such that only the SE can access the key material in plaintext.
> 2. Persistent storage in flash memory is implemented by the [NVM3 driver](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3).

|**Type**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|
|---|---|---|---|
|Volatile Plain Key|Y|Y|Y|
|Persistent Plain Key|Y|Y|Y|
|Volatile Wrapped Key|—|—|HSE-SVH|
|Persistent Wrapped Key|—|—|HSE-SVH|
|Public Sign Key|—|— (1)|Y (2)|
|Public Command Key|—|— (1)|Y (2)|
|AES-128 Key|—|—|Y (3)|
|Private Device Key|—|—|HSE-SVH (2)|
|PUF-derived Hardware Unique Key|—|Y (4)|—|

> **Notes**:
> 
> 1. The PSA Crypto cannot access the Public Sign Key and Public Command Key in the VSE-SVM OTP.
> 2. These keys can only be used for ECDSA (SECP256R1) precomputed hash operations.
> 3. This key can only be used for AES cipher operations. The `SL_SE_BUILTIN_KEY_AES128_ALG` in `sli_se_opaque_types.h` or `sl_psa_values.h` in the Windows folder below defines the default AES cipher algorithm (AES CTR) for this key.
> 
> For GSDK v3.1.x and v3.2.x (`sli_se_opaque_types.h`): `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION>\util\third_party\crypto\sl_component\sl_psa_driver\inc`
> 
> For GSDK v4.0.x (`sli_se_opaque_types.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\sl_component\sl_psa_driver\inc`
> 
> For GSDK v4.1.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\sl_component\sl_psa_driver\inc\public`
> 
> For GSDK v4.2.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_psa_driver\inc\public`
> 
> For GSDK v4.3.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_mbedtls_support\inc`
> 
> 1. The PUF-derived Hardware Unique Key is only available on VSE-SVM devices with a built-in PUF module (e.g., EFR32xG27C). This key can only be used by the [CRYPTOACC](02-device-capability#device-capability) peripheral for [Message Authentication Codes (MAC)](06-migration-guide#message-authentication-codes-mac) and [Key Derivation](06-migration-guide#key-derivation).
> 
> The `SL_CRYPTOACC_BUILTIN_KEY_PUF_ALG` in `sl_psa_values.h` in the Windows folder below defines the default algorithm (PBKDF2 CMAC) for this key.
> 
> For GSDK v4.3.x and higher: `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_compon ent\sl_mbedtls_support\inc`

###### Key Identifiers

A key identifier can be a permanent name for a persistent key, or a transient reference to a volatile key. Key identifiers are encoded in a

`psa_key_id_t` object. The identifier and [lifetime](#key-lifetimes) of a key indicate the location of the key in storage.

The `sli_se_opaque_types.h` or `sl_psa_values.h` in the Windows folder below includes the defines for SE key identifier macros.

For GSDK v3.1.x and v3.2.x (`sli_se_opaque_types.h`): `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\\<GSDK VERSION\>\util\third_party\crypto\sl_component\sl_psa_driver\inc`

For GSDK v4.0.x (`sli_se_opaque_types.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\ crypto\sl_component\sl_psa_driver\inc`

For GSDK v4.1.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\sl_component\sl_psa_driver\inc\public`

For GSDK v4.2.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_psa_driver\inc\public`

For GSDK v4.3.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_mbedtls_support\inc`

|**Type**|**Key Identifier (Key ID)**|**SE Key Identifier**|
|---|---|---|
|Volatile Plain Key|0 (Assigned by the PSA Crypto)|—|
|Persistent Plain Key|PSA_KEY_ID_USER_MIN to PSA_KEY_ID_USER_MAX|—|
|Volatile Wrapped Key|0 (Assigned by the PSA Crypto)|—|
|Persistent Wrapped Key|PSA_KEY_ID_USER_MIN to PSA_KEY_ID_USER_MAX|—|
|Public Sign Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_SECUREBOOT_ID|
|Public Command Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_SECUREDEBUG_ID|
|AES-128 Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_AES128_ID|
|Private Device Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID|
|PUF-derived Hardware Unique Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_CRYPTOACC_BUILTIN_KEY_PUF_ID (GSDK ≥ v4.3.0)|

If users are about to use the PSA Crypto for persistent key storage in their application, adhere to the identifier (Key ID) allocation below. The value 0 is reserved as an invalid key identifier.

![image-10](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image10.png)

###### Key Policies

This attribute consists of usage flags and a specification of the permitted algorithm. The `psa_key_usage_t` encodes the usage flags in a bit-mask. The following table describes three kinds of usage flag in the PSA Crypto.

<table>
    <thead>
        <tr>
            <th><strong>Flag</strong></th>
            <th><strong>Bit-mask</strong></th>
            <th><strong>Description</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Extractable</td>
            <td>PSA_KEY_USAGE_EXPORT</td>
            <td>Permission to export the key.</td>
        </tr>
        <tr>
            <td>Copyable</td>
            <td>PSA_KEY_USAGE_COPY</td>
            <td>Permission to copy the key.</td>
        </tr>
        <tr>
            <td>Other usage</td>
            <td>PSA_KEY_USAGE_ENCRYPT</td>
            <td>Permission for a symmetric encryption operation, for an AEAD encryption-and-authentication operation, or for an asymmetric encryption operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_DECRYPT</td>
            <td>Permission for a symmetric decryption operation, for an AEAD decryption-and-verification operation, or for an asymmetric decryption operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_SIGN_MESSAGE</td>
            <td>Permission for a MAC calculation operation or for an asymmetric message signature operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_VERIFY_MESSAGE</td>
            <td>Permission for a MAC verification operation or for an asymmetric message signature verification operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_SIGN_HASH</td>
            <td>Permission to sign a message hash as part of an asymmetric signature operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_VERIFY_HASH</td>
            <td>Permission to verify a message hash as part of an asymmetric signature verification operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_DERIVE</td>
            <td>Permission to derive other keys from this key.</td>
        </tr>
    </tbody>
</table>

> **Note**: Users can always export a public key or the public part of a key pair regardless of the value of the `PSA_KEY_USAGE_EXPORT` ﬂag.

The `psa_algorithm_t` encodes the permitted algorithm with the key. The [Symmetric Cryptographic Operation](06-migration-guide#symmetric-cryptographic-operation) and [Asymmetric Cryptographic Operation](06-migration-guide#asymmetric-cryptographic-operation) describe which algorithms can apply to the corresponding cryptographic operations.

The application must supply the algorithm to use for the operation. This algorithm is checked against the permitted algorithm policy of the key.

###### Summary

The `psa_key_attributes_t` object specifies the attributes for the new key during the creation process. The attributes are immutable once the key has been created.

The key identifier and lifetime in the attributes determine the location of the key in storage. The application must set the key type and size, key algorithm policy, and the appropriate key usage flags in the attributes for the key to be used in any cryptographic operations.

The key material can be copied into a new key, which can have a different lifetime or a more restrictive usage policy.

If the key creation succeeds, the PSA Crypto will return an identifier for the newly created key. The PSA Crypto can destroy a key from volatile memory and non-volatile storage [NVM3 object](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3). The destroying process makes the key identifier invalid, and the key identifier must not be used again by the application until it is allocated to a newly created key.

If not necessary, the extractable usage flag (`PSA_KEY_USAGE_EXPORT`) should not be set to allow the key to export in binary format.

##### Key Attributes API

The following table lists the PSA Crypto API for the [key attributes](04-key-management-in-psa-crypto#key-management-in-psa-crypto).

<table>
    <thead>
        <tr>
            <th><strong>API</strong></th>
            <th><strong>Description</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><code>psa_key_attributes_init(…)</code></p>
            </td>
            <td>
                <p>Initialize the key attributes (<code>psa_key_attributes_t</code>) before calling any function.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_attributes(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key attributes (<code>psa_key_attributes_t</code>) of a key if successful.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_reset_key_attributes(…)</code></p>
            </td>
            <td>
                <p>Reset the key attributes (<code>psa_key_attributes_t</code>) to an initialized state.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_type(…)</code></p>
            </td>
            <td>
                <p>Declare the key type (<code>psa_key_type_t</code>) of a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_type(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key type (<code>psa_key_type_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_bits(…)</code></p>
            </td>
            <td>
                <p>Declare the key size (<code>psa_key_bits_t</code>) of a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_bits(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key size (<code>size_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_usage_flags(…)</code></p>
            </td>
            <td>
                <p>Declare the usage flags (<code>psa_key_usage_t</code>) for a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_usage_flags(…)</code></p>
            </td>
            <td>
                <p>Retrieve the usage flags (<code>psa_key_usage_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_algorithm(…)</code></p>
            </td>
            <td>
                <p>Declare the permitted algorithm policy (<code>psa_algorithm_t</code>) for a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_algorithm(…)</code></p>
            </td>
            <td>
                <p>Retrieve the algorithm policy (<code>psa_algorithm_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_id(…)</code></p>
            </td>
            <td>
                <p>Declare a key as persistent and set its key identifier (<code>psa_key_id_t</code>).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_id(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key identifier (<code>psa_key_id_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_lifetime(…)</code></p>
            </td>
            <td>
                <p>Set the location (<code>psa_key_lifetime_t</code>) of a persistent key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_lifetime(…)</code></p>
            </td>
            <td>
                <p>Retrieve the lifetime (<code>psa_key_lifetime_t</code>) from key attributes.</p>
            </td>
        </tr>
    </tbody>
</table>

The following sections describe how to use the key attributes API to set up the [storage](04-key-management-in-psa-crypto) for a key. Refer to the quick reference examples in [Symmetric Key](06-migration-guide#symmetric-key) and [Asymmetric Key](06-migration-guide#asymmetric-key) for more details.

**Volatile Plain Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>= 0</td>
            <td><code>PSA_KEY_PERSISTENCE_VOLATILE</code></td>
            <td>Local (0x0)</td>
            <td>
                It is the default setting after calling <code>psa_key_attributes_init()</code>.
                No need to call <code>psa_set_key_id()</code> and <code>psa_set_key_lifetime()</code>.
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
```

**Persistent Plain Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>&gt; 0</td>
            <td><code>PSA_KEY_PERSISTENCE_DEFAULT</code></td>
            <td>Local (0x0)</td>
            <td>
                A non-zero key ID in <code>psa_set_key_id()</code> will change the persistence level from <code>PSA_KEY_PERSISTENCE_VOLATILE</code> to <code>PSA_KEY_PERSISTENCE_DEFAULT</code>.
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
psa_set_key_id(&key_attr, 0x02);
```

**Volatile Wrapped Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>= 0</p>
            </td>
            <td>
                <p><code>PSA_KEY_PERSISTENCE_VOLATILE</code></p>
            </td>
            <td>
                <p>Secure (0x1)</p>
            </td>
            <td>
                <p>Use the <code>psa_set_key_lifetime()</code> to change the location indicator from Local to Secure (0x01).</p>
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, 0x01));
```

**Persistent Wrapped Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>&gt; 0</p>
            </td>
            <td>
                <p><code>PSA_KEY_PERSISTENCE_DEFAULT</code></p>
            </td>
            <td>
                <p>Local (0x0)</p>
            </td>
            <td>
                <p>A non-zero key ID in <code>psa_set_key_id()</code> will change the persistence level from <code>PSA_KEY_PERSISTENCE_VOLATILE</code> to <code>PSA_KEY_PERSISTENCE_DEFAULT</code>.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>&gt; 0</p>
            </td>
            <td>
                <p><code>PSA_KEY_PERSISTENCE_DEFAULT</code></p>
            </td>
            <td>
                <p>Secure (0x1)</p>
            </td>
            <td>
                <p>Use the <code>psa_set_key_lifetime()</code> to change the location indicator from Local to Secure (0x01).</p>
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
psa_set_key_id(&key_attr, 0x02);
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));
```

> **Note**:
> 
> - The `PSA_KEY_PERSISTENCE_DEFAULT` is equal to `PSA_KEY_LIFETIME_PERSISTENT`.
> - Refer to [Key Identifiers](04-key-management-in-psa-crypto#key-identifiers) for details about the Key ID.

##### Migration Guide

###### System Requirements and Document

1. Simplicity Studio 5
2. GSDK v3.1.1 (Mbed TLS v2.24.0) or later
3. The latest SE Firmware image and release note can be found in the Windows folder below.  
   - For GSDK v3.1.x and v3.2.x: `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION\>\util\se_release\public`  
   - For GSDK v4.0.0 and higher: `C:\Users\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public`
4. PSA Crypto API (aka PSA Cryptography API) document: [ARM](https://arm-software.github.io/psa-api/crypto/)

###### Mbed TLS Versus PSA Crypto API

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto API</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Key input</p>
            </td>
            <td>
                <p>APIs take key input directly.</p>
            </td>
            <td>
                <p>
                    • APIs do not take key input directly.<br>
                    • Key (identifier) needs to be created or imported before use.<br>
                    • APIs take an identifier if a key is required.
                </p>
            </td>
        </tr>
        <tr>
            <td rowspan="3">
                <p>Symmetric cryptographic operation</p>
            </td>
            <td>
                <p>Individual API (one-shot and streaming) for algorithm-specific functions.</p>
            </td>
            <td>
                <p>
                    • APIs are grouped by algorithm category for one-shot and streaming modes.<br>
                    • The exact algorithm is a parameter (<code>psa_algorithm_t</code>) to the function, not an individual API.
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Except for AEAD (encrypt and decrypt), a one-shot function is not in a pair.</p>
            </td>
            <td>
                <p>Single-part (one-shot) functions are in a pair. For example, compute and verify, or encrypt and decrypt.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Initialization and free a context are required.</p>
            </td>
            <td>
                <p>Initialization and abort an operation are only required in multi-part (streaming) operations.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Error code</p>
            </td>
            <td>
                <p>APIs always return an integer.</p>
            </td>
            <td>
                <p>APIs always return <code>psa_status_t</code>.</p>
            </td>
        </tr>
    </tbody>
</table>

###### Migration

In [Key Handling](#key-handling), [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation), [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) the following items will be considered when migrating from Mbed TLS to PSA Crypto.

1. The algorithms that can be used in a cryptographic operation.
2. The [key attributes](04-key-management-in-psa-crypto#key-management-in-psa-crypto) [type](04-key-management-in-psa-crypto#key-types) and [usage flags](04-key-management-in-psa-crypto#key-policies) for specific [algorithms](04-key-management-in-psa-crypto#key-policies) in the PSA Crypto.
3. Security Software Components.
4. The functions (APIs) for the Mbed TLS and PSA Crypto. For each type of [symmetric cryptographic operation](#symmetric-cryptographic-operation), the functions include:  
   - A pair of single-part (one-shot) functions  
   - A series of functions that implement multi-part (streaming) operations
5. Quick Reference Examples. These examples do not have error checking, but the user should always check the return code ([psa_status_t](https://docs.silabs.com/gecko-platform/latest/service/api/group-error) = `PSA_SUCCESS` or `PSA_ERROR_XXX`) from PSA Crypto to determine whether to use the output parameters in the application.

###### Platform Examples

Simplicity Studio 5 includes the PSA Crypto platform examples to evaluate the performance on [key handling](#key-handling), [symmetric](#symmetric-cryptographic-operation) and [asymmetric cryptographic operations](#asymmetric-cryptographic-operation), and [X.509 certificate](#x509-certificate).

- Refer to the corresponding `readme` file for details about each PSA Crypto platform example. This file also includes the procedures to create the project and run the example.
- Unless specified in the example, the PSA Crypto platform examples will use the software fallback feature in Mbed TLS if the [cryptography hardware accelerator](02-device-capability#device-capability) of the selected device does not support the corresponding ECC key or algorithm.

The figures in the following sections are based on GSDK v4.1.0. These figures may be different on other versions of the GSDK.

###### Security Software Components

The `slcp` file for each PSA Crypto platform example defines the software components installed in the project. The following figure shows the installed security software components (under the **Platform → Security** category) in the PSA Crypto ECDH example (`psa_crypto_ecdh.slcp`) on an HSE-SVH device.

![Installed Security Software Components](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image12.png)

The Simplicity IDE uses the installed security software components to automatically generate the configuration files for Mbed TLS (`mbedtls_config_autogen.h`) and PSA Crypto (`psa_crypto_config_autogen.h`) in the `autogen` folder when creating the project.

![Mbed TLS and PSA Crypto Configuration Files](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image13.png)

The user can browse the available security software components (under the **Platform → Security** category) on the target MCU or Wireless SoC if the [**Installed Components**] checkbox is unchecked.

![Available Security Software Components on the Target Device](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image14.png)

The Mbed TLS and PSA Crypto configuration files automatically regenerates when the user installs or uninstalls a security software component in the project.

![Install a Security Software Component](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image15.png)

![Uninstall a Security Software Component](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image16.png)

For a new project (like `empty.slcp`), the required security software components will be automatically added to the project after installing any cryptographic operation in PSA Crypto (like `GCM`) from the user. The `SE Manager` component is only for the HSE devices.

![Security Software Components for PSA Crypt](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image17.png)

If users are about to use the PSA Crypto for persistent key storage (either plain or wrapped) in their application, make sure to add the `PSA Persistent Storage Support (ITS)` component to the project.

![Security Software Component for Persistent Key Storage](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image18.png)

###### PSA Crypto Configuration

Click **Configuration** in **Installed Components**. Click [**Configure**] to open the Configuration Wizard in Context Menu.

![image19](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image19.png)

Enter the desired values in **PSA User Maximum Open Keys Count** (`SL_PSA_KEY_USER_SLOT_COUNT`) and **PSA Maximum User Persistent Keys Count** (`SL_PSA_ITS_USER_MAX_FILES`) to replace the default values. Click [**X**] to exit.

The default value of **PSA User Maximum Open Keys Count** is equal to 0 if the project installed any Wireless Stack before.

![image20](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image20.png)

The PSA Crypto configuration file (`psa_crypto_config_autogen.h`) in the `autogen` folder [Figure Mbed TLS and PSA Crypto Configuration Files](#security-software-components) includes the definitions for PSA key slot count and maximum PSA ITS files.

```sh
#define MBEDTLS_PSA_KEY_SLOT_COUNT (2 + 1 + SL_PSA_KEY_USER_SLOT_COUNT)
#define SL_PSA_ITS_MAX_FILES (1 + SL_PSA_ITS_USER_MAX_FILES)
```

The first digit in `MBEDTLS_PSA_KEY_SLOT_COUNT` is Wireless Stack (if installed) dependent. The second digit should be 1 for the PSA Crypto.

The first digit in `SL_PSA_ITS_MAX_FILES` is equal to 1 if the project installed the `PSA persistent storage support (ITS)` component [Figure Security Software Component for Persistent Key Storage](#security-software-components) before.

###### Initialization and Random Number Generation (RNG)

In PSA Crypto, applications must call `psa_crypto_init()` to initialize the library before using any other function. The PSA Crypto initialization includes seeding the pseudo-random generator (CTR-DRBG) with a hardware entropy source during the execution of `psa_crypto_init()`.

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Initialization</p>
            </td>
            <td>
                <p>
                    Initialize CTR-DRBG<br>
                    • <code>void mbedtls_entropy_init(…)</code><br>
                    • <code>void mbedtls_ctr_drbg_init(…)</code><br>
                    • <code>int mbedtls_entropy_add_source(…)</code><br>
                    Seed and set up the CTR-DRBG entropy<br>
                    • <code>int mbedtls_ctr_drbg_seed(…)</code>
                </p>
            </td>
            <td>
                <p>
                    Initialize PSA Crypto<br>
                    • <code>psa_status_t psa_crypto_init(void)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Generate random bytes</p>
            </td>
            <td>
                <p><code>int mbedtls_ctr_drbg_random(…)</code></p>
            </td>
            <td>
                <p><code>psa_status_t psa_generate_random(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Free resources</p>
            </td>
            <td>
                <p>
                    • <code>void mbedtls_ctr_drbg_free(…)</code><br>
                    • <code>void mbedtls_entropy_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>void mbedtls_psa_crypto_free(void)</code></p>
            </td>
        </tr>
    </tbody>
</table>

If a device includes a True Random Number Generator (TRNG) hardware module, the example will use the TRNG as an entropy source to seed the CTR-DRBG. If the device does not incorporate a TRNG, the example will use [RAIL](https://docs.silabs.com/rail/latest/), Non-volatile (NV) seed (requires [NVM3 driver](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3)), or ADC as the entropy source.

|**Device**|**Entropy Source**|
|---|---|
|MCU Series 1 - EFM32JG1, EFM32PG1|NV seed (default) or ADC|
|MCU Series 1 - EFM32JG12, EFM32PG12, EFM32GG11, EFM32GG12, EFM32TG11|TRNG|
|Wireless SoC Series 1 - EFR32xG1, EFR32xG14|RAIL|
|Wireless SoC Series 1 - EFR32xG12, EFR32xG13 (Revision D or later)|TRNG|
|All MCU Series 2 and Wireless SoC Series 2 devices|TRNG|

**Quick Reference Examples**

**PSA Crypto Initialization and Random Number Generation**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  uint8_t rand_buf[32];
  psa_status_t ret;

  // Initialize the PSA Crypto and generate random numbers
  ret = psa_crypto_init();
  ret = psa_generate_random(rand_buf, sizeof(rand_buf));
}
```

###### Key Handling

The following table describes the main differences in key handling between Mbed TLS and PSA Crypto.

|**Item**|**Mbed TLS**|**PSA Crypto**|
|---|---|---|
|Random Number Generation (RNG)|It requires application code to keep track of RNG.|The core keeps track of RNG.|
|Buffer|It requires dedicated key buffers.|The core manages the key.|
|Key export|The key is exportable.|The usage flag manages this option.|
|Lifetime|It is volatile.|It can be volatile or persistent.|
|Location|Local|Local or Secure|

###### Symmetric Key

A symmetric key can be used with a block cipher or a stream cipher.

**Algorithms**

Refer to the [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation) section.

**Key Attributes in PSA Crypto**

Refer to the [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation) section.

**Security Software Components**

Refer to the [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation) section.

**Functions**

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Create a random key</p>
            </td>
            <td>
                <p>
                    Generate random numbers to a buffer<br>
                    • <code>int mbedtls_ctr_drbg_random(…)</code><br>
                    Set up a key from a buffer (API is algorithm dependent)<br>
                    • <code>int mbedtls_aes_setkey_enc(…)</code><br>
                    • <code>int mbedtls_aes_setkey_dec(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    • <code>int mbedtls_ccm_setkey(…)</code><br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chacha20_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p>
                    Create a key from randomly generated data<br>
                    • <code>psa_status_t psa_generate_key(…)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Import a key from a buffer</p>
            </td>
            <td>
                <p>
                    API is algorithm dependent<br>
                    • <code>int mbedtls_aes_setkey_enc(…)</code><br>
                    • <code>int mbedtls_aes_setkey_dec(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    • <code>int mbedtls_ccm_setkey(…)</code><br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chacha20_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_import_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Copy a key</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_copy_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Export a key to a buffer</p>
            </td>
            <td>
                <p>The key is always in a buffer.</p>
            </td>
            <td>
                <p><code>psa_status_t psa_export_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Destroy a key</p>
            </td>
            <td>
                <p>Zero the key buffer.</p>
            </td>
            <td>
                <p><code>psa_status_t psa_destroy_key(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The `psa_export_key()` can export a symmetric key in plaintext if the [PSA_KEY_USAGE_EXPORT](04-key-management-in-psa-crypto#key-policies) usage flag is set.

**Quick Reference Examples**

**Symmetric Plain Key Creation and Import**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ecb_key[16] = {0};

  psa_status_t ret;
  psa_key_id_t generate_key_id;
  psa_key_id_t import_key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a AES ECB key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, 128);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);

  // Generate a random volatile plain key for AES ECB
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a volatile plain key for AES ECB
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the volatile plain keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);

  // Generate a random persistent plain key for AES ECB (ID = 0x02)
  psa_set_key_id(&key_attr, 0x02);
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a persistent plain key for AES ECB (ID = 0x03)
  psa_set_key_id(&key_attr, 0x03);
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the persistent plain keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);
}
```

**Symmetric Wrapped Key Creation and Import (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ecb_key[16] = {0};

  psa_status_t ret;
  psa_key_id_t generate_key_id;
  psa_key_id_t import_key_id;
  psa_key_attributes_t key_attr;
  ret = psa_crypto_init();

  // Set up attributes for a AES ECB key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, 128);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
  psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, 0x01));

  // Generate a random volatile wrapped key for AES ECB
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a volatile wrapped key for AES ECB
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the volatile wrapped keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);

  // Generate a random persistent wrapped key for AES ECB (ID = 0x02)
  psa_set_key_id(&key_attr, 0x02);
  psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a persistent wrapped key for AES ECB (ID = 0x03)
  psa_set_key_id(&key_attr, 0x03);
  psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the persistent wrapped keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image21](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image21.png)

The following table describes the implementation status of the PSA Crypto symmetric key platform example.

|**Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|Extractable|Y|Y|Y|—|
|Copyable|Y|Y|Y|The PSA_KEY_USAGE_COPY usage flag does not apply to the wrapped key.|
|Wrapped|—|—|Y|Only on HSE-SVH devices.|
|128-bit|Y|Y|Y|—|
|192-bit|Y|Y|Y|—|
|256-bit|Y|Y|Y|—|

###### Asymmetric Key

An asymmetric key pair consists of a (secret) private key and a public key (not secret). A public key cryptographic algorithm can be used for key distribution and digital signatures.

**Algorithms**

Refer to the [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) section.

**Key Attributes in PSA Crypto**

Refer to the [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) section.

**Security Software Components**

Refer to the [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) section.

**Functions**

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Create a random key</p>
            </td>
            <td>
                <p>
                    ECDH<br>
                    • <code>void mbedtls_ecdh_init(…)</code><br>
                    • <code>int mbedtls_ecp_group_load(…)</code><br>
                    • <code>int mbedtls_ecdh_gen_public(…)</code><br>
                    ECDSA<br>
                    • <code>void mbedtls_ecdsa_init(…)</code><br>
                    • <code>int mbedtls_ecdsa_genkey(…)</code>
                </p>
            </td>
            <td>
                <p>
                    Create a key from randomly generated data<br>
                    • <code>psa_status_t psa_generate_key(…)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Import a private or public key from a buffer</p>
            </td>
            <td>
                <p>
                    • <code>int mbedtls_ecp_point_read_binary(…)</code><br>
                    • <code>int mbedtls_mpi_read_binary(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_import_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Copy a key</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_copy_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Export a private key to a buffer</p>
            </td>
            <td>
                <p>
                    • <code>int mbedtls_ecp_point_write_binary(…)</code><br>
                    • <code>int mbedtls_mpi_write_binary(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_export_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Export a public key to a buffer</p>
            </td>
            <td>
                <p>
                    • <code>int mbedtls_ecp_point_write_binary(…)</code><br>
                    • <code>int mbedtls_mpi_write_binary(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_export_public_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Destroy a key</p>
            </td>
            <td>
                <p>
                    ECDH<br>
                    • <code>void mbedtls_ecdh_free(…)</code><br>
                    ECDSA<br>
                    • <code>void mbedtls_ecdsa_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_destroy_key(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - The `psa_import_key()` cannot store a public key in [wrapped](04-key-management-in-psa-crypto) form.
> - The `psa_export_key()` can export a private key in plaintext if the [PSA_KEY_USAGE_EXPORT](04-key-management-in-psa-crypto) usage flag is set.

|**ECC Key**|**Private Key Size (Import and Export)**|**Public Key Size (Import and Export)**|
|---|---|---|
|secp192r1|24-byte|49-byte|
|secp224r1|28-byte|57-byte|
|secp256r1|32-byte|65-byte|
|secp384r1|48-byte|97-byte|
|secp521r1|66-byte|133-byte|
|secp256k1|32-byte|65-byte|
|Curve25519|32-byte|32-byte|
|Curve448|56-byte|56-byte|
|Edwards25519|32-byte|32-byte|

> **Note**:
> 
> - The public key of the `secpxxx` curve is stored in an uncompressed format (prefix `0x04` with the X and Y coordinates).
> - EFR32xG21A/B devices do not support hardware acceleration on the secp224r1 curve.
> - Only the VSE-SVM devices support hardware acceleration on the secp256k1 curve.
> - The secp224r1 and secp256k1 with wrapped keys are not supported yet.

**Quick Reference**

**Examples Asymmetric Key Creation and Import**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  uint8_t public_key[65];         // Uncompressed point format
  size_t pubkey_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Check if there is already a persistent key with the given identifier (ID = 0x02)
  key_attr = psa_key_attributes_init();
  ret = psa_get_key_attributes(0x02, &key_attr);

  if (ret == PSA_ERROR_INVALID_HANDLE) {
    // Key identifier does not exist, set up attributes for a persistent private wrapped key (secp256r1)
    key_attr = psa_key_attributes_init();
    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
    psa_set_key_bits(&key_attr, 256);
    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
    psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
    psa_set_key_id(&key_attr, 0x02);
    psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));

    // Generate a random persistent private wrapped key (ID = 0x02)
    ret = psa_generate_key(&key_attr, &key_id);

    // Export a public key from a persistent private wrapped key (ID = 0x02)
    ret = psa_export_public_key(0x02, public_key, sizeof(public_key), &pubkey_len);

    // Set up attributes for a public key (secp256r1)
    key_attr = psa_key_attributes_init();
    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
    psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

    // Import a public key
    ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

    // Destroy a persistent private wrapped key (ID = 0x02) and public key
    ret = psa_destroy_key(0x02);
    ret = psa_destroy_key(key_id);
  } else if (ret == PSA_SUCCESS) {
    // Key identifier already exists
    return;
  } else {
      // Unexpected error
    return;
  }
}
```

> **Note**: Remove the code for the `psa_set_key_lifetime()` function to generate a random persistent private plain key on non-HSE-SVH devices.

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image22](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image22.png)

The following table describes the implementation status of the PSA Crypto asymmetric key platform example.

|**ECC Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|Extractable|Y|Y|Y|—|
|Copyable|Y|Y|Y|The PSA_KEY_USAGE_COPY usage flag does not apply to the wrapped key.|
|Wrapped|—|—|Y|Only on HSE-SVH devices.|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Curve25519|Y|Y|Y|Hardware acceleration only on HSE devices.|
|Curve448|—|—|Y|Only on HSE-SVH devices with hardware acceleration.|
|Edwards25519|—|—|Y|Only on HSE devices with hardware acceleration.|

> **Note**:
> 
> - This example does not include secp224r1 and secp256k1.
> - The PSA Crypto does not yet support software fallback on the Curve448 and Edwards25519.
> - The HSE-SVM devices require SE firmware v1.2.11 or higher (EFR32xG21) and v2.1.7 or higher (other HSE devices) to support hardware acceleration on Curve25519 and Edwards25519. This feature also requires GSDK v4.0.1 or higher.

###### Symmetric Cryptographic Operation

###### Message Digests (heading level 7)

Message digests are designed to protect the integrity of a piece of data or media to detect changes to any part of a message. They are a type of cryptography utilizing hash values that can warn the receiver of any modifications applied to a message transmitted over an insecure channel.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SHA-1</p>
            </td>
            <td>
                <p><code>MBEDTLS_MD_SHA1</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_SHA_1</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SHA-2</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_MD_SHA224</code><br>
                    • <code>MBEDTLS_MD_SHA256</code><br>
                    • <code>MBEDTLS_MD_SHA384</code><br>
                    • <code>MBEDTLS_MD_SHA512</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_SHA_224</code><br>
                    • <code>PSA_ALG_SHA_256</code><br>
                    • <code>PSA_ALG_SHA_384</code><br>
                    • <code>PSA_ALG_SHA_512</code>
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_SHA_1|SHA-1|
|PSA_ALG_SHA_224|SHA-224|
|PSA_ALG_SHA_256|SHA-256|
|PSA_ALG_SHA_384|SHA-384|
|PSA_ALG_SHA_512|SHA-512|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_ret(…)</code><br>
                    • <code>int mbedtls_sha256_ret(…)</code><br>
                    • <code>int mbedtls_sha512_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_compute(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_compare(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_md_init(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_sha1_init(…)</code><br>
                    • <code>void mbedtls_sha256_init(…)</code><br>
                    • <code>void mbedtls_sha512_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_hash_operation_t psa_hash_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_setup(…)</code><br>
                    • <code>int mbedtls_md_starts(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_starts_ret(…)</code><br>
                    • <code>int mbedtls_sha256_starts_ret(…)</code><br>
                    • <code>int mbedtls_sha512_starts_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_update(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_update_ret(…)</code><br>
                    • <code>int mbedtls_sha256_update_ret(…)</code><br>
                    • <code>int mbedtls_sha512_update_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_update(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_finish(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_finish_ret(…)</code><br>
                    • <code>int mbedtls_sha256_finish_ret(…)</code><br>
                    • <code>int mbedtls_sha512_finish_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_verify(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_md_free(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_sha1_free(…)</code><br>
                    • <code>void mbedtls_sha256_free(…)</code><br>
                    • <code>void mbedtls_sha512_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_abort(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_clone(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_clone(…)</code><br>
                    • <code>int mbedtls_sha256_clone(…)</code><br>
                    • <code>int mbedtls_sha512_clone(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_clone(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The multi-part operation allows the data to be processed for message digest in fragments instead of all at once.

**Quick Reference Examples**

**SHA-256 (One-shot)**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  char test_msg[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
  uint8_t expect_sha256_hash[] = {
    0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
  };

  uint8_t hash_buf[32];
  size_t hash_len;
  psa_status_t ret;

  ret = psa_crypto_init();

  // Calculate the hash of a message
  ret = psa_hash_compute(PSA_ALG_SHA_256,
                        (uint8_t *)test_msg,
                        sizeof(test_msg) - 1,
                        hash_buf,
                        sizeof(hash_buf),
                        &hash_len);

  // Calculate the hash of a message and compare it with a reference value
  ret = psa_hash_compare(PSA_ALG_SHA_256,
                        (uint8_t *)test_msg,
                        sizeof(test_msg) - 1,
                        expect_sha256_hash,
                        sizeof(expect_sha256_hash));
}
```

**SHA-256 (Streaming)**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  char test_msg[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
  uint8_t hash_buf[32];
  size_t hash_len;
  uint32_t hash_total;
  uint32_t stream_block_size = 16;            // Block size for streaming

  psa_status_t ret;
  psa_hash_operation_t hash_op;
  psa_hash_operation_t verify_op;

  ret = psa_crypto_init();

  hash_op = psa_hash_operation_init();
  ret = psa_hash_setup(&hash_op, PSA_ALG_SHA_256);

  // Streaming block
  hash_total = 0;
  while ((sizeof(test_msg) - 1 - hash_total) > stream_block_size) {
  ret = psa_hash_update(&hash_op, (uint8_t *)(test_msg + hash_total), stream_block_size);
  hash_total += stream_block_size;
  }
  ret = psa_hash_update(&hash_op, (uint8_t *)(test_msg + hash_total), sizeof(test_msg) -1 - hash_total);

  // Generate hash and verify
  // Expected hash:
  // 24 8d 6a 61 d2 06 38 b8 e5 c0 26 93 0c 3e 60 39 a3 3c e4 59 64 ff 21 67 f6 ec ed d4 19 db 06 c1
  verify_op = psa_hash_operation_init();
  ret = psa_hash_clone(&hash_op, &verify_op);
  ret = psa_hash_finish(&hash_op, hash_buf, sizeof(hash_buf), &hash_len);
  ret = psa_hash_verify(&verify_op, hash_buf, hash_len);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image23](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image23.png)

The following table describes the implementation status of the PSA Crypto hash platform example.

|**Algorithm**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|SHA-1|Y|Y|Y|—|
|SHA-224|Y|Y|Y|—|
|SHA-256|Y|Y|Y|—|
|SHA-384|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|SHA-512|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|

###### Message Authentication Codes (MAC)

A Message Authentication Code (MAC), sometimes known as a tag, is a short piece of information used to confirm that the message came from the stated sender (its authenticity) and has not been changed.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HMAC</p>
            </td>
            <td>
                <p><code>• MBEDTLS_MD_SHA1</code><br><code>• MBEDTLS_MD_SHA224</code><br><code>• MBEDTLS_MD_SHA256</code><br><code>• MBEDTLS_MD_SHA384</code><br><code>• MBEDTLS_MD_SHA512</code></p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_1)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_512)</code><br>
                    • <code>PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)</code><br>
                    • <code>PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_HMAC(hash_alg))</code><br>
                    • <code>PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CMAC</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_ECB</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_CMAC</code><br>
                    • <code>PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)</code><br>
                    • <code>PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_CMAC)</code><br>
                    • <code>PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)</code>
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>•PSA_ALG_HMAC(PSA_ALG_SHA_1)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_224)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_256)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_384)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_512)<br><br>
                •PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)<br><br>
                •PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_HMAC(hash_alg))<br><br>
                •PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)
            </td>
            <td>PSA_KEY_TYPE_HMAC</td>
            <td>Multiple of 8</td>
            <td rowspan="2">•PSA_KEY_USAGE_SIGN_MESSAGE<br><br>
                •PSA_KEY_USAGE_VERIFY_MESSAGE
            </td>
        </tr>
        <tr>
            <td>•PSA_ALG_CMAC<br><br>
                •PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)<br><br>
                •PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_CMAC)<br><br>
                •PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)
            </td>
            <td>PSA_KEY_TYPE_AES</td>
            <td>•128 (16-byte)<br><br>
                •192 (24-byte)<br><br>
                •256 (32-byte)
            </td>
        </tr>
    </tbody>
</table>

> **Note**: For GSDK lower than v4.1.0, use usage flag `PSA_KEY_USAGE_SIGN_HASH` and `PSA_KEY_USAGE_VERIFY_HASH` instead of `PSA_KEY_USAGE_SIGN_MESSAGE` and `PSA_KEY_USAGE_VERIFY_MESSAGE`.

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_HMAC(PSA_ALG_SHA_1)|HMAC and SHA-1|
|PSA_ALG_HMAC(PSA_ALG_SHA_224)|HMAC and SHA-224|
|PSA_ALG_HMAC(PSA_ALG_SHA_256)|HMAC and SHA-256|
|PSA_ALG_HMAC(PSA_ALG_SHA_384)|HMAC and SHA-384|
|PSA_ALG_HMAC(PSA_ALG_SHA_512)|HMAC and SHA-512|
|PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)|HMAC and SHA-X|
|PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_HMAC(hash_alg))|HMAC and SHA-X|
|PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)|HMAC and SHA-X|
|PSA_ALG_CMAC|CMAC|
|PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)|CMAC|
|PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_CMAC)|CMAC|
|PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)|CMAC|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_compute(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_verify(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>void mbedtls_md_init(…)</code><br>
                    • <code>int mbedtls_md_setup(…)</code><br>
                    CMAC<br>
                    • <code>void mbedtls_cipher_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_mac_operation_t psa_mac_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac_starts(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_sign_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_verify_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac_update(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac_update(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_update(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac_finish(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac_finish(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_sign_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_verify_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>void mbedtls_md_free(…)</code><br>
                    CMAC<br>
                    • <code>void mbedtls_cipher_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_abort(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The multi-part operation allows the data to be processed for MAC in fragments instead of all at once.

**Quick Reference Examples**

**CMAC (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t cmac_key[] = {
    0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
  };
  uint8_t cmac_msg[] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11
  };
  uint8_t mac_buf[16];
  size_t mac_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a CMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC);

  // Import a volatile plain key for CMAC
  ret = psa_import_key(&key_attr, cmac_key, sizeof(cmac_key), &key_id);

  // Calculate the CMAC MAC of a message
  // Expected CMAC MAC: aa f3 d8 f1 de 56 40 c2 32 f5 b1 69 b9 c9 11 e6
  ret = psa_mac_compute(key_id, PSA_ALG_CMAC,
                        cmac_msg, sizeof(cmac_msg),
                        mac_buf, sizeof(mac_buf), &mac_len);

  // Verify the CMAC MAC of a message
  ret = psa_mac_verify(key_id, PSA_ALG_CMAC,
                        cmac_msg, sizeof(cmac_msg),
                        mac_buf, mac_len);

  // Destroy a volatile plain key for CMACss
  ret = psa_destroy_key(key_id);
}
```

> **Note**: There are two ways to change the CMAC MAC length (default 16 bytes).
> 
> 1. Replace all MAC algorithm `PSA_ALG_CMAC` with `PSA_ALG_TRUNCATED_MAC``(PSA_ALG_CMAC, mac_length)` for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_CMAC` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC)` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)` to set the minimum MAC length (≥ 4) in bytes. Replace the MAC algorithm `PSA_ALG_CMAC` in `psa_mac_compute()` and `psa_mac_verify()` with `PSA_ALG_TRUNCATED_MAC``(PSA_ALG_CMAC, mac_length)` to set the desired MAC length (≥ `min_mac_length` and ≤ `PSA_MAC_LENGTH``(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC))` in bytes.

**HMAC SHA-256 (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t hmac_key[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t hmac_msg[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t mac_buf[32];
  size_t mac_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a HMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_HMAC);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));

  // Import a volatile plain key for HMAC
  ret = psa_import_key(&key_attr, hmac_key, sizeof(hmac_key), &key_id);

  // Calculate the HMAC MAC of a message
  // Expected HMAC MAC:
  // fb 5b 26 22 9c 20 b7 ed 86 67 06 a2 fb fa e6 7e 3f 40 4b b6 ab e7 7f f4 50 63 a4 59 a4 29 24 a4
  ret = psa_mac_compute(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256),
                        hmac_msg, sizeof(hmac_msg),
                        mac_buf, sizeof(mac_buf), &mac_len);
  // Verify the HMAC MAC of a message
  ret = psa_mac_verify(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256),
                        hmac_msg, sizeof(hmac_msg),
                        mac_buf, mac_len);

  // Destroy a volatile plain key for HMAC
  ret = psa_destroy_key(key_id);
}
```

> **Notes**: There are two ways to change the HMAC MAC length (default is `hash_alg` dependent).
> 
> 1. Replace all MAC algorithm `PSA_ALG_HMAC(hash_alg)` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg)`, `mac_length`) for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(hash_alg))` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)` to set the minimum MAC length (≥ 4) in bytes.
> 
> Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in `psa_mac_compute()` and `psa_mac_verify()` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)` to set the desired MAC length `(≥ min_mac_length` and `≤ PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 256, PSA_ALG_HMAC(hash_alg)))` in bytes.

**CMAC (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t cmac_key[] = {
    0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
  };
  uint8_t cmac_msg[] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11
  };
  uint8_t mac_buf[16];
  size_t mac_len;
  uint32_t mac_total;
  uint32_t stream_block_size = 8;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_mac_operation_t mac_op;

  ret = psa_crypto_init();

  // Set up attributes for a CMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC);

  // Import a volatile plain key for CMAC
  ret = psa_import_key(&key_attr, cmac_key, sizeof(cmac_key), &key_id);

  // Stream message and calculate the CMAC MAC
  // Expected CMAC MAC: aa f3 d8 f1 de 56 40 c2 32 f5 b1 69 b9 c9 11 e6
  mac_op = psa_mac_operation_init();
  ret = psa_mac_sign_setup(&mac_op, key_id, PSA_ALG_CMAC);
  mac_total = 0;        // Streaming block
  while ((sizeof(cmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, cmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, cmac_msg + mac_total, sizeof(cmac_msg) - mac_total);
  ret = psa_mac_sign_finish(&mac_op, mac_buf, sizeof(mac_buf), &mac_len);

  // Stream message and verify the CMAC MAC
  mac_op = psa_mac_operation_init();
  ret = psa_mac_verify_setup(&mac_op, key_id, PSA_ALG_CMAC);
  mac_total = 0;        // Streaming block
  while ((sizeof(cmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, cmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, cmac_msg + mac_total, sizeof(cmac_msg) - mac_total);
  ret = psa_mac_verify_finish(&mac_op, mac_buf, mac_len);

  // Destroy a volatile plain key for CMAC
  ret = psa_destroy_key(key_id);
}
```

> **Notes**: There are two ways to change the CMAC MAC length (default 16 bytes).
> 
> 1. Replace all MAC algorithm `PSA_ALG_CMAC` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)` for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_CMAC` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC)` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)` to set the minimum MAC length (≥ 4) in bytes.
> 
> Replace the MAC algorithm `PSA_ALG_CMAC` in `psa_mac_sign_setup()` and `psa_mac_verify_setup()` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)` to set the desired MAC length `(≥ min_mac_length and ≤ PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC))` in bytes.

**HMAC SHA-256 (Streaming)**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  uint8_t hmac_key[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t hmac_msg[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t mac_buf[32];
  size_t mac_len;
  uint32_t mac_total;
  uint32_t stream_block_size = 8;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_mac_operation_t mac_op;

  ret = psa_crypto_init();

  // Set up attributes for a HMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_HMAC);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));

  // Import a volatile plain key for HMAC
  ret = psa_import_key(&key_attr, hmac_key, sizeof(hmac_key), &key_id);

  // Stream message and calculate the HMAC MAC
  // Expected HMAC MAC:
  // fb 5b 26 22 9c 20 b7 ed 86 67 06 a2 fb fa e6 7e 3f 40 4b b6 ab e7 7f f4 50 63 a4 59 a4 29 24 a4
  mac_op = psa_mac_operation_init();
  ret = psa_mac_sign_setup(&mac_op, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
  mac_total = 0; // Streaming block
  while ((sizeof(hmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, hmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, hmac_msg + mac_total, sizeof(hmac_msg) - mac_total);
  ret = psa_mac_sign_finish(&mac_op, mac_buf, sizeof(mac_buf), &mac_len);

  // Stream message and verify the HMAC MAC
  mac_op = psa_mac_operation_init();
  ret = psa_mac_verify_setup(&mac_op, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
  mac_total = 0; // Streaming block
  while ((sizeof(hmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, hmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, hmac_msg + mac_total, sizeof(hmac_msg) - mac_total);
  ret = psa_mac_verify_finish(&mac_op, mac_buf, mac_len);

  // Destroy a volatile plain key for HMAC
  ret = psa_destroy_key(key_id);
}
```

> **Notes**: There are two ways to change the HMAC MAC length (default is `hash_alg` dependent).
> 
> 1. Replace all MAC algorithm `PSA_ALG_HMAC(hash_alg)` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)` for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(hash_alg))` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)` to set the minimum MAC length (≥ 4) in bytes.
> 
> Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in `psa_mac_sign_setup()` and `psa_mac_verify_setup()` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)` to set the desired MAC length `(≥ min_mac_length and ≤ PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 256, PSA_ALG_HMAC(hash_alg)))` in bytes.

**PSA Crypto Platform Example**

Click the View Project Documentation link to open the readme file.

![image24](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image24.png)

The following table describes the implementation status of the PSA Crypto MAC platform example.

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Series 1</strong></th>
            <th><strong>Series 2 - VSE</strong></th>
            <th><strong>Series 2 - HSE</strong></th>
            <th>Remark</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HMAC</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>
                    - Hardware acceleration only on Series 2 devices.<br>
                    - HMAC streaming with wrapped key is not supported yet.
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CMAC</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Series 1 devices do not support a 192-bit key.</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - The MAC platform example uses the default MAC length.
> - The single-part MAC functions are only available on GSDK v4.0.0 and higher.

###### Unauthenticated Ciphers (heading level 7)

The unauthenticated cipher API is for use cases where the data integrity and authenticity are guaranteed by non-cryptographic means.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>AES ECB</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_ECB</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_ECB_NO_PADDING</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CBC</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_CBC</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_CBC</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_CBC</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_CBC_NO_PADDING</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CFB</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_CFB128</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_CFB128</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_CFB128</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_CFB</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CTR</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_CTR</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_CTR</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_CTR</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_CTR</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CHACHA20</p>
            </td>
            <td>
                <p><code>MBEDTLS_CIPHER_CHACHA20</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_STREAM_CIPHER</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>PSA_ALG_ECB_NO_PADDING</code></td>
            <td rowspan="4"><code>PSA_KEY_TYPE_AES</code></td>
            <td rowspan="4">128 (16-byte)<br>192 (24-byte)<br>256 (32-byte)</td>
            <td rowspan="5"><code>PSA_KEY_USAGE_ENCRYPT</code><br><code>PSA_KEY_USAGE_DECRYPT</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CBC_NO_PADDING</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CFB</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CTR</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_STREAM_CIPHER</code></td>
            <td><code>PSA_KEY_TYPE_CHACHA20</code></td>
            <td>256 (32-byte)</td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm and Built-in Key**|**Security Software Components**|
|---|---|
|PSA_ALG_ECB_NO_PADDING|ECB Mode|
|PSA_ALG_CBC_NO_PADDING|CBC Mode|
|PSA_ALG_CFB|CFB Mode|
|PSA_ALG_CTR|CTR Mode|
|PSA_ALG_STREAM_CIPHER|Chacha20 Stream Cipher|

|**Built-in Key**|**Security Software Components**|
|---|---|
|secp256r1 keys in SE OTP|Built-In Keys|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_crypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_aes_crypt_ecb(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cbc(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cfb128(…)</code><br>
                    • <code>int mbedtls_aes_crypt_ctr(…)</code><br>
                    • <code>int mbedtls_chacha20_crypt(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_encrypt(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_crypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_aes_crypt_ecb(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cbc(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cfb128(…)</code><br>
                    • <code>int mbedtls_aes_crypt_ctr(…)</code><br>
                    • <code>int mbedtls_chacha20_crypt(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_decrypt(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - The `psa_cipher_encrypt()` encrypts a message with a random initialization vector (IV). The output of this function is the IV followed by the ciphertext. Use the multi-part operations to manage the IV and ciphertext separately.
> - The input to `psa_cipher_decrypt()` must contain the IV followed by the ciphertext, as output by` psa_cipher_encrypt()`. Use the multi-part operations to decrypt data that is not in the expected input format.

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_init(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_chacha20_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_cipher_operation_t psa_cipher_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_encrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_generate_iv(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_decrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_set_iv(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_update(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_update(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_update(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>int mbedtls_cipher_finish(…)</code></p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_free(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_abort(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The following situations require the use of a multi-part operation:
> 
> - Processing messages that cannot be assembled in memory.
> - Using a deterministic initialization vector (IV) for unauthenticated encryption.
> - Providing the IV separately for unauthenticated encryption or decryption.

**Quick Reference Examples**

**AES ECB (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ecb_key[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
  };
  uint8_t plain_msg_buf[] = {
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
  };
  uint8_t cipher_buf[16];
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES ECB key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);

  // Import a volatile plain key for AES ECB
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &key_id);
  
  // AES ECB encryption and decryption
  // Expected ciphertext: 69 c4 e0 d8 6a 7b 04 30 d8 cd b7 80 70 b4 c5 5a
  // Single-part
  ret = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_ECB_NO_PADDING,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_ECB_NO_PADDING);
  ret = psa_cipher_update(&cipher_op, plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_ECB_NO_PADDING);
  ret = psa_cipher_update(&cipher_op, cipher_buf, sizeof(cipher_buf),
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);

  // Destroy a volatile plain key for AES ECB
  ret = psa_destroy_key(key_id);
}
```

**AES CFB (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_cbc_key[] = {
    0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
  };
  uint8_t iv_buf[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
  };
  uint8_t plain_msg_buf[] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
  };
  uint8_t cipher_buf[32]; // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES CBC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CBC_NO_PADDING);

  // Import a volatile plain key for AES CBC
  ret = psa_import_key(&key_attr, aes_cbc_key, sizeof(aes_cbc_key), &key_id);

  // AES CBC encryption and decryption
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(key_id, PSA_ALG_CBC_NO_PADDING,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_CBC_NO_PADDING,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  // Expected ciphertext: 76 49 ab ac 81 19 b2 46 ce e9 8e 9b 12 e9 19 7d
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_CBC_NO_PADDING);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_CBC_NO_PADDING);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);

  // Destroy a volatile plain key for AES CBC
  ret = psa_destroy_key(key_id);
}
```

> **Note**: The multi-part operations provide the IV separately for AES CFB encryption or decryption.

**AES CTR (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ctr_key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  };
  uint8_t iv_buf[] = {
    0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70
  };
  uint8_t plain_msg_buf[] = {
    0xd8, 0x65, 0xc9, 0xcd, 0xea, 0x33, 0x56, 0xc5, 0x48, 0x8e, 0x7b, 0xa1, 0x5e, 0x84, 0xf4, 0xeb,
    0xa3, 0xb8, 0x25, 0x9c, 0x05, 0x3f, 0x24, 0xce, 0x29, 0x67, 0x22, 0x1c, 0x00, 0x38, 0x84, 0xd7,
    0x9d, 0x4c, 0xa4, 0x87, 0x7f, 0xfa, 0x4b, 0xc6, 0x87, 0xc6, 0x67, 0xe5, 0x49, 0x5b, 0xcf, 0xec,
    0x12, 0xf4, 0x87, 0x17, 0x32, 0xaa, 0xe4, 0x5a, 0x11, 0x06, 0x76, 0x11, 0x3d, 0xf9, 0xe7, 0xda
  };
  uint8_t cipher_buf[80]; // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES CTR key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Import a volatile plain key for AES CTR
  ret = psa_import_key(&key_attr, aes_ctr_key, sizeof(aes_ctr_key), &key_id);

  // AES CTR encryption and decryption
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(key_id, PSA_ALG_CTR,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_CTR,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);
  // Multi-part
  // Expected ciphertext:
  // b6 72 f2 af 6a cc 20 ae ee 1a d8 14 12 8c 31 8b 95 5b be 80 5b 38 92 49 89 76 00 f5 20 74 54 32
  // 7d 6d 0f b4 ac 0a 94 f3 7c a0 9e 45 05 33 98 fe a8 9c 20 0a d3 58 12 6d 9e 89 a4 05 26 5c 96 e7
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);
  // Destroy a volatile plain key for AES CTR
  ret = psa_destroy_key(key_id);
}
```

> **Note**: The multi-part operations provide the IV separately for AES CTR encryption or decryption.

**CHACHA20 (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t chacha20_key[32] = {0};
  uint8_t iv_buf[12] = {0};
  uint8_t plain_msg_buf[64] = {0};
  uint8_t cipher_buf[76];         // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a CHACHA20 key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_CHACHA20);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_STREAM_CIPHER);

  // Import a volatile plain key for CHACHA20
  ret = psa_import_key(&key_attr, chacha20_key, sizeof(chacha20_key), &key_id);

  // CHACHA20 encryption and decryption
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(key_id, PSA_ALG_STREAM_CIPHER,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_STREAM_CIPHER,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  // Expected ciphertext:
  // 76 b8 e0 ad a0 f1 3d 90 40 5d 6a e5 53 86 bd 28 bd d2 19 b8 a0 8d ed 1a a8 36 ef cc 8b 77 0d c7
  // da 41 59 7c 51 57 48 8d 77 24 e0 3f b8 d8 4a 37 6a 43 b8 f4 15 18 a1 1c c3 87 b6 69 b2 ee 65 86
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_STREAM_CIPHER);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_STREAM_CIPHER);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);

  // Destroy a volatile plain key for CHACHA20
  ret = psa_destroy_key(key_id);
}
```

> **Note**: The multi-part operations provide the IV separately for CHACHA20 encryption or decryption.

**AES CTR (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
 uint8_t aes_ctr_key[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 };
 uint8_t iv_buf[] = {
   0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70
 };
 uint8_t plain_msg_buf[] = {
  0xd8, 0x65, 0xc9, 0xcd, 0xea, 0x33, 0x56, 0xc5, 0x48, 0x8e, 0x7b, 0xa1, 0x5e, 0x84, 0xf4, 0xeb,
  0xa3, 0xb8, 0x25, 0x9c, 0x05, 0x3f, 0x24, 0xce, 0x29, 0x67, 0x22, 0x1c, 0x00, 0x38, 0x84, 0xd7,
  0x9d, 0x4c, 0xa4, 0x87, 0x7f, 0xfa, 0x4b, 0xc6, 0x87, 0xc6, 0x67, 0xe5, 0x49, 0x5b, 0xcf, 0xec,
  0x12, 0xf4, 0x87, 0x17, 0x32, 0xaa, 0xe4, 0x5a, 0x11, 0x06, 0x76, 0x11, 0x3d, 0xf9, 0xe7, 0xda
 };
 uint8_t cipher_buf[64];
 size_t out_len;
 uint32_t out_total;
 uint32_t stream_block_size = 14;                 // Block size for streaming

 psa_status_t ret;
 psa_key_id_t key_id;
 psa_key_attributes_t key_attr;
 psa_cipher_operation_t cipher_op;

 ret = psa_crypto_init();

 // Set up attributes for a AES CTR key
 key_attr = psa_key_attributes_init();
 psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
 psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

 // Import a volatile plain key for AES CTR
 ret = psa_import_key(&key_attr, aes_ctr_key, sizeof(aes_ctr_key), &key_id);

 // AES CTR stream encryption and decryption
 // Expected ciphertext:
 // b6 72 f2 af 6a cc 20 ae ee 1a d8 14 12 8c 31 8b 95 5b be 80 5b 38 92 49 89 76 00 f5 20 74 54 32
 // 7d 6d 0f b4 ac 0a 94 f3 7c a0 9e 45 05 33 98 fe a8 9c 20 0a d3 58 12 6d 9e 89 a4 05 26 5c 96 e7
 cipher_op = psa_cipher_operation_init();
 ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
 ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));

 out_total = 0; // Streaming block
 while ((sizeof(plain_msg_buf) - out_total) > stream_block_size) {
   ret = psa_cipher_update(&cipher_op,
                            plain_msg_buf + out_total, stream_block_size,
                            cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                            &out_len);
  out_total += out_len;
 }
  ret = psa_cipher_update(&cipher_op, // Last block
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
  out_total += out_len;

 ret = psa_cipher_finish(&cipher_op,
                        cipher_buf + out_total,
                        sizeof(cipher_buf) - out_total,
                        &out_len);

 cipher_op = psa_cipher_operation_init();
 ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
 ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));

 out_total = 0; // Streaming block
 while ((sizeof(cipher_buf) - out_total) > stream_block_size) {
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf + out_total, stream_block_size,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
  out_total += out_len;
 }

  ret = psa_cipher_update(&cipher_op, // Last block
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
  out_total += out_len;

  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_total,
                          sizeof(plain_msg_buf) - out_total,
                          &out_len);

 // Destroy a volatile plain key for AES CTR
 ret = psa_destroy_key(key_id);
}
```

**AES CTR with Built-in AES-128 Key (HSE only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t iv_buf[16] = {0};
  uint8_t plain_msg_buf[16] = {0};
  uint8_t cipher_buf[32]; // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // AES CTR encryption and decryption with built-in AES-128 key
  // ret = -140 (PSA_ERROR_DOES_NOT_EXIST) if the AES-128 key has not been provisioned
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  // Built-in AES-128 key: 81 a5 e2 1f a1 52 86 f1 df 44 5c 2c c1 20 fa 3f
  // Expected ciphertext: 66 d2 0f 99 65 3e a8 d0 83 05 a6 39 d4 4e 98 a6
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image25](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image25.png)

The following table describes the implementation status of the PSA Crypto cipher platform example.

|**Algorithm/Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|AES ECB|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES CBC|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES CFB|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES CTR|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|CHACHA20|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|AES-128 Key|—|—|Y|—|

> **Note**: The single-part unauthenticated cipher functions are only available on GSDK v4.0.0 and higher.

###### Authenticated Encryption with Associated Data (AEAD) (heading level 7)

The authenticated encryption with associated data (AEAD) is a form of encryption that simultaneously assures the confidentiality and authenticity of data.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>AES GCM</p>
            </td>
            <td>
                <p>
                    • MBEDTLS_CIPHER_AES_128_GCM<br>
                    • MBEDTLS_CIPHER_AES_192_GCM<br>
                    • MBEDTLS_CIPHER_AES_256_GCM
                </p>
            </td>
            <td>
                <p>
                    • PSA_ALG_GCM<br>
                    • PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_length)<br>
                    • PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(PSA_ALG_GCM)<br>
                    • PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, min_tag_length)
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CCM</p>
            </td>
            <td>
                <p>
                    • MBEDTLS_CIPHER_AES_128_CCM<br>
                    • MBEDTLS_CIPHER_AES_192_CCM<br>
                    • MBEDTLS_CIPHER_AES_256_CCM
                </p>
            </td>
            <td>
                <p>
                    • PSA_ALG_CCM<br>
                    • PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length)<br>
                    • PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(PSA_ALG_CCM)<br>
                    • PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, min_tag_length)
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CHACHA20_POLY1305</p>
            </td>
            <td>
                <p>MBEDTLS_CIPHER_CHACHA20_POLY1305</p>
            </td>
            <td>
                <p>PSA_ALG_CHACHA20_POLY1305</p>
            </td>
        </tr>
    </tbody>
</table>

|**Algorithm**|**Nonce Length (Bytes)**|**Authentication Tag Length (Bytes)**|
|---|---|---|
|AES GCM|1 - 16 (Default 12)|4, 8, 12, 13, 14, 15, and 16 (Default)|
|AES CCM|7 - 13|4, 6, 8, 10, 12, 14, and 16 (Default)|
|CHACHA20_POLY1305|12|16|

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <code>PSA_ALG_GCM</code> or<br>
                <code>PSA_ALG_AEAD_WITH_*(PSA_ALG_GCM…)</code>
            </td>
            <td rowspan="2"><code>PSA_KEY_TYPE_AES</code></td>
            <td>128 (16-byte)<br>192 (24-byte)<br>256 (32-byte)</td>
            <td rowspan="3">
                <code>PSA_KEY_USAGE_ENCRYPT</code><br>
                <code>PSA_KEY_USAGE_DECRYPT</code>
            </td>
        </tr>
        <tr>
            <td>
                <code>PSA_ALG_CCM</code> or<br>
                <code>PSA_ALG_AEAD_WITH_*(PSA_ALG_CCM…)</code>
            </td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CHACHA20_POLY1305</code></td>
            <td><code>PSA_KEY_TYPE_CHACHA20</code></td>
            <td>256 (32-byte)</td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_GCM or PSA_ALG_AEAD_WITH_*(PSA_ALG_GCM…)|GCM (12-byte IV) or GCM with Non-Recommended IV Lengths|
|PSA_ALG_CCM or PSA_ALG_AEAD_WITH_*(PSA_ALG_CCM…)|CCM Mode|
|PSA_ALG_CHACHA20_POLY1305|ChachaPoly|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_auth_encrypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_ccm_encrypt_and_tag(…)</code><br>
                    • <code>int mbedtls_gcm_crypt_and_tag(…)</code><br>
                    • <code>int mbedtls_chachapoly_encrypt_and_tag(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_encrypt(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_auth_decrypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_ccm_auth_decrypt(…)</code><br>
                    • <code>int mbedtls_gcm_auth_decrypt(…)</code><br>
                    • <code>int mbedtls_chachapoly_auth_decrypt(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_decrypt(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The single-part functions use one buffer for the ciphertext and AEAD authentication tag.

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_init(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_gcm_init(…)</code><br>
                    • <code>void mbedtls_chachapoly_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_aead_operation_t psa_aead_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_encrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_starts(…)</code><br>
                    • <code>int mbedtls_chachapoly_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_generate_nonce(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_set_lengths(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_decrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_starts(…)</code><br>
                    • <code>int mbedtls_chachapoly_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_set_nonce(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_update_ad(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_starts(…)</code><br>
                    • <code>int mbedtls_chachapoly_update_aad(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_update_ad(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_update(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_update(…)</code><br>
                    • <code>int mbedtls_chachapoly_update(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_update(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_finish(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_finish(…)</code><br>
                    • <code>int mbedtls_chachapoly_finish(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_verify(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_free(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_free(…)</code><br>
                    • <code>int mbedtls_chachapoly_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_abort(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - For `PSA_ALG_CCM`, calling` psa_aead_set_lengths()` is required.
> - For the other AEAD algorithms, calling `psa_aead_set_lengths()` is not required.
> - The following situations require the use of a multi-part operation:
> - Processing messages that cannot be assembled in memory.
> - Separating the AEAD authentication tag from the ciphertext.

**Quick Reference Examples**

**AES CCM (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0xea, 0x4f, 0x6f, 0x3c, 0x2f, 0xed, 0x2b, 0x9d, 0xd9, 0x70, 0x8c, 0x2e, 0x72, 0x1a, 0xe0, 0x0f
  };
  uint8_t nonce_buf[] = {0xf9, 0x75, 0x80, 0x9d, 0xdb, 0x51, 0x72, 0x38, 0x27, 0x45, 0x63, 0x4f};
  uint8_t ad_buf[] = {0x5c, 0x65, 0xd4, 0xf2, 0x61, 0xd2, 0xc5, 0x4f, 0xfe, 0x6a};
  uint8_t plain_msg_buf[] = {0x8d, 0x6c, 0x08, 0x44, 0x6c, 0xb1, 0x0d, 0x9a, 0x20, 0x75};
  uint8_t cipher_tag_buf[32];       // Ciphertext + Tag
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a AES CCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CCM);

  // Import a volatile plain key for AES CCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES CCM encryption and descryption
  // Expected ciphertext: e2 2f 37 3b eb f6 4a 3e 9b 87
  // Expected tag: 75 2b f9 db 34 dc 4d 43 3f 00 f5 5c 3f 53 0c 89
  ret = psa_aead_encrypt(key_id, PSA_ALG_CCM,
                        nonce_buf, sizeof(nonce_buf),
                        ad_buf, sizeof(ad_buf),
                        plain_msg_buf, sizeof(plain_msg_buf),
                        cipher_tag_buf, sizeof(cipher_tag_buf),
                        &out_len);
  ret = psa_aead_decrypt(key_id, PSA_ALG_CCM,
                        nonce_buf, sizeof(nonce_buf),
                        ad_buf, sizeof(ad_buf),
                        cipher_tag_buf, out_len,
                        plain_msg_buf, sizeof(plain_msg_buf),
                        &out_len);

  // Destroy a volatile plain key for AES CCM
  ret = psa_destroy_key(key_id);
}
```

> **Notes**:
> 
> - There are two ways to change the CCM authentication tag length (default 16 bytes).
>   1. Replace all AEAD algorithm `PSA_ALG_CCM` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length)` for the desired size of the authentication tag in bytes.
>   2. Replace the AEAD algorithm `PSA_ALG_CCM` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_CCM)` function with `PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, min_tag_length)` to set the minimum authentication tag length in bytes. Replace the AEAD algorithm `PSA_ALG_CCM in psa_aead_encrypt()` and `psa_aead_decrypt()` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length)` to set the desired tag length `(≥ min_tag_length and ≤ PSA_AEAD_TAG_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CCM))` in bytes.

**AES GCM (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0xea, 0x4f, 0x6f, 0x3c, 0x2f, 0xed, 0x2b, 0x9d, 0xd9, 0x70, 0x8c, 0x2e, 0x72, 0x1a, 0xe0, 0x0f
  };
  uint8_t nonce_buf[] = {0xf9, 0x75, 0x80, 0x9d, 0xdb, 0x51, 0x72, 0x38, 0x27, 0x45, 0x63, 0x4f};
  uint8_t ad_buf[] = {0x5c, 0x65, 0xd4, 0xf2, 0x61, 0xd2, 0xc5, 0x4f, 0xfe, 0x6a};
  uint8_t plain_msg_buf[] = {0x8d, 0x6c, 0x08, 0x44, 0x6c, 0xb1, 0x0d, 0x9a, 0x20, 0x75};
  uint8_t cipher_tag_buf[32]; // Ciphertext + Tag
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a AES GCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_GCM);

  // Import a volatile plain key for AES GCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES GCM encryption and decryption
  // Expected ciphertext: 0f 51 f7 a8 3c 5b 5a a7 96 b9
  // Expected tag: 70 25 9c dd fe 8f 9a 15 a5 c5 eb 48 5a f5 78 fb
  ret = psa_aead_encrypt(key_id, PSA_ALG_GCM,
                          nonce_buf, sizeof(nonce_buf),
                          ad_buf, sizeof(ad_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_tag_buf, sizeof(cipher_tag_buf),
                          &out_len);

  ret = psa_aead_decrypt(key_id, PSA_ALG_GCM,
                          nonce_buf, sizeof(nonce_buf),
                          ad_buf, sizeof(ad_buf),
                          cipher_tag_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
                          
  // Destroy a volatile plain key for AES GCM
  ret = psa_destroy_key(key_id);
}
```

> **Notes**:
> 
> - There are two ways to change the GCM authentication tag length (default 16 bytes).
>   1. Replace all AEAD algorithm `PSA_ALG_GCM` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_length)` for the desired size of the authentication tag in bytes.
>   2. Replace the AEAD algorithm `PSA_ALG_GCM in the psa_set_key_algorithm(&key_attr, PSA_ALG_GCM)` function with `PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, min_tag_length)` to set the minimum authentication tag length in bytes. Replace the AEAD algorithm `PSA_ALG_GCM in psa_aead_encrypt()` and `psa_aead_decrypt()` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_length)` to set the desired tag length `(≥ min_tag_length and ≤ PSA_AEAD_TAG_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_GCM))` in bytes.

**CHACHA20_POLY1305 (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
  };
  uint8_t nonce_buf[] = {0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47};
  uint8_t ad_buf[] = {0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7};
  uint8_t plain_msg_buf[] = {
    0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
    0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
    0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
    0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
    0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
    0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
    0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
    0x74, 0x2e
  };
  uint8_t cipher_tag_buf[130]; // Ciphertext + Tag
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  
  ret = psa_crypto_init();

  // Set up attributes for a CHACHA20_POLY1305 key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_CHACHA20);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CHACHA20_POLY1305);

  // Import a volatile plain key for CHACHA20_POLY1305
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // CHACHA20_POLY1305 encryption
  // Expected ciphertext:
  // d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2 a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6
  // 3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b 1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36
  // 92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58 fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc
  // 3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b 61 16
  // Expected tag: 1a e1 0b 59 4f 09 e2 6a 7e 90 2e cb d0 60 06 91
  ret = psa_aead_encrypt(key_id,
                        PSA_ALG_CHACHA20_POLY1305,
                        nonce_buf,
                        sizeof(nonce_buf),
                        ad_buf,
                        sizeof(ad_buf),
                        plain_msg_buf,
                        sizeof(plain_msg_buf),
                        cipher_tag_buf,
                        sizeof(cipher_tag_buf),
                        &out_len);

  // CHACHA20_POLY1305 decryption
  ret = psa_aead_decrypt(key_id,
                        PSA_ALG_CHACHA20_POLY1305,
                        nonce_buf,
                        sizeof(nonce_buf),
                        ad_buf,
                        sizeof(ad_buf),
                        cipher_tag_buf,
                        out_len,
                        plain_msg_buf,
                        sizeof(plain_msg_buf),
                        &out_len);

  // Destroy a volatile plain key for CHACHA20_POLY1305
  ret = psa_destroy_key(key_id);
}
```

**AES CCM (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0x9c, 0xde, 0xba, 0xee, 0xe8, 0x69, 0x0b, 0x68, 0x75, 0x10, 0x70, 0x69, 0x1f, 0x49, 0x59, 0x36,
    0x68, 0xa6, 0xde, 0x12, 0xd3, 0xa9, 0x48, 0xb3, 0x8d, 0xdb, 0xd3, 0xf7, 0x52, 0x18, 0xb2, 0xd4
  };
  uint8_t nonce_buf[] = {0xaf, 0x1a, 0x97, 0xd4, 0x31, 0x51, 0xf5, 0xea, 0x9c, 0x48, 0xad, 0x36, 0xa3};
  uint8_t ad_buf[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13
  };
  uint8_t plain_msg_buf[] = {
    0x3c, 0xbb, 0x08, 0xf1, 0x33, 0x27, 0x0e, 0x44, 0x54, 0xbc, 0xaa, 0xa0, 0xf2, 0x0f, 0x6d, 0x63,
    0xc3, 0x8b, 0x65, 0x72, 0xe7, 0x66
  };
  uint8_t cipher_buf[22];
  uint8_t tag_buf[16];
  size_t tag_len;
  size_t out_len;
  uint32_t out_total;
  uint32_t stream_cnt;
  uint32_t stream_block_size = 14;                      // Block size for streaming

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_aead_operation_t aead_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES CCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CCM);

  // Import a volatile plain key for AES CCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES CCM stream encryption and decryption
  // Expected ciphertext:
  // 39 66 93 0a 2a e8 fd d8 f4 0e 70 07 f3 fd e0 bd 6e b4 8a 46 e6 d2
  // Expected tag: 7c 0c 1b a4 bf d2 bd 21 5b 0c d9 21 f0 6a 8f 3b
  aead_op = psa_aead_operation_init();
  ret = psa_aead_encrypt_setup(&aead_op, key_id, PSA_ALG_CCM);
  ret = psa_aead_set_lengths(&aead_op, sizeof(ad_buf), sizeof(plain_msg_buf));
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0;                                             // Streaming block
  out_total = 0;
  while ((sizeof(plain_msg_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          plain_msg_buf + (stream_cnt * stream_block_size), stream_block_size,
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
  }
    ret = psa_aead_update(&aead_op,                         // Last block
                          plain_msg_buf + (stream_cnt * stream_block_size),
                          sizeof(plain_msg_buf) - (stream_cnt * stream_block_size),
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
    out_total += out_len;

    ret = psa_aead_finish(&aead_op,                         // Generate tag
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len,
                          tag_buf, sizeof(tag_buf),
                          &tag_len);
  out_total += out_len;

  aead_op = psa_aead_operation_init();
  ret = psa_aead_decrypt_setup(&aead_op, key_id, PSA_ALG_CCM);
  ret = psa_aead_set_lengths(&aead_op, sizeof(ad_buf), sizeof(plain_msg_buf));
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0;                                           // Streaming block
  out_total = 0;
  while ((sizeof(cipher_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          cipher_buf + (stream_cnt * stream_block_size), stream_block_size,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
  }

    ret = psa_aead_update(&aead_op,                           // Last block
                        cipher_buf + (stream_cnt * stream_block_size),
                        sizeof(cipher_buf) - (stream_cnt * stream_block_size),
                        plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                        &out_len);
    out_total += out_len;
    ret = psa_aead_verify(&aead_op,                           // Verify tag
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len,
                          tag_buf, sizeof(tag_buf));
    out_total += out_len;

    // Destroy a volatile plain key for AES CCM
    ret = psa_destroy_key(key_id);
}
```

**AES GCM (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0x5f, 0xe0, 0x1c, 0x4b, 0xaf, 0x01, 0xcb, 0xe0, 0x77, 0x96, 0xd5, 0xaa, 0xef, 0x6e, 0xc1, 0xf4,
    0x51, 0x93, 0xa9, 0x8a, 0x22, 0x35, 0x94, 0xae, 0x4f, 0x0e, 0xf4, 0x95, 0x2e, 0x82, 0xe3, 0x30
  };
  uint8_t nonce_buf[] = {0xbd, 0x58, 0x73, 0x21, 0x56, 0x6c, 0x7f, 0x1a, 0x5d, 0xd8, 0x65, 0x2d};
  uint8_t ad_buf[] = {
    0x90, 0x13, 0x61, 0x78, 0x17, 0xdd, 0xa9, 0x47, 0xe1, 0x35, 0xee, 0x6d, 0xd3, 0x65, 0x33, 0x82
  };
  uint8_t plain_msg_buf[] = {
    0x88, 0x1d, 0xc6, 0xc7, 0xa5, 0xd4, 0x50, 0x9f, 0x3c, 0x4b, 0xd2, 0xda, 0xab, 0x08, 0xf1, 0x65,
    0xdd, 0xc2, 0x04, 0x48, 0x9a, 0xa8, 0x13, 0x45, 0x62, 0xa4, 0xea, 0xc3, 0xd0, 0xbc, 0xad, 0x79,
    0x65, 0x84, 0x7b, 0x10, 0x27, 0x33, 0xbb, 0x63, 0xd1, 0xe5, 0xc5, 0x98, 0xec, 0xe0, 0xc3, 0xe5,
    0xda, 0xdd, 0xdd
  };
  uint8_t cipher_buf[51];
  uint8_t tag_buf[16];
  size_t tag_len;
  size_t out_len;
  uint32_t out_total;
  uint32_t stream_cnt;
  uint32_t stream_block_size = 14;                              // Block size for streaming

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_aead_operation_t aead_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES GCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_GCM);

  // Import a volatile plain key for AES GCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES GCM stream encryption and decryption
  // Expected ciphertext:
  // 16 e3 75 b4 97 3b 33 9d 3f 74 6c 1c 5a 56 8b c7 52 6e 90 9d df f1 e1 9c 95 c9 4a 6c cf f2 10 c9
  // a4 a4 06 79 de 57 60 c3 96 ac 0e 2c eb 12 34 f9 f5 fe 26
  // Expected tag: ab d3 d2 6d 65 a6 27 5f 7a 4f 56 b4 22 ac ab 49
  aead_op = psa_aead_operation_init();
  ret = psa_aead_encrypt_setup(&aead_op, key_id, PSA_ALG_GCM);
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0; // Streaming block
  out_total = 0;
  while ((sizeof(plain_msg_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          plain_msg_buf + (stream_cnt * stream_block_size), stream_block_size,
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
    }

    ret = psa_aead_update(&aead_op,                                     // Last block
                        plain_msg_buf + (stream_cnt * stream_block_size),
                        sizeof(plain_msg_buf) - (stream_cnt * stream_block_size),
                        cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                        &out_len);
    out_total += out_len;

    ret = psa_aead_finish(&aead_op,                                       // Generate tag
                        cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                        &out_len,
                        tag_buf, sizeof(tag_buf),
                        &tag_len);
    out_total += out_len;

  aead_op = psa_aead_operation_init();
  ret = psa_aead_decrypt_setup(&aead_op, key_id, PSA_ALG_GCM);
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0;                                                       // Streaming block
  out_total = 0;
  while ((sizeof(cipher_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          cipher_buf + (stream_cnt * stream_block_size), stream_block_size,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
  }

    ret = psa_aead_update(&aead_op,                                         // Last block
                          cipher_buf + (stream_cnt * stream_block_size),
                          sizeof(cipher_buf) - (stream_cnt * stream_block_size),
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
    out_total += out_len;

    ret = psa_aead_verify(&aead_op,                                         // Verify tag
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len,
                          tag_buf, sizeof(tag_buf));
    out_total += out_len;

    // Destroy a volatile plain key for AES GCM
    ret = psa_destroy_key(key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image26](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image26.png)

The following table describes the implementation status of the PSA Crypto AEAD platform example.

|**Algorithm**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|AES CCM|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES GCM|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|CHACHA20_POLY1305|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|

> **Notes**:
> 
> - The AEAD platform example uses default nonce (12-byte for GCM) and tag length (16-byte for CCM and GCM).
> - The multi-part AEAD operations are only available on GSDK v4.2.0 and higher.
> - The multi-part AEAD operations for CHACHA20_POLY1305 are not yet implemented.
> - The multi-part AEAD operations for a shortened tag length (AES CCM and GCM) are not yet implemented.
> - The multi-part GCM operations do not support non-12-byte nonce (GCM with Non-Recommended IV Lengths).
> - The AEAD platform example for multi-part AEAD operations is pending for fully-featured multi-part AEAD drivers.

###### Key Derivation

A Key Derivation Function (KDF) derives one or many secret keys from a secret value such as a master key, a password, or a pass-phrase using a pseudo-random function. The typical usage of a key derivation function is to use a secret, such as a password or an ECDH shared secret, and a salt to produce a symmetric key and initialization vector (IV) for use with AES.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HKDF (SHA-1)</p>
            </td>
            <td>
                <p><code>MBEDTLS_MD_SHA1</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_HKDF(PSA_ALG_SHA_1)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>HKDF (SHA-2)</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_MD_SHA224</code><br>
                    • <code>MBEDTLS_MD_SHA256</code><br>
                    • <code>MBEDTLS_MD_SHA384</code><br>
                    • <code>MBEDTLS_MD_SHA512</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_512)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PBKDF2 (SHA-1)</p>
            </td>
            <td>
                <p><code>MBEDTLS_MD_SHA1</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PBKDF2 (SHA-2)</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_MD_SHA224</code><br>
                    • <code>MBEDTLS_MD_SHA256</code><br>
                    • <code>MBEDTLS_MD_SHA384</code><br>
                    • <code>MBEDTLS_MD_SHA512</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_512)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PBKDF2 CMAC</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_PBKDF2_AES_CMAC_PRF_128</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDH + HKDF</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

|**Algorithm**|**Key Type**|**Key Size in Bits**|**Key Usage Flag**|
|---|---|---|---|
|- PSA_ALG_HKDF(PSA_ALG_SHA_1)|PSA_KEY_TYPE_DERIVE|Multiple of 8|PSA_KEY_USAGE_DERIVE|
|- PSA_ALG_HKDF(PSA_ALG_SHA_224)| | | |
|- PSA_ALG_HKDF(PSA_ALG_SHA_256)| | | |
|- PSA_ALG_HKDF(PSA_ALG_SHA_384)| | | |
|- PSA_ALG_HKDF(PSA_ALG_SHA_512)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_224)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_384)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_512)| | | |
|PSA_ALG_PBKDF2_AES_CMAC_PRF_128| | | |

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_HKDF(PSA_ALG_SHA_1)|HKDF and SHA-1|
|PSA_ALG_HKDF(PSA_ALG_SHA_224)|HKDF and SHA-224|
|PSA_ALG_HKDF(PSA_ALG_SHA_256)|HKDF and SHA-256|
|PSA_ALG_HKDF(PSA_ALG_SHA_384)|HKDF and SHA-384|
|PSA_ALG_HKDF(PSA_ALG_SHA_512)|HKDF and SHA-512|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)|PBKDF2 and SHA-1|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_224)|PBKDF2 and SHA-224|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)|PBKDF2 and SHA-256|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_384)|PBKDF2 and SHA-384|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_512)|PBKDF2 and SHA-512|
|PSA_ALG_PBKDF2_AES_CMAC_PRF_128|PBKDF2|
|PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))|ECDH and HKDF and SHA-X|

> **Note**:
> 
> - It should add the components for the derived key algorithm to implement the HKDF. For example, it requires the `CTR Mode` component if the derived key algorithm is `PSA_ALG_CTR`.
> - Refer to [Key Agreement (ECDH)](#key-agreement-ecdh) to add the ECDH components to derive the shared secret for the ECDH + HKDF algorithm (`PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))`).

**Single-Part Functions**

|**Mbed TLS**|**PSA Crypto**|
|---|---|
|int mbedtls_hkdf(…)|psa_status_t sl_psa_key_derivation_single_shot(…)|
|int mbedtls_pkcs5_pbkdf2_hmac(…)|psa_status_t sl_psa_key_derivation_single_shot(…)|

> **Note**: The `sl_psa_key_derivation_single_shot(…)` is a **Silicon Labs custom API**. It can only use on HSE-SVH devices.

**Multi-Part Operations**

|**Mbed TLS**|**PSA Crypto**|
|---|---|
|—|psa_key_derivation_operation_t psa_key_derivation_operation_init(void)|
|—|psa_status_t psa_key_derivation_setup(…)|
|—|psa_status_t psa_key_derivation_get_capacity(…)|
|—|psa_status_t psa_key_derivation_set_capacity(…)|
|—|psa_status_t psa_key_derivation_input_bytes(…)|
|—|psa_status_t psa_key_derivation_input_key(…)|
|—|psa_status_t psa_key_derivation_output_bytes(…)|
|—|psa_status_t psa_key_derivation_output_key(…)|
|—|psa_status_t psa_key_derivation_abort(…)|

> **Note**: The multi-part operation allows the data to be processed for KDF in fragments instead of all at once.

**Quick Reference Examples HKDF (SHA-256)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t hkdf_ikm[] = {
    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
  };
  uint8_t hkdf_salt[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c};
  uint8_t hkdf_info[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
  uint8_t key_buf[32];
  size_t key_len;
  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t hkdf_key_id;
  psa_key_attributes_t key_attr;
  psa_key_derivation_operation_t kdf_op;

  ret = psa_crypto_init();

  // Set up attributes for a volatile master plain key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_DERIVE);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_HKDF(PSA_ALG_SHA_256));

  // Import a volatile master plain key
  ret = psa_import_key(&key_attr, hkdf_ikm, sizeof(hkdf_ikm), &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (HKDF SHA256) a volatile plain key for AES CTR
  #if defined(SEMAILBOX_PRESENT) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)

  // Silicon Labs custom API for Secure Vault High devices
  ret = sl_psa_key_derivation_single_shot(PSA_ALG_HKDF(PSA_ALG_SHA_256), master_key_id,
                                          hkdf_info, sizeof(hkdf_info),
                                          hkdf_salt, sizeof(hkdf_salt),
                                          0, &key_attr, &hkdf_key_id);
  #else
  kdf_op = psa_key_derivation_operation_init();
  ret = psa_key_derivation_setup(&kdf_op, PSA_ALG_HKDF(PSA_ALG_SHA_256));
  ret = psa_key_derivation_set_capacity(&kdf_op, sizeof(key_buf));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SALT, hkdf_salt, sizeof(hkdf_salt));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_info, sizeof(hkdf_info));
  ret = psa_key_derivation_input_key(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, master_key_id);
  ret = psa_key_derivation_output_key(&key_attr, &kdf_op, &hkdf_key_id);
  ret = psa_key_derivation_abort(&kdf_op);
  #endif

  // Export derived volatile plain key (expected value of HKDF SHA256):
  // 3c b2 5f 25 fa ac d5 7a 90 43 4f 64 d0 36 2f 2a 2d 2d 0a 90 cf 1a 5a 4c 5d b0 2d 56 ec c4 c5 bf
  ret = psa_export_key(hkdf_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(hkdf_key_id);
}
```

**PBKDF2-HMAC-SHA256 (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t pbkdf2_ikm[] = {0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64};
  uint8_t pbkdf2_salt[] = {0x73, 0x61, 0x6c, 0x74};
  uint8_t key_buf[32];
  size_t key_len;
  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t pbkdf2_key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();
  // Set up attributes for a volatile master plain key

  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_DERIVE);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256));

  // Import a volatile master plain key
  ret = psa_import_key(&key_attr, pbkdf2_ikm, sizeof(pbkdf2_ikm), &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (PBKDF2 SHA256 with 4096 iterations) a volatile plain key for AES CTR
  // Silicon Labs custom API for Secure Vault High devices
  ret = sl_psa_key_derivation_single_shot(PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256), master_key_id,
                                          NULL, 0,
                                          pbkdf2_salt, sizeof(pbkdf2_salt),
                                          4096, &key_attr, &pbkdf2_key_id);

  // Export derived volatile plain key (expected value of PBKDF2 SHA256 with 4096 iterations):
  // c5 e4 78 d5 92 88 c8 41 aa 53 0d b6 84 5c 4c 8d 96 28 93 a0 01 ce 4e 11 a4 96 38 73 aa 98 13 4a
  ret = psa_export_key(pbkdf2_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(pbkdf2_key_id);
}
```

> **Note**: The PBKDF2-HMAC implementation of PSA Crypto is not yet available.

**PBKDF2-AES-CMAC-PRF-128 (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t pbkdf2_ikm[] = {0x4a, 0x30, 0x31, 0x4e, 0x4d, 0x45};
  uint8_t pbkdf2_salt[] = {
    0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x37, 0x33, 0x35, 0x63, 0x38, 0x37, 0x62, 0x34, 0x4f, 0x70,
    0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x44, 0x65, 0x6d, 0x6f
  };
  uint8_t key_buf[16];
  size_t key_len;
  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t pbkdf2_key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile master plain key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_DERIVE);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PBKDF2_AES_CMAC_PRF_128);

  // Import a volatile master plain key
  ret = psa_import_key(&key_attr, pbkdf2_ikm, sizeof(pbkdf2_ikm), &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (PBKDF2 AES_CMAC_PRF_128 with 16384 iterations) a volatile plain key for AES CTR
  // Silicon Labs custom API for Secure Vault High devices
  ret = sl_psa_key_derivation_single_shot(PSA_ALG_PBKDF2_AES_CMAC_PRF_128, master_key_id,
                                          NULL, 0,
                                          pbkdf2_salt, sizeof(pbkdf2_salt),
                                          16384, &key_attr, &pbkdf2_key_id);

  // Export derived volatile plain key (expected value of PBKDF2 AES_CMAC_PRF_128 with 16384 iterations):
  // 8b 27 be ed 7e 7a 4d d6 c5 31 38 c8 79 a8 e3 3c
  
  ret = psa_export_key(pbkdf2_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(pbkdf2_key_id);
}
```

> **Note**:
> 
> - The PBKDF2-AES-CMAC-PRF-128 implementation of PSA Crypto is not yet available.
> - EFR32xG21B (HSE-SVH) devices do not support PBKDF2-AES-CMAC-PRF-128.

**ECDH and HKDF**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t client_private_key[] = {
    0xc8, 0x8f, 0x01, 0xf5, 0x10, 0xd9, 0xac, 0x3f, 0x70, 0xa2, 0x92, 0xda, 0xa2, 0x31, 0x6d, 0xe5,
    0x44, 0xe9, 0xaa, 0xb8, 0xaf, 0xe8, 0x40, 0x49, 0xc6, 0x2a, 0x9c, 0x57, 0x86, 0x2d, 0x14, 0x33
  };
  uint8_t client_public_key[] = { // Uncompressed point format
    0x04, 0xda, 0xd0, 0xb6, 0x53, 0x94, 0x22, 0x1c, 0xf9, 0xb0, 0x51, 0xe1, 0xfe, 0xca, 0x57, 0x87, 0xd0,
    0x98, 0xdf, 0xe6, 0x37, 0xfc, 0x90, 0xb9, 0xef, 0x94, 0x5d, 0x0c, 0x37, 0x72, 0x58, 0x11, 0x80,
    0x52, 0x71, 0xa0, 0x46, 0x1c, 0xdb, 0x82, 0x52, 0xd6, 0x1f, 0x1c, 0x45, 0x6f, 0xa3, 0xe5, 0x9a,
    0xb1, 0xf4, 0x5b, 0x33, 0xac, 0xcf, 0x5f, 0x58, 0x38, 0x9e, 0x05, 0x77, 0xb8, 0x99, 0x0b, 0xb3
  };
  uint8_t server_private_key[] = {
    0xc6, 0xef, 0x9c, 0x5d, 0x78, 0xae, 0x01, 0x2a, 0x01, 0x11, 0x64, 0xac, 0xb3, 0x97, 0xce, 0x20,
    0x88, 0x68, 0x5d, 0x8f, 0x06, 0xbf, 0x9b, 0xe0, 0xb2, 0x83, 0xab, 0x46, 0x47, 0x6b, 0xee, 0x53
  };
  uint8_t server_public_key[] = { // Uncompressed point format
    0x04, 0xd1, 0x2d, 0xfb, 0x52, 0x89, 0xc8, 0xd4, 0xf8, 0x12, 0x08, 0xb7, 0x02, 0x70, 0x39, 0x8c, 0x34,
    0x22, 0x96, 0x97, 0x0a, 0x0b, 0xcc, 0xb7, 0x4c, 0x73, 0x6f, 0xc7, 0x55, 0x44, 0x94, 0xbf, 0x63,
    0x56, 0xfb, 0xf3, 0xca, 0x36, 0x6c, 0xc2, 0x3e, 0x81, 0x57, 0x85, 0x4c, 0x13, 0xc5, 0x8d, 0x6a,
    0xac, 0x23, 0xf0, 0x46, 0xad, 0xa3, 0x0f, 0x83, 0x53, 0xe7, 0x4f, 0x33, 0x03, 0x98, 0x72, 0xab
  };
  uint8_t hkdf_salt[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c};
  uint8_t hkdf_info[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
  uint8_t key_buf[32];
  size_t key_len;

  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t hkdf_key_id;
  psa_key_attributes_t key_attr;
  psa_key_derivation_operation_t kdf_op;

  ret = psa_crypto_init();

  // Set up attributes for a volatile master plain key (algorithm for ECDH and HKDF)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));

  // Import a volatile master plain key (client private key)
  ret = psa_import_key(&key_attr, client_private_key, sizeof(client_private_key),
  &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (HKDF SHA256) a volatile plain key from ECDH shared secret (server public key) for AES CTR
  kdf_op = psa_key_derivation_operation_init();
  ret = psa_key_derivation_setup(&kdf_op, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));
  ret = psa_key_derivation_set_capacity(&kdf_op, sizeof(key_buf));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SALT, hkdf_salt, sizeof(hkdf_salt));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_info, sizeof(hkdf_info));
  ret = psa_key_derivation_key_agreement(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, master_key_id, server_public_key,
  sizeof(server_public_key));
  ret = psa_key_derivation_output_key(&key_attr, &kdf_op, &hkdf_key_id);
  ret = psa_key_derivation_abort(&kdf_op);

  // Export derived volatile plain key (client shared secret):
  // B7 CA BD A7 42 60 DE D5 4C 4C 11 FA BC A3 56 4B 77 35 CC 9F 89 E9 BF E8 08 24 8A F3 54 99 B0 55
  ret = psa_export_key(hkdf_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(hkdf_key_id);

  // Set up attributes for a volatile master plain key (algorithm for ECDH and HKDF)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));

  // Import a volatile master plain key (server private key)
  ret = psa_import_key(&key_attr, server_private_key, sizeof(server_private_key),
                      &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (HKDF SHA256) a volatile plain key from ECDH shared secret (client public key) for AES CTR
  kdf_op = psa_key_derivation_operation_init();
  ret = psa_key_derivation_setup(&kdf_op, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));
  ret = psa_key_derivation_set_capacity(&kdf_op, sizeof(key_buf));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SALT, hkdf_salt, sizeof(hkdf_salt));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_info, sizeof(hkdf_info));
  ret = psa_key_derivation_key_agreement(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, master_key_id, client_public_key,
                                        sizeof(client_public_key));
  ret = psa_key_derivation_output_key(&key_attr, &kdf_op, &hkdf_key_id);
  ret = psa_key_derivation_abort(&kdf_op);

  // Export derived volatile plain key (server shared secret):
  // B7 CA BD A7 42 60 DE D5 4C 4C 11 FA BC A3 56 4B 77 35 CC 9F 89 E9 BF E8 08 24 8A F3 54 99 B0 55
  ret = psa_export_key(hkdf_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(hkdf_key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image27](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image27.png)

The following table describes the implementation status of the PSA Crypto KDF platform example.

|**Algorithm**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|HKDF|Y|Y|Y|Hardware acceleration only on HSE-SVH devices with Silicon Labs custom API.|
|ECDH + HKDF|Y|Y|Y|Hardware acceleration (HKDF) only on HSE-SVH devices with Silicon Labs custom API.|

> **Note**:
> 
> - The PBKDF2 implementation of PSA Crypto is not yet available.
> - The ECDH + HKDF algorithm does not apply to the [wrapped key](04-key-management-in-psa-crypto#key-lifetimes).

###### Asymmetric Cryptographic Operation

###### Asymmetric Signature (ECDSA and EdDSA) (heading level 7)

In modern cryptography, the Elliptic-Curve-based signatures (like ECDSA and EdDSA) are widely used because of shorter key lengths, shorter signature lengths, higher security levels (for the same key length), and better performance.

The Elliptic Curve Digital Signature Algorithm (ECDSA) is a cryptographically secure digital signature scheme based on the Elliptic Curve Cryptography (ECC). The Edwards-curve Digital Signature Algorithm (EdDSA) is a fast digital signature algorithm, using elliptic curves in Edwards form (like Ed25519 and Ed448).

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>ECDSA (SHA-1)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_ECDSA(PSA_ALG_SHA_1)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDSA (SHA-2)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_512)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDSA (Any hash algorithm)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDSA (No hashing)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_ECDSA_ANY</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EdDSA</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_PURE_EDDSA</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The hash-and-sign algorithms `(PSA_ALG_ECDSA(hash_alg)` and `PSA_ALG_ECDSA(PSA_ALG_ANY_HASH))` include the hashing step for ECDSA.

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>PSA_ALG_ECDSA_ANY</code></td>
            <td><code>PSA_ECC_FAMILY_SECP_R1</code></td>
            <td>
                secp192r1 : 192<br>
                secp224r1 : 224<br>
                secp256r1 : 256<br>
                secp384r1 : 384<br>
                secp521r1 : 521
            </td>
            <td>
                <code>PSA_KEY_USAGE_SIGN_HASH</code><br>
                <code>PSA_KEY_USAGE_VERIFY_HASH</code>
            </td>
        </tr>
        <tr>
            <td></td>
            <td><code>PSA_ECC_FAMILY_SECP_K1</code></td>
            <td>secp256k1 : 256</td>
            <td></td>
        </tr>
        <tr>
            <td>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_1)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_224)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_256)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_384)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_512)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)</code>
            </td>
            <td><code>PSA_ECC_FAMILY_SECP_R1</code></td>
            <td>
                secp192r1 : 192<br>
                secp224r1 : 224<br>
                secp256r1 : 256<br>
                secp384r1 : 384<br>
                secp521r1 : 521
            </td>
            <td>
                <code>PSA_KEY_USAGE_SIGN_MESSAGE</code><br>
                <code>PSA_KEY_USAGE_VERIFY_MESSAGE</code>
            </td>
        </tr>
        <tr>
            <td></td>
            <td><code>PSA_ECC_FAMILY_SECP_K1</code></td>
            <td>secp256k1 : 256</td>
            <td></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_PURE_EDDSA</code></td>
            <td><code>PSA_ECC_FAMILY_TWISTED_EDWARDS</code></td>
            <td>Edwards25519 : 255</td>
            <td>
                <code>PSA_KEY_USAGE_SIGN_MESSAGE</code><br>
                <code>PSA_KEY_USAGE_VERIFY_MESSAGE</code>
            </td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_ECDSA_ANY|ECDSA|
|PSA_ALG_ECDSA(PSA_ALG_SHA_1)|ECDSA and SHA-1|
|PSA_ALG_ECDSA(PSA_ALG_SHA_224)|ECDSA and SHA-224|
|PSA_ALG_ECDSA(PSA_ALG_SHA_256)|ECDSA and SHA-256|
|PSA_ALG_ECDSA(PSA_ALG_SHA_384)|ECDSA and SHA-384|
|PSA_ALG_ECDSA(PSA_ALG_SHA_512)|ECDSA and SHA-512|
|PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)|ECDSA and SHA-X|

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_PURE_EDDSA|EdDSA|

|**PSA_ECC_FAMILY_SECP_R1**|**Security Software Components**|
|---|---|
|secp192r1|secp192r1|
|secp224r1|secp224r1|
|secp256r1|secp256r1|
|secp384r1|secp384r1|
|secp521r1|secp521r1|

|**PSA_ECC_FAMILY_SECP_K1**|**Security Software Components**|
|---|---|
|secp256k1|secp256k1|

|**PSA_ECC_FAMILY_TWISTED_EDWARDS**|**Security Software Components**|
|---|---|
|Edwards25519|edwards25519|

|**Built-in Key**|**Security Software Components**|
|---|---|
|secp256r1 keys in SE OTP|Built-In Keys|

**Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Hash-and-sign<br>—</p>
            </td>
            <td>
                <p>Hash-and-sign<br>
                    <code>psa_status_t psa_sign_message(…)</code><br>
                    <code>psa_status_t psa_verify_message(…)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Precomputed hash<br>
                    <code>int mbedtls_ecdsa_write_signature(…)</code><br>
                    <code>int mbedtls_ecdsa_read_signature(…)</code>
                </p>
            </td>
            <td>
                <p>Precomputed hash<br>
                    <code>psa_status_t psa_sign_hash(…)</code><br>
                    <code>psa_status_t psa_verify_hash(…)</code>
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Quick Reference Examples**

**ECDSA on secp256r1 (Precomputed Hash)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t hash_data[] = {
    0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
  };
  uint8_t public_key[65]; // Uncompressed point format
  size_t pubkey_len;
  uint8_t signature_buf[64];
  size_t signature_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_bits(&key_attr, 256);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

  // Generate a random volatile private plain key
  ret = psa_generate_key(&key_attr, &key_id);

  // Sign a hash with a volatile private plain key
  ret = psa_sign_hash(key_id,
                      PSA_ALG_ECDSA_ANY,
                      hash_data,
                      sizeof(hash_data),
                      signature_buf,
                      sizeof(signature_buf),
                      &signature_len);

  // Verify a signature with a volatile private plain key
  ret = psa_verify_hash(key_id,
                        PSA_ALG_ECDSA_ANY,
                        hash_data,
                        sizeof(hash_data),
                        signature_buf,
                        signature_len);

  // Export a public key from a volatile private plain key and then destroy the private key
  ret = psa_export_public_key(key_id,
                              public_key,
                              sizeof(public_key),
                              &pubkey_len);

  ret = psa_destroy_key(key_id);

  // Set up attributes for a public key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

  // Import a public key
  ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

  // Verify a signature with a public key and then destroy the public key
  ret = psa_verify_hash(key_id,
                        PSA_ALG_ECDSA_ANY,
                        hash_data,
                        sizeof(hash_data),
                        signature_buf,
                        signature_len);

  ret = psa_destroy_key(key_id);
}
```

**ECDSA on secp256r1 (Hash-and-Sign)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t ecdsa_msg[] = {
    0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
  };
  uint8_t public_key[65];                                     // Uncompressed point format
  size_t pubkey_len;
  uint8_t signature_buf[64];
  size_t signature_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_bits(&key_attr, 256);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));

  // Generate a random volatile private plain key
  ret = psa_generate_key(&key_attr, &key_id);

  // Hash-and-Sign (SHA-256) a message with a volatile private plain key
  ret = psa_sign_message(key_id,
                        PSA_ALG_ECDSA(PSA_ALG_SHA_256),
                        ecdsa_msg,
                        sizeof(ecdsa_msg),
                        signature_buf,
                        sizeof(signature_buf),
                        &signature_len);

  // Hash (SHA-256) a message and verify a signature with a volatile private plain key
  ret = psa_verify_message(key_id,
                          PSA_ALG_ECDSA(PSA_ALG_SHA_256),
                          ecdsa_msg,
                          sizeof(ecdsa_msg),
                          signature_buf,
                          signature_len);

  // Export a public key from a volatile private plain key and then destroy the private key
  ret = psa_export_public_key(key_id,
                              public_key,
                              sizeof(public_key),
                              &pubkey_len);

  ret = psa_destroy_key(key_id);

  // Set up attributes for a public key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));

  // Import a public key
  ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

  // Hash (SHA-256) and verify a signature with a public key and then destroy the public key
  ret = psa_verify_message(key_id,
                          PSA_ALG_ECDSA(PSA_ALG_SHA_256),
                          ecdsa_msg,
                          sizeof(ecdsa_msg),
                          signature_buf,
                          signature_len);

  ret = psa_destroy_key(key_id);
}
```

**ECDSA with Built-in Private Device Key (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
 uint8_t hash_data[] = {
  0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
  0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
 };
 uint8_t public_key[65];                                  // Uncompressed point format
 size_t pubkey_len;
 uint8_t signature_buf[64];
 size_t signature_len;

 psa_status_t ret;
 psa_key_id_t key_id;
 psa_key_attributes_t key_attr;

 ret = psa_crypto_init();

 // Sign a hash with a built-in private device key
 ret = psa_sign_hash(SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID,
                    PSA_ALG_ECDSA_ANY,
                    hash_data,
                    sizeof(hash_data),
                    signature_buf,
                    sizeof(signature_buf),
                    &signature_len);

 // Verify a signature with a built-in private device key
 ret = psa_verify_hash(SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID,
                      PSA_ALG_ECDSA_ANY,
                      hash_data,
                      sizeof(hash_data),
                      signature_buf,
                      signature_len);

 // Export a built-in public device key
 ret = psa_export_public_key(SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID,
                            public_key,
                            sizeof(public_key),
                            &pubkey_len);

 // Set up attributes for a public device key
 key_attr = psa_key_attributes_init();
 psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
 psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

 // Import a public device key
 ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

 // Verify a signature with a public device key
 ret = psa_verify_hash(key_id,
                      PSA_ALG_ECDSA_ANY,
                      hash_data,
                      sizeof(hash_data),
                      signature_buf,
                      signature_len);

 // Destroy a public device key
 ret = psa_destroy_key(key_id);
#endif
}
```

**EdDSA on Ed25519 (HSE only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
#if defined(SEMAILBOX_PRESENT)
  uint8_t eddsa_msg[] = {
    0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
  };
  uint8_t ed25519_private[] = {
    0x83, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e,
    0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42
  };
  uint8_t ed25519_public[] = {
    0xec, 0x17, 0x2b, 0x93, 0xad, 0x5e, 0x56, 0x3b, 0xf4, 0x93, 0x2c, 0x70, 0xe1, 0x24, 0x50, 0x34,
    0xc3, 0x54, 0x67, 0xef, 0x2e, 0xfd, 0x4d, 0x64, 0xeb, 0xf8, 0x19, 0x68, 0x34, 0x67, 0xe2, 0xbf
  };
  uint8_t signature_buf[64];
  size_t signature_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile private plain key (Ed25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA);

  // Import a volatile private plain key
  ret = psa_import_key(&key_attr, ed25519_private, sizeof(ed25519_private), &key_id);

  // Hash-and-Sign a message with a volatile private plain key (expected EdDSA signature):
  // dc 2a 44 59 e7 36 96 33 a5 2b 1b f2 77 83 9a 00 20 10 09 a3 ef bf 3e cb 69 be a2 18 6c 26 b5 89
  // 09 35 1f c9 ac 90 b3 ec fd fb c7 c6 64 31 e0 30 3d ca 17 9c 13 8a c1 7a d9 be f1 17 73 31 a7 04
  ret = psa_sign_message(key_id,
                        PSA_ALG_PURE_EDDSA,
                        eddsa_msg,
                        sizeof(eddsa_msg),
                        signature_buf,
                        sizeof(signature_buf),
                        &signature_len);

  // Destroy a volatile private plain key
  ret = psa_destroy_key(key_id);

  // Set up attributes for a public key (Ed25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA);

  // Import a public key
  ret = psa_import_key(&key_attr, ed25519_public, sizeof(ed25519_public), &key_id);

  // Hash a message and verify the signature with a public key
  ret = psa_verify_message(key_id,
                          PSA_ALG_PURE_EDDSA,
                          eddsa_msg,
                          sizeof(eddsa_msg),
                          signature_buf,
                          signature_len);

  // Destroy a public key
  ret = psa_destroy_key(key_id);
#endif
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image28](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image28.png)

The following table describes the implementation status of the PSA Crypto DSA platform example.

|**ECC Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Edwards25519|—|—|Y|Only on HSE devices with hardware acceleration.|
|Public Sign Key|—|—|Y|—|
|Public Command Key|—|—|Y|—|
|Private Device Key|—|—|Y|Only on HSE-SVH devices.|

> **Note**:
> 
> - This example does not include secp224r1 and secp256k1. The secp256k1 ECDSA on HSE devices is not yet implemented.
> - The PSA Crypto does not yet support software fallback on the Edwards25519.
> - The HSE-SVM devices require SE firmware v1.2.11 or higher (EFR32xG21) and v2.1.7 or higher (other HSE devices) to support hardware acceleration on Edwards25519. This feature also requires GSDK v4.0.1 or higher.

###### Key Agreement (ECDH)

The Elliptic Curve Diffie-Hellman (ECDH) is an anonymous key agreement protocol that allows two parties, each having an elliptic-curve private-public key pair, to establish a shared secret over an insecure channel.

**Algorithms**

|**Algorithm**|**Mbed TLS**|**PSA Crypto**|
|---|---|---|
|ECDH|—|PSA_ALG_ECDH|
|ECDH and HKDF|—|PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))|

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>PSA_ALG_ECDH</p>
            </td>
            <td>
                <p>PSA_ECC_FAMILY_SECP_R1</p>
            </td>
            <td>
                <p>
                    • secp192r1 : 192<br>
                    • secp224r1 : 224<br>
                    • secp256r1 : 256<br>
                    • secp384r1 : 384<br>
                    • secp521r1 : 521
                </p>
            </td>
            <td>
                <p>PSA_KEY_USAGE_DERIVE</p>
            </td>
        </tr>
        <tr>
            <td></td>
            <td>
                <p>PSA_ECC_FAMILY_SECP_K1</p>
            </td>
            <td>
                <p>secp256k1 : 256</p>
            </td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td>
                <p>PSA_ECC_FAMILY_MONTGOMERY</p>
            </td>
            <td>
                <p>
                    • Curve25519 : 255<br>
                    • Curve448 : 448
                </p>
            </td>
            <td></td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_ECDH|ECDH|

|**PSA_ECC_FAMILY_SECP_R1**|**Security Software Components**|
|---|---|
|secp192r1|secp192r1|
|secp224r1|secp224r1|
|secp256r1|secp256r1|
|secp384r1|secp384r1|
|secp521r1|secp521r1|

|**PSA_ECC_FAMILY_SECP_K1**|**Security Software Components**|
|---|---|
|secp256k1|secp256k1|

|**PSA_ECC_FAMILY_MONTGOMERY**|**Security Software Components**|
|---|---|
|Curve25519|Curve25519|
|Curve448|Curve448|

**Functions**

|**Mbed TLS**|**PSA Crypto**|
|---|---|
|int mbedtls_ecdh_compute_shared(…)|psa_status_t psa_raw_key_agreement(…)|
|—|psa_status_t psa_key_derivation_key_agreement(…)|

> **Note**: For the `psa_key_derivation_key_agreement(…)` function, refer to the PSA Crypto [KDF](#key-derivation) quick reference (ECDH and HKDF) and platform examples for details.

**Quick Reference Examples ECDH on secp256r1**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t client_private_key[] = {
    0xc8, 0x8f, 0x01, 0xf5, 0x10, 0xd9, 0xac, 0x3f, 0x70, 0xa2, 0x92, 0xda, 0xa2, 0x31, 0x6d, 0xe5,
    0x44, 0xe9, 0xaa, 0xb8, 0xaf, 0xe8, 0x40, 0x49, 0xc6, 0x2a, 0x9c, 0x57, 0x86, 0x2d, 0x14, 0x33
  };

  uint8_t client_public_key[] = { // Uncompressed point format
    0x04, 0xda, 0xd0, 0xb6, 0x53, 0x94, 0x22, 0x1c, 0xf9, 0xb0, 0x51, 0xe1, 0xfe, 0xca, 0x57, 0x87, 0xd0,
    0x98, 0xdf, 0xe6, 0x37, 0xfc, 0x90, 0xb9, 0xef, 0x94, 0x5d, 0x0c, 0x37, 0x72, 0x58, 0x11, 0x80,
    0x52, 0x71, 0xa0, 0x46, 0x1c, 0xdb, 0x82, 0x52, 0xd6, 0x1f, 0x1c, 0x45, 0x6f, 0xa3, 0xe5, 0x9a,
    0xb1, 0xf4, 0x5b, 0x33, 0xac, 0xcf, 0x5f, 0x58, 0x38, 0x9e, 0x05, 0x77, 0xb8, 0x99, 0x0b, 0xb3
  };

  uint8_t server_private_key[] = {
    0xc6, 0xef, 0x9c, 0x5d, 0x78, 0xae, 0x01, 0x2a, 0x01, 0x11, 0x64, 0xac, 0xb3, 0x97, 0xce, 0x20,
    0x88, 0x68, 0x5d, 0x8f, 0x06, 0xbf, 0x9b, 0xe0, 0xb2, 0x83, 0xab, 0x46, 0x47, 0x6b, 0xee, 0x53
  };

  uint8_t server_public_key[] = { // Uncompressed point format
    0x04, 0xd1, 0x2d, 0xfb, 0x52, 0x89, 0xc8, 0xd4, 0xf8, 0x12, 0x08, 0xb7, 0x02, 0x70, 0x39, 0x8c, 0x34,
    0x22, 0x96, 0x97, 0x0a, 0x0b, 0xcc, 0xb7, 0x4c, 0x73, 0x6f, 0xc7, 0x55, 0x44, 0x94, 0xbf, 0x63,
    0x56, 0xfb, 0xf3, 0xca, 0x36, 0x6c, 0xc2, 0x3e, 0x81, 0x57, 0x85, 0x4c, 0x13, 0xc5, 0x8d, 0x6a,
    0xac, 0x23, 0xf0, 0x46, 0xad, 0xa3, 0x0f, 0x83, 0x53, 0xe7, 0x4f, 0x33, 0x03, 0x98, 0x72, 0xab
  };

  // Expected shared secret:
  // d6 84 0f 6b 42 f6 ed af d1 31 16 e0 e1 25 65 20 2f ef 8e 9e ce 7d ce 03 81 24 64 d0 4b 94 42 de
  uint8_t shared_secret_buf[32];
  size_t shared_secret_len;
  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile client private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile client private plain key
  ret = psa_import_key(&key_attr, client_private_key, sizeof(client_private_key), &key_id);

  // Perform a key agreement with the server public key and then destroy the client private key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              server_public_key,
                              sizeof(server_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  ret = psa_destroy_key(key_id);

  // Set up attributes for a volatile server private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile server private plain key
  ret = psa_import_key(&key_attr, server_private_key, sizeof(server_private_key), &key_id);

  // Perform a key agreement with the client public key and then destroy the server private key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              client_public_key,
                              sizeof(client_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  ret = psa_destroy_key(key_id);
}
```

**ECDH on Curve25519**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t client_private_key[] = {
    0xB0, 0x76, 0x51, 0xEA, 0x20, 0xF0, 0x28, 0xA8,0x16, 0xEE, 0x01, 0xB0, 0xD1, 0x06, 0x2A, 0x7C,
    0x81, 0x58, 0xE8, 0x84, 0xE9, 0xBC, 0xC6, 0x1C, 0x5D, 0xAB, 0xDB, 0x4E, 0x38, 0x2F, 0x96, 0x69,
  };

  uint8_t client_public_key[] = {
    0x87, 0xD8, 0x6B, 0xDA, 0xAC, 0x38, 0x3C, 0x85, 0xA6, 0xBC, 0xF8, 0xFC, 0xC6, 0x26, 0xD6, 0x14,
    0x36, 0xE4, 0x8F, 0xDB, 0xFA, 0x5A, 0x45, 0xFE, 0x0C, 0x9E, 0xA8, 0x4B, 0x35, 0x3E, 0xF1, 0x37,
  };

  uint8_t server_private_key[] = {
    0x98, 0x2E, 0xB6, 0x7D, 0x0A, 0x01, 0x57, 0x90, 0xE1, 0x45, 0xF3, 0x67, 0xF6, 0xDA, 0xA6, 0x44,
    0x2C, 0x87, 0xC0, 0xED, 0x3C, 0x36, 0x71, 0xA6, 0x89, 0xC7, 0x49, 0xAC, 0x0D, 0xFE, 0x43, 0x6E,
  };

  uint8_t server_public_key[] = {
    0x0C, 0x04, 0x10, 0x5B, 0xE8, 0x7C, 0xAB, 0x37, 0x21, 0x15, 0x7A, 0x8D, 0x49, 0x85, 0x8C, 0x7A,
    0x9F, 0xC1, 0x46, 0xDA, 0xCC, 0x96, 0xEF, 0x6E, 0xD4, 0xDA, 0x71, 0xBF, 0xED, 0x32, 0x0D, 0x76,
  };

  // Expected shared secret:
  // F2 E6 0E 1C B7 64 BC 48 F2 9D BB 12 FB 12 17 31 32 1D 79 AF 0A 9F AB AD 34 05 A2 07 39 9C 5F 15
  uint8_t shared_secret_buf[32];
  size_t shared_secret_len;
  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile client private plain key (Curve25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile client private plain key
  ret = psa_import_key(&key_attr, client_private_key, sizeof(client_private_key), &key_id);

  // Perform a key agreement with server public key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              server_public_key,
                              sizeof(server_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  // Destroy the client private key
  ret = psa_destroy_key(key_id);

  // Set up attributes for a volatile server private plain key (Curve25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile server private plain key
  ret = psa_import_key(&key_attr, server_private_key, sizeof(server_private_key), &key_id);

  // Perform a key agreement with client public key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              client_public_key,
                              sizeof(client_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  // Destroy the server private key
  ret = psa_destroy_key(key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image29](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image29.png)

The following table describes the implementation status of the PSA Crypto ECDH platform example.

|**ECC Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Curve25519|Y|Y|Y|Hardware acceleration only on HSE devices.|
|Curve448|—|—|Y|Only on HSE-SVH devices with hardware acceleration.|

> **Note**:
> 
> - This example does not include secp224r1 and secp256k1. The secp256k1 ECDH on HSE devices is not yet implemented.
> - The PSA Crypto does not yet support software fallback on the Curve448.
> - The HSE-SVM devices require SE firmware v1.2.11 or higher (EFR32xG21) and v2.1.7 or higher (other HSE devices) to support hardware acceleration on Curve25519. This feature also requires GSDK v4.0.1 or higher.

###### X.509 Certificate

An X.509 certificate is a digital certificate that uses the widely accepted international X.509 public key infrastructure (PKI) standard to verify that a public key belongs to the user, computer, or service identity contained within the certificate.

An X.509 certificate contains a public key and an identity (a hostname, an organization, an individual). It is either signed by a certificate authority or self-signed. When a certificate is signed by a trusted certificate authority or validated by other means, someone holding that certificate can rely on the public key it contains to establish secure communications with another party or validate documents digitally signed by the corresponding private key.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>ECDSA (SHA-2)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_224)<br>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_256)<br>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_384)<br>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_512)
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

|**Algorithm**|**Key Type**|**Key Size in Bits**|**Key Usage Flag**|
|---|---|---|---|
|• PSA_ALG_ECDSA(PSA_ALG_SHA_224)|PSA_ECC_FAMILY_SECP_R1|• secp192r1 : 192|• PSA_KEY_USAGE_SIGN_HASH|
|• PSA_ALG_ECDSA(PSA_ALG_SHA_256)| |• secp256r1 : 256|• PSA_KEY_USAGE_VERIFY_HASH|
|• PSA_ALG_ECDSA(PSA_ALG_SHA_384)| |• secp384r1 : 384| |
|• PSA_ALG_ECDSA(PSA_ALG_SHA_512)| |• secp521r1 : 521| |

> **Note**: The key usage flag must use PSA_KEY_USAGE_SIGN_HASH and PSA_KEY_USAGE_VERIFY_HASH.

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_ECDSA(PSA_ALG_SHA_224)|ECDSA and SHA-224|
|PSA_ALG_ECDSA(PSA_ALG_SHA_256)|ECDSA amd SHA-256|
|PSA_ALG_ECDSA(PSA_ALG_SHA_384)|ECDSA and SHA-384|
|PSA_ALG_ECDSA(PSA_ALG_SHA_512)|ECDSA and SHA-512|

|**PSA_ECC_FAMILY_SECP_R1**|**Security Software Components**|
|---|---|
|secp192r1|secp192r1|
|secp256r1|secp256r1|
|secp384r1|secp384r1|
|secp521r1|secp521r1|

|**Built-in Key**|**Security Software Components**|
|---|---|
|secp256r1 keys in SE OTP|Built-In Keys|

|**Item**|**Security Software Components**|
|---|---|
|SHA-1 for X.509 certificate|SHA-1|

|**Item**|**Security Software Components**|
|---|---|
|X.509 certificate support|X.509|

**Using Opaque ECDSA Key to Generate Certificate Signing Request (CSR)**

1. Declare (and allocate) an object of type `mbedtls_pk_context` (PK context) and an object of type `psa_key_id_t` (key identifier).
2. Use the key identifier to generate an ECDSA key or load the built-in ECDSA key. Refer to the [Asymmetric Key](#asymmetric-key) for details.
3. Set up the PK context to wrap that PSA key by calling `mbedtls_pk_setup_opaque(mbedtls_pk_context \*ctx, const psa_key_id_t key)`.
4. Configure the pending CSR object to use that key by calling `mbedtls_x509write_csr_set_key(mbedtls_x509write_csr \*ctx, mbedtls_pk_context \*key)` on that PK context.
5. Call any other function that needs to configure and generate the CSR.
6. After generating the CSR, free the PK context using `mbedtls_pk_free(mbedtls_pk_context \*ctx)`. It only frees the PK context itself and leaves the key identifier untouched.
7. Either keep using the key identifier or call `psa_destroy_key()` on it, depending on the application flow.

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image30](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image30.png)

The following table describes the implementation status of the PSA Crypto X.509 platform example.

|**ECDSA Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Private Device Key|—|—|Y|Only on HSE-SVH devices.|

> **Note**: This example can select the Private Device Key (secp256r1) to generate the root certificate CSR.

#### Series 2 TrustZone

##### Series 2 TrustZone

> **Note: This section replaces _AN1374: TrustZone_. Further updates to this user guide will be provided here**.

ARMv8-M TrustZone is a technology that provides a foundation for improved system security in embedded applications. It allows the ARMv8-M to be aware of the security states of the system. Series 2 devices use the Cortex-M33 core to implement the ARMv8-M TrustZone security extension, which provides the ability to restrict access to peripherals and memory regions based on the processor security attribute. TrustZone works with the MPU, which controls privileged/unprivileged execution of code to provide a complete security solution.

ARMv8-M TrustZone is an extensive topic. The references below are publicly available on the [ARM Developer Documentation](https://developer.arm.com/docs) website.

- [ARMv8-M Architecture Reference Manual](https://developer.arm.com/documentation/ddi0553/latest)
- [ARMv8-M Architecture Technical Overview](https://community.arm.com/cfs-file/__key/telligent-evolution-components-attachments/01-2142-00-00-00-00-66-90/Whitepaper-_2D00_-ARMv8_2D00_M-Architecture-Technical-Overview.pdf)
- [ARM Cortex-M33 Processor Technical Reference Manual](https://developer.arm.com/documentation/100230/latest)
- [System Design with ARMv8-M](https://developer.arm.com/documentation/100767/0100/System-Design-for-ARMv8-M)
- [TrustZone technology for ARMv8-M Architecture](https://developer.arm.com/documentation/100690/latest/)
- [ARM Cortex-M33 Devices Generic User Guide](https://developer.arm.com/documentation/100235/latest)
- [Secure software guidelines for ARMv8-M](https://developer.arm.com/documentation/100720/0300)
- [Software Development in ARMv8-M Architecture](https://community.arm.com/cfs-file/__key/telligent-evolution-components-attachments/01-2142-00-00-00-01-27-19/ARM-Cortex-_2D00_-session-11-_2D00_-Yiu-_2D00_-Software-Development-in-ARMv8_2D00_M-Architecture.pdf)Reading guides:
- Beginner
- Minimal experience with TrustZone, starting with [TrustZone Basics](02-r-basic)
- Intermediate - Have a basic understanding of the TrustZone technology, starting with [Bus Level Security](03-r-bls)
- Advanced - Developed experience on TrustZone, starting with [TrustZone Implementation](05-r-implementation)-Demo - Starting with [TrustZone Platform Examples](05-r-implementation)

###### Key Points

- TrustZone Basics
- Bus Level Security (BLS)
- Secure and Privileged Programming Model
- TrustZone Implementation
- Upgrade Existing Application to TrustZone
- TrustZone Platform Examples

##### Series 2 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure communication paths to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys, and to execute cryptographic functions and secure services.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

<table>
    <thead>
        <tr>
            <th>
                <p>Level (1)</p>
            </th>
            <th>
                <p>SE Support</p>
            </th>
            <th>
                <p>Part</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Secure Vault High (SVH)</p>
            </td>
            <td>
                <p>HSE only (HSE-SVH)</p>
            </td>
            <td>
                <p>Refer to <a href="https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/">IoT Endpoint Security Fundamentals</a> for details on supporting devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Mid (SVM)</p>
            </td>
            <td>
                <p>HSE (HSE-SVM)</p>
            </td>
            <td>
                <p>"</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Mid (SVM)</p>
            </td>
            <td>
                <p>VSE (VSE-SVM)</p>
            </td>
            <td>
                <p>"</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure Vault Base (SVB)</p>
            </td>
            <td>
                <p>N/A</p>
            </td>
            <td>
                <p>"</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: 1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).

Secure Vault Mid consists of two core security functions:

- Secure Boot: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- Secure Debug Access Control: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- Secure Key Storage: Protects cryptographic keys by "wrapping" or encrypting the keys using a root key known only to the HSE-SVH.
- Anti-Tamper protection: A configurable module to protect the device against tamper attacks.
- Device authentication: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

Series 2 devices require a specific [SE firmware version](06-r-migration) to support the TrustZone implementation. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) to learn how to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 devices and modules.

Series 2 devices use Cortex-M33 core to implement the ARMv8-M Mainline TrustZone security extension and refer to TrustZone as [Bus Level Security](03-r-bls). The following table lists the configuration of TrustZone related components in the Series 2 Cortex-M33 core.

<table>
    <thead>
        <tr>
            <th>
                <p>Component</p>
            </th>
            <th>
                <p>Series 2 Configuration</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Security Extension (TrustZone)</p>
            </td>
            <td>
                <p>Enabled</p>
            </td>
            <td>
                <p>The security extension cannot be disabled, and the entire memory after RESET is Secure by default.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Memory Protection Unit (MPU)</p>
            </td>
            <td>
                <p>16 regions (maximum)</p>
            </td>
            <td>
                <p>The MPU regions for both Secure and Non-secure MPUs.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Security Attribution Unit (SAU)</p>
            </td>
            <td>
                <p>8 regions (maximum)</p>
            </td>
            <td>
                <p>The SAU regions for Non-secure and Non-secure Callable.</p>
            </td>
        </tr>
    </tbody>
</table>

##### TrustZone Basics

###### Introduction

TrustZone for ARMv8-M adds extra states to the Cortex-M processor operations to ensure there is  a Secure and Non-secure state. These security states are orthogonal to the existing Thread and Handler modes, thereby having both a Thread and Handler mode in both Secure and Non-secure states. The Thread mode can also be either Privileged or Unprivileged.

![Operation States and Modes of TrustZone Implementation](/series2-trustzone/0.2/images/sld717-operation-states-and-modes-of-trustzone-implementation.png)

_Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

TrustZone for ARMv8-M is an optional architecture extension. By default, the system starts up in a Secure state if the processor implements the TrustZone security extension. The division of Secure and Non-secure worlds is memory-map based (security state depends on the address of the fetched instruction), and the transitions happen automatically. It is also possible to leave the Non-secure state unused and execute the whole application in the Secure state.

###### Memory Security Attributes

TrustZone classifies memory into four security attributes as described in the following table.

<table>
    <thead>
        <tr>
            <th>
                <p>Security Attribute</p>
            </th>
            <th>
                <p>Processor State</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Non-secure (NS)</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
            <td>
                <p>Non-secure and Secure software can access these memory regions.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure (S)</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
            <td>
                <p>Secure software can access these memory regions. Non-secure software cannot gain access to the Secure memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Non-secure Callable (NSC)</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
            <td>
                <p>Secure memory with an NSC attribute provides entry points for Secure APIs that can be called from a Non-secure space. It is a region of memory that contains the Secure Gateway (SG) veneers that allow Non-secure code to call secure functions that exist in Secure code. Non-secure software cannot read/write to an NSC memory but can branch into it if the branch target is an SG instruction.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Exempted</p>
            </td>
            <td>
                <p>Secure/Non-secure</p>
            </td>
            <td>
                <p>Non-secure and Secure software can access these memory regions (exempted from security checking). Exempted regions are typically used by debugging components that do not pose any security risk (e.g., system ROM table) when accessed by the Non-secure software.</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note:** The [Non-secure Callable](#switching-from-non-secure-to-secure-state) is also known as Secure Non-secure Callable (Secure NSC) to declare that this region resides in Secure memory.

###### Banked Register

The concept of a banked register in ARMv8-M between Secure and Non-secure states means that there are two copies of the register, and the core automatically uses the copy that belongs to the current security state. When a register is banked, the `_S` and `_NS` suffixes are used in the ARMv8-M architecture to identify whether the resource is for the Secure state or Non-secure state.

###### General-Purpose Registers (heading level 7)

The Cortex-M processors have 16 general-purpose registers (R0 - R15) for data processing (R0 - R12) and control. The following figure shows the general-purpose register view of the ARMv8-M system with TrustZone. Refer to the [ARM Cortex-M33 Devices Generic User Guide](https://developer.arm.com/documentation/100235/0100/The-Cortex-M33-Processor/Programmer-s-model/Core-registers) for details about these registers.

![General-Purpose Register View with TrustZone](/series2-trustzone/0.2/images/sld717-general-purpose-register-view-with-trustzone.png)

_Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

The Secure or Non-secure state can access the data processing registers R0 - R12 and special usage registers R13 - R15. The register R13 (banked SP) is the stack pointer alias, and the actual stack pointer (`MSP_NS`, `PSP_NS`, `MSP_S`, `PSP_S`) accessed depends on the state (Secure or Non-secure) and mode (Handler or Thread) as described in the following figure.

In addition, stack limit registers ([special registers](#special-purpose-registers)) enable hardware to detect stack overflow conditions. Two pairs of [stack limit registers](#special-purpose-registers) (`MSPLIM_NS` and `PSPLIM_NS`, `MSPLIM_S` and `PSPLIM_S`) are implemented, one per security state, to protect the Main Stack Pointer (MSP) and Process Stack Pointer (PSP).

![Banked Registers in the General-Purpose Registers](/series2-trustzone/0.2/images/sld717-banked-registers-in-the-general-purpose-registers.png)

_Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

In Thread mode, execution can be privileged or unprivileged. The stack pointer used can be the MSP or PSP, depending on the `SPSEL` bit in the [CONTROL](#special-purpose-registers) register. When in Handler mode, the processor is Privileged. The stack pointer is always MSP.

It is possible to directly [access](https://arm-software.github.io/CMSIS_5/Core/html/group__Core__Register__gr.html) the stack pointers (MSP and PSP) and stack limit registers (MSPLIM and PSPLIM), providing that the processor is in a privileged state. If the processor is in a Secure privileged state, the software can also access the Non-secure stack pointers (`MSP_NS` and `PSP_NS`) through [Core Register Access Functions](https://arm-software.github.io/CMSIS_5/Core/html/group__coreregister__trustzone__functions.html) in CMSIS-Core.

###### Special-Purpose Registers (heading level 7)

Except for the general-purpose registers, there are several special-purpose registers for conditional flags, interrupt masking, control, and stack pointer limit. The following figure shows the special-purpose registers view of the ARMv8-M system with TrustZone. Refer to the [ARM Cortex-M33 Devices Generic User Guide](https://developer.arm.com/documentation/100235/0100/The-Cortex-M33-Processor/Programmer-s-model/Core-registers) for details about these registers.

![Special-purpose Registers View with TrustZone](/series2-trustzone/0.2/images/sld717-special-purpose-registers-view-with-trustzone.png)

Image:_[https://documentation-service.arm.com/](https://documentation-service.arm.com/static/5e7cd7b67158f500bd5c4eea?token=).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

The Combined Program Status Register (xPSR) consists of the Application Program Status Register (APSR), Interrupt Program Status Register (IPSR), and Execution Program Status Register (EPSR).

Some of the special-purpose registers are banked between Secure and Non-secure states. Special-purpose registers are not memory-mapped and can be [accessed](https://arm-software.github.io/CMSIS_5/Core/html/group__Core__Register__gr.html) using Core Register Access Functions in CMSIS-Core (except for EPSR in xPSR).

Secure privileged software can also access the Non-secure interrupt masking registers (`PRIMASK_NS`, `FAULTMASK_NS`, and `BASEPRI_NS`), CONTROL register (`CONTROL_NS`), and stack limit registers (`MSPLIM_NS` and `PSPLIM_NS`) through [Core Register Access Functions](https://arm-software.github.io/CMSIS_5/Core/html/group__coreregister__trustzone__functions.html) in CMSIS-Core.

###### System Private Peripheral Bus (PPB) (heading level 7)

The banking of registers is usually used to separate the Secure and Non-secure information of the system components inside the processor. The following figure shows the System Private Peripheral Bus (PPB) registers view of the ARMv8-M system with TrustZone. Refer to the [ARM Cortex-M33 Devices Generic User Guide](https://developer.arm.com/documentation/100235/0100/The-Cortex-M33-Peripherals/About-the-Cortex-M33-peripherals) for details about the System PPB registers.

![System Private Peripheral Bus (PPB) Registers View with TrustZone](/series2-trustzone/0.2/images/sld717-system-private-peripheral-bus-ppb-registers-view-with-trustzone.png)

**System components for debugging and trace operations (`0xE0000000` to `0xE0002FFF`)**:

- Instrumentation Trace Macrocell (ITM)
- Data Watch point and Trace unit (DWT)
- Flash Patch and Breakpoint unit (FPB)

**System Control Space (SCS)**:

- The registers in SCS address spaces are memory-mapped and can be accessed using pointers in software
- Secure SCS (`0xE000E000` to `0xE000EFFF`) - Secure software using this address space to access the banked Secure SCS registers (e.g., `SCB->CPUID`)
- Non-secure SCS (`0xE000E000` to `0xE000EFFF`) - Non-secure software using this address space to access the banked Non-secure SCS registers (e.g., `SCB->CPUID`)
- Non-secure alias SCS (`0xE002E000` to `0xE002EFFF`) - Secure software using this address space to access the Non-secure SCS registers (e.g., `SCB_NS->CPUID`)

The following table describes some core peripherals in the SCS and corresponding [data structures](https://arm-software.github.io/CMSIS_5/Core/html/annotated.html) defined in the CMSIS-Core header file to access the registers of core peripherals in two SCS address spaces.

<table>
    <thead>
        <tr>
            <th>
                <p>Core Peripheral</p>
            </th>
            <th>
                <p>Data Structure for Secure and NS SCS</p>
            </th>
            <th>
                <p>Data Structure for NS Alias SCS</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Implementation Control Block</p>
            </td>
            <td>
                <p>SCnSCB (0xE000E004)</p>
            </td>
            <td>
                <p>SCnSCB_NS (0xE002E004)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SysTick Timer</p>
            </td>
            <td>
                <p>SysTick (0xE000E010)</p>
            </td>
            <td>
                <p>SysTick_NS (0xE002E010)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Nested Vectored Interrupt Controller</p>
            </td>
            <td>
                <p>NVIC (0xE000E100)</p>
            </td>
            <td>
                <p>NVIC_NS (0xE002E100)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>System Control Block</p>
            </td>
            <td>
                <p>SCB (0xE000ECFC)</p>
            </td>
            <td>
                <p>SCB_NS (0xE002ECFC)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Memory Protection Unit</p>
            </td>
            <td>
                <p>MPU (0xE000ED90)</p>
            </td>
            <td>
                <p>MPU_NS (0xE002ED90)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Security Attribution Unit</p>
            </td>
            <td>
                <p>SAU (0xE000EDD0)</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Debug Control Block</p>
            </td>
            <td>
                <p>CoreDebug (0xE000EDF0)</p>
            </td>
            <td>
                <p>CoreDebug_NS (0xE002EDF0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Software Interrupt Generation</p>
            </td>
            <td>
                <p>STIR (0xE000EF00)</p>
            </td>
            <td>
                <p>STIR_NS (0xE002EF00)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Floating-Point Extension</p>
            </td>
            <td>
                <p>FPU (0xE000EF34)</p>
            </td>
            <td>
                <p>FPU_NS (0xE002EF34)</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- The SCB is a group of system control registers for the various usages below.  
  - System Control Register (SCR) to configure processor low power mode  
  - Fault Status Register (xFSR) to provide fault status information  
  - [Vector Table Offset Register (VTOR)](#type-of-exceptions) for vector table relocation
- The [SAU](03-r-bls#security-attribution-unit) register is accessible from the Secure state only.
- The STIR register is not physically banked.
- Core peripherals such as SysTick, SCB, and MPU are duplicated. One instance is Secure and the other one is Non-secure.
- Secure software can use the corresponding functions for ARMv8-M in CMSIS-Core to configure the Non-secure [NVIC](https://arm-software.github.io/CMSIS_5/Core/html/group__nvic__trustzone__functions.html) and [SysTick](https://arm-software.github.io/CMSIS_5/Core/html/group__systick__trustzone__functions.html) through the Non-secure alias SCS.

**Debug or vendor specific components (`0xE0040000` to `0xE00FFFFF`)**:

- Optional debug components (e.g., ETM)
- [External Private Peripheral Bus (EPPB)](03-r-bls#external-secure-attribution-unit-esau) allows designers to add their own debug or vendor-specific components
- [System ROM Table](03-r-bls#external-secure-attribution-unit-esau) is a simple lookup table that enables debug tools to extract the addresses of debug and trace components

###### Secure Attribution Unit (SAU), Implementation Defined Attribution Unit (IDAU), and Memory Protection Unit (MPU)

Two units determine the security attribute of an address:

1. The internal programmable [Secure Attribution Unit (SAU)](https://developer.arm.com/documentation/100690/0201/Attribution-units--SAU-and-IDAU-).
2. The external Implementation Defined Attribution Unit (IDAU), through the IDAU interface, returns the security attribute and region number of an address.

![mpu](/series2-trustzone/0.2/images/sld717-mpu.png)

Three possible configurations to define the security attribute of an address:

1. Internal SAU only
2. External IDAU only
3. A combination of the internal [SAU](03-r-bls#security-attribution-unit) and external IDAU

**Notes**:

- Series 2 devices use configuration 3.
- IDAU in Series 2 devices is the [External Secure Attribution Unit (ESAU)](03-r-bls#external-secure-attribution-unit-esau).

The [Memory Protection Unit (MPU)](https://developer.arm.com/documentation/100699/0100/) is a programmable unit that allows privileged software to define memory access permission. If the TrustZone is enabled, there can be up to two MPUs, one for Secure and one for Non-secure.

- The number of [MPU regions](01-series-2-security-features) for the Secure and the Non-secure MPU can be different.
- The MPU registers are memory-mapped and are placed in the [System Control Space (SCS)](#system-private-peripheral-bus-ppb).
- Secure software can use the [MPU Functions for ARMv8-M](https://arm-software.github.io/CMSIS_5/Core/html/group__mpu8__functions.html) in CMSIS-Core to configure the Non-secure MPU through the [Non-secure alias SCS](#system-private-peripheral-bus-ppb) (`0xE002ED90` - `0xE002EDC4`).

<table>
    <thead>
        <tr>
            <th>Software</th>
            <th>Non-secure MPU Registers</th>
            <th>Secure MPU Registers</th>
            <th>MemManage Fault</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Non-secure privileged</p>
            </td>
            <td>
                <p>0xE000ED90 - 0xE000EDC4</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Non-secure MPU violation</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure privileged</p>
            </td>
            <td>
                <p>0xE002ED90 - 0xE002EDC4</p>
            </td>
            <td>
                <p>0xE000ED90 - 0xE000EDC4</p>
            </td>
            <td>
                <p>Secure MPU violation</p>
            </td>
        </tr>
    </tbody>
</table>

###### Exceptions and Interrupts

###### Type of Exceptions (heading level 7)

The following table describes the types of exceptions in the TrustZone implemented system.

<table>
    <thead>
        <tr>
            <th>Section</th>
            <th>Guidance</th>
            <th>Type</th>
            <th>Default State</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>1 (-)</p>
            </td>
            <td>
                <p>Reset</p>
            </td>
            <td>
                <p>Secure only</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2 (-14)</p>
            </td>
            <td>
                <p>NMI</p>
            </td>
            <td>
                <p>Configurable</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>3 (-13)</p>
            </td>
            <td>
                <p>HardFault</p>
            </td>
            <td>
                <p>Configurable</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>4 (-12)</p>
            </td>
            <td>
                <p>MemManage Fault</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>5 (-11)</p>
            </td>
            <td>
                <p>BusFault</p>
            </td>
            <td>
                <p>Configurable</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>6 (-10)</p>
            </td>
            <td>
                <p>UsageFault</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>7 (-9)</p>
            </td>
            <td>
                <p>SecureFault</p>
            </td>
            <td>Secure only<p></p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>11 (-5)</p>
            </td>
            <td>
                <p>SVCall</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>12 (-4)</p>
            </td>
            <td>
                <p>DebugMonitor</p>
            </td>
            <td>
                <p>Configurable</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>14 (-2)</p>
            </td>
            <td>
                <p>PendSV</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>15 (-1)</p>
            </td>
            <td>
                <p>SysTick</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
            <td>
                <p>Banked</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>16 - 495 (0 - 479)</p>
            </td>
            <td>
                <p>IRQ0 - IRQ479</p>
            </td>
            <td>
                <p>Configurable</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- "Secure only" means the system exceptions can only trigger in the Secure state.
- "Configurable" means the system exceptions and interrupts can be configured to target either the Secure state or the Non-secure state.
- Banked means the system exceptions can have Secure and Non-secure versions. Both can be triggered and executed independently and have different priority level settings.

###### Exception Priorities (heading level 7)

It may cause a security issue if the Non-secure software uses high priority levels to mask the Secure interrupts. To avoid this issue, TrustZone introduces a programmable bit in the `AIRCR` register called `PRIS` (Prioritize Secure exception) for Secure software to prioritize, if needed, Secure exceptions and interrupts.

The `AIRCR.PRIS` is set to 0 out of reset, which means Secure and Non-secure exceptions/interrupts share the same configurable programmable priority level space (columns 2 and 3 in the following table). When the `AIRCR.PRIS` is set to 1, all Non-secure configurable exceptions/interrupts are placed in the lower half of the priority level space so that Secure exceptions/interrupts can potentially have higher priorities (columns 2 and 4 in the following table).

<table>
    <thead>
        <tr>
            <th>Priority Value</th>
            <th>Secure Priority</th>
            <th>Non-secure Priority (PRIS = 0)</th>
            <th>Non-secure Priority (PRIS = 1)</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0</p>
            </td>
            <td>
                <p>0</p>
            </td>
            <td>
                <p>0 (0x00)</p>
            </td>
            <td>
                <p>128 (0x80)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>32</p>
            </td>
            <td>
                <p>32 (0x20)</p>
            </td>
            <td>
                <p>144 (0x90)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>64</p>
            </td>
            <td>
                <p>64 (0x40)</p>
            </td>
            <td>
                <p>160 (0xA0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>3</p>
            </td>
            <td>
                <p>96</p>
            </td>
            <td>
                <p>96 (0x60)</p>
            </td>
            <td>
                <p>176 (0xB0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>128</p>
            </td>
            <td>
                <p>128 (0x80)</p>
            </td>
            <td>
                <p>192 (0xC0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>5</p>
            </td>
            <td>
                <p>160</p>
            </td>
            <td>
                <p>160 (0xA0)</p>
            </td>
            <td>
                <p>208 (0xD0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>6</p>
            </td>
            <td>
                <p>192</p>
            </td>
            <td>
                <p>192 (0xC0)</p>
            </td>
            <td>
                <p>224 (0xE0)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>7</p>
            </td>
            <td>
                <p>224</p>
            </td>
            <td>
                <p>224 (0xE0)</p>
            </td>
            <td>
                <p>240 (0xF0)</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: This table uses three bits (Bit [7:5]) of the group priority level (`AIRCR.PRIGROUP`) to limit the maximum number of preemption levels to 8. A lower priority value indicates a higher priority.

###### Vector Tables (heading level 7)

The following figure shows two vector tables for Secure and Non-secure exceptions and interrupts. The vector table offset is defined by a Vector Table Offset Register (`VTOR` at `0xE000ED08`), which can only be programmed in the privileged state.

![vector-table](/series2-trustzone/0.2/images/sld717-vector-table.png)

Image: _[Vector Table](https://developer.arm.com/documentation/100235/0100/The-Cortex-M33-Processor/Exception-model/Vector-table).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

**Notes**:

- The `VTOR_S` defines the address of the Secure vector table in Secure memory, and the [Secure Main Stack Pointer](#general-purpose-registers) (`MSP_S`) is the default stack for the Secure exception handler.
- The `VTOR_NS` defines the address of the Non-secure vector table in Non-secure memory, and the [Non-secure Main Stack Pointer](#general-purpose-registers) (`MSP_NS`) is the default stack for the Non-secure exception handler.
- Secure privileged software can access the `VTOR_NS` using the [Non-secure SCB alias](#system-private-peripheral-bus-ppb) (`0xE002ED08`).
- The [System Control Space](#system-private-peripheral-bus-ppb) contains registers for the SysTick timer, NVIC, and SCB.
- The interrupt masking registers (PRIMASK, FAULTMASK, and BASEPRI) are [banked](#special-purpose-registers) between security states. The priority level space is shared between the Secure and the Non-secure world, setting an interrupt mask register on one side can block some, or all, of the exceptions on the other side.
- Interrupts (`IRQ0` - `IRQ479`) are defined as Secure by default. Each interrupt can be configured as Secure or Non-secure and is determined by the Interrupt Target Non-secure (`NVIC_ITNS`) register, which is only programmable in the Secure software.

###### State Transitions in Exceptions and Interrupts (heading level 7)

The following figure shows transitions between the [processor states](#introduction) in ARMv8-M TrustZone.![State Transitions](/series2-trustzone/0.2/images/sld717-state-transitions.png)

Image (left): _[Switching-between-Secure-and-Non-secure-states](https://developer.arm.com/documentation/100690/0201/Switching-between-Secure-and-Non-secure-states).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

1. Secure Thread → Secure Handler or Non-secure Thread to Non-secure Handler  
   - No security state transition.  
   - The exception sequence is almost identical to the exception stacking mechanism of current Cortex-M processors.  
   - The Interrupt Service Routine (ISR) is executed in the current security state (either Secure or Non-secure).
2. Non-secure Thread → Secure Handler or Non-secure Handler → Secure Handler  
   - The transition from Non-secure to Secure state.  
   - The exception sequence is almost identical to the exception stacking mechanism of current Cortex-M processors.  
   - The ISR is executed in a Secure state.
3. Secure Thread → Non-secure Handler or Secure Handler → Non-secure Handler  
   - The transition from Secure to Non-secure state.  
   - To avoid an information leak when transitioning from the Secure to Non-secure state. The processor automatically pushes all general-purpose registers into the Secure stack and erases the contents of all general-purpose registers before executing the Non-secure ISR. The processor pops the contents of all general-purpose registers from the Secure stack when returning from the Non-secure ISR (right side in [Figure 2.6 State Transitions on page 12](#state-transitions-in-exceptions-and-interrupts)). It incurs a slightly longer interrupt latency.  
   - The ISR is executed in a Non-secure state.
4. Secure Privileged Thread ↔ Non-secure Privileged Thread or Secure Unprivileged Thread ↔ Non-secure Unprivileged Thread  
   - The transition from Secure to Non-secure state or Non-secure to Secure state.  
   - The [Function calls and returns](#switching-between-secure-and-non-secure-states) can be used when the privileged level remains the same.

> **Note**: Subject to interrupt priority, there are no restrictions regarding whether a Non-secure or Secure interrupt can occur when the processor runs Non-secure or Secure code.

###### Switching Between Secure and Non-secure States

The TrustZone allows direct calling between Secure and Non-secure software. The following figure shows how to use an API function call to trigger security state transitions. The state transitions can also happen because of [exceptions and interrupts](#state-transitions-in-exceptions-and-interrupts).

![swich state](/series2-trustzone/0.2/images/sld717-switch-state.png)

Image: _[Switching-between-Secure-and-Non-secure-states](https://developer.arm.com/documentation/100690/0201/Switching-between-Secure-and-Non-secure-states).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

###### Switching from Non-secure to Secure State (heading level 7)

When the Non-secure program calls a Secure software, the first instruction must be a Secure Gateway (`SG`) instruction residing in Non-secure Callable memory. The Secure Gateway entry points (veneers) decouple the address of the `SG` instructions in the Non-secure Callable memory region from the rest of the Secure code. It can eliminate the risk of having inadvertent entry points when the Secure software contains a pattern that matches the opcode of the `SG` instruction.

![switch-image](/series2-trustzone/0.2/images/sld717-switch-s.png)

Image (right): _Whitepaper - ARMv8-M Architecture Technical Overview. Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

The bit 0 of the [Link Register (LR)](#special-purpose-registers) is cleared to zero by `SG` instruction to indicate that returning from this function transits from Secure to Non-secure. The processor is still in the Non-secure state when the `SG` instruction is executed. The `BXNS LR` instruction is used when returning since a normal `BX LR` instruction interprets it as an unsupported execution mode change. A [SecureFault](#vector-tables) exception is triggered if the processor returns to a Secure address. It prevents a hacker from calling a Secure API with a fake return address pointing to a Secure program location. If bit 0 of LR is 1, the `BXNS LR` instruction behaves like a normal `BX LR`. Therefore, Secure code can call a Secure API in the NSC region even it is not a usual practice.

<table>
    <thead>
        <tr>
            <th>Program</th>
            <th>Call Instruction</th>
            <th>SG Instruction</th>
            <th>Return Instruction</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Non-secure call Non-secure</p>
            </td>
            <td>
                <p>BL or BLX</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>BX LR (Return to Non-secure state)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Non-secure call Secure</p>
            </td>
            <td>
                <p>BL or BLX</p>
            </td>
            <td>
                <p>Clear bit 0 of LR</p>
            </td>
            <td>
                <p>BXNS LR (Return to Non-secure state)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure call Secure</p>
            </td>
            <td>
                <p>BL or BLX</p>
            </td>
            <td>
                <p>Set bit 0 of LR</p>
            </td>
            <td>
                <p>BXNS LR (Return to Secure state)</p>
            </td>
        </tr>
    </tbody>
</table>

To help software developers create Secure APIs in C/C++, the [Cortex-M Security Extension (CMSE)](https://developer.arm.com/documentation/ecm0359818/latest) defines a C function attribute called `cmse_nonsecure_entry`.

- GCC — `__attribute__((cmse_nonsecure_entry))`
- IAR — `__cmse_nonsecure_entry`

###### Test Target (TT) Instruction (heading level 7)

The software can use an ARMv8-M instruction called Test Target (TT) and the region number generated by the SAU or the IDAU to determine if a contiguous range of memory shares common security attributes and privilege levels.

The TT instruction returns the [SAU/IDAU](#secure-attribution-unit-sau-implementation-defined-attribution-unit-idau-and-memory-protection-unit-mpu) region number, security attributes (S/NS), and MPU region number after passing the start and end addresses of the memory range to the TT instruction. The software can determine whether the memory range has required security attributes and resides in the same region number.

![tt-instruction](/series2-trustzone/0.2/images/sld717-tt-instruction.png)

Image: _[Test-target-instruction](https://developer.arm.com/documentation/100690/0201/Test-target-instruction).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

This mechanism allows security checking at the beginning of the API service (instead of during the operation) to determine if the memory referenced by a pointer from Non-secure software points to the Non-secure address. It prevents Non-secure software from using those APIs in Secure software to access or modify Secure data.

To make these operations easier in a C/C++ programming environment, the [Cortex-M Security Extension (CMSE)](https://developer.arm.com/documentation/ecm0359818/latest) has defined a range of [intrinsic functions](https://www.keil.com/support/man/docs/armclang_ref/armclang_ref_pge1446715440722.htm) for dealing with pointer checks with the TT instructions.

###### Switching from Secure to Non-secure State (heading level 7)

When the Secure program calls a Non-secure software, the Secure program must use a `BLXNS <reg>` instruction to invoke the process. If bit 0 of the `<reg>` is 0, the processor must switch to the Non-secure state when branching to the target address. During the state transition, the return address and some processor state information are pushed onto the Secure stack, while the return address on the [Link Register (LR)](#special-purpose-registers) is set to a special value called `FNC_RETURN` (`0xFEFFFFFF`).

The Non-secure function completes by performing a branch (`BX LR`) to the `FNC_RETURN` address (bit 0 is 1 to indicate the function was called from the Secure state). It automatically triggers the unstacking of the actual return address from the Secure stack and returns to the calling function. The `FNC_RETURN` hides the return address of the Secure program from the Non-secure software to avoid the leakage of any secret information. It also prevents Non-secure software from modifying the Secure return address stored in the Secure stack.

![switch_ns](/series2-trustzone/0.2/images/sld717-switch-ns.png)

Image: _[Switching-between-Secure-and-Non-secure-states](https://developer.arm.com/documentation/100690/0201/Switching-between-Secure-and-Non-secure-states).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

To help software developers declare Non-secure function pointers in C/C++, the [Cortex-M Security Extension (CMSE)](https://developer.arm.com/documentation/ecm0359818/latest) defines a C function attribute called `cmse_nonsecure_call`.

- GCC: `__attribute__((cmse_nonsecure_call))`
- IAR: `__cmse_nonsecure_call`

###### Software Flow

The following figure describes a software flow example in a TrustZone implemented system.

![Execution Flow of a TrustZone Implemented System](/series2-trustzone/0.2/images/sld717-execution-flow-of-a-trustzone-implemented-system.png)

Image: _[Software Development in ARMv8-M Architecture](https://community.arm.com/cfs-file/__key/telligent-evolution-components-attachments/01-2142-00-00-00-01-27-19/ARM-Cortex-_2D00_-session-11-_2D00_-Yiu-_2D00_-Software-Development-in-ARMv8_2D00_M-Architecture.pdf).Copyright © 1995-2022 Arm Limited (or its affiliates). All rights reserved._

1. The system starts executing code in the Secure state after a power-on or reset (Secure boot).  
   - The Secure [stack pointer](#general-purpose-registers) (`MSP_S`) is set from the address of the Secure vector table (`VTOR_S`).  
   - The Secure Reset Handler pointed by the `VTOR_S` is called.  
   - Perform various initialization tasks such as C startup code.  
   - Place peripherals and associated interrupts in either Secure or Non-secure applications.  
   - Program [SAU/IDAU](04-r-programming) to partition the entire memory into Secure, Non-secure Callable, and Non-secure regions.  
   - Program the address of the Non-secure vector table (`VTOR_NS`).  
   - Initialize the two first entries of the table for the Non-secure stack pointer (`MSP_NS`) and Reset Handler to emulate a Non-secure reset.
2. The Secure firmware branches to the entry point (Reset Handler pointed by the `VTOR_NS`) of the Non-secure application.  
   - The Non-secure software has its Reset Handler.  
   - Perform various initialization tasks such as C startup code and hardware initialization (e.g., Non-secure peripherals).  
   - It does not conflict with initialization from the Secure code as the stack and heap spaces of Secure and Non-secure code are separated.
3. During the execution of Non-secure applications, the application could call Secure APIs through the [Secure Gateway (SG) veneer](#switching-from-non-secure-to-secure-state) in the Non-secure Callable region.
4. In some cases, Secure APIs might need to call [Non-secure call-back functions](#switching-from-non-secure-to-secure-state) (e.g., a hardware driver).

##### Bus Level Security (BLS)

###### System Design

The following figure shows two system designs:

- The sample system contains an ARMv8-M processor and the required components to support TrustZone.
- Bus Level Security (BLS) on Series 2 devices implements the concepts introduced in the ARM TrustZone sample system. BLS enforces Secure and privileged programming models and uses security components (colored blocks) to configure the security attribute and privileged level of peripherals and Bus Masters.

![ARMv8-M TrustZone Implementation](/series2-trustzone/0.2/images/sld717-armv8-m-trustzone-implementation.png)

###### ARMv8-M Processor (heading level 7)

The ARMv8M processor is TrustZone capable of Secure and Non-secure states. It has a dedicated internal [SAU](#security-attribution-unit) that is fully programmable up to 8 different memory regions. Out of reset, the processor is in a Secure state and every transaction is a Secure transaction.

ARMv8-M Processor in Series 2 devices is the Cortex-M33.

###### System Security Controller (heading level 7)

The system security controller is the central location for all security settings in the system. Each type of controller, IDAU, and wrapper receives its security configuration and bus response configuration from this block.

System Security Controller in Series 2 devices is the [Security Management Unit (SMU)](#security-management-unit-smu).

###### Implementation Defined Attribution Unit (IDAU) (heading level 7)

The [IDAU](02-r-basic) generates the security attribute for a given address. All IDAUs in the system have the same memory partitioning. The IDAU is intended only for ARMv8-M cores and utilizes the entire IDAU interface for the core. The lite IDAU uses only the Secure and Non-secure interface from the IDAU and is intended for Non-ARMv8-M Bus Masters.

IDAU in Series 2 devices is the [External Secure Attribution Unit (ESAU)](#external-secure-attribution-unit-esau).

###### Security Wrapper (heading level 7)

The Security Wrapper gives a legacy Bus Master the ability to drive security attribution. The security wrapper outputs the transaction address to the lite IDAU which returns the security attribute of the address. If the wrapper is configured as Non-secure, any transactions to a Secure address are blocked.

Security Wrapper in Series 2 devices is the [Bus Master Protect Unit (BMPU)](#bus-master-protection-unit-bmpu).

###### Memory Protection Controller (MPC) (heading level 7)

MPC has a security configuration for a per block of memory or memory above and below the watermark. If the security attribute of the block or memory region does not match the security attribute of the address, the transaction is blocked. This controller is used in a system that alias RAM or flash memory locations. This controller is not needed when the memory region size is programmable in an IDAU.

Series 2 devices have a programmable flash and RAM region in the [ESAU](#external-secure-attribution-unit-esau) (equivalent to IDAU) and are not implementing this block.

###### Peripheral Protection Controller (PPC) (heading level 7)

PPC has a security configuration for every peripheral. If the security attribute of the selected peripheral does not match the security attribute of the address, the transaction is blocked. This controller is used in systems that alias the peripheral memory locations.

PPC in Series 2 devices is the [Peripheral Protection Unit (PPU)](#peripheral-protection-unit-ppu).

Hardware security is now extended to the peripheral bus system of the processor. Each component on the bus can verify and propagate the security level for each bus operation.  The following sections describe the individual security component for BLS on Series 2 devices.

###### Security Management Unit (SMU)

The SMU is the only user-facing block in the BLS architecture and houses all the configuration and status for the [ESAUs, BMPUs, and PPUs](#bus-level-security-bls).

- Thirteen memory regions ([ESAU](#external-secure-attribution-unit-esau))
- Per Bus Master privileged and security attribute ([BMPU](#bus-master-protection-unit-bmpu))
- Interrupt flag for Bus Master security fault (fault table in BMPU section)
- Per peripheral privileged and security attribute ([PPU](#peripheral-protection-unit-ppu))
- Interrupt flags for privileged, security, and instruction peripheral access faults (fault tables in PPU section)
- Separate Secure and Privileged IRQ

The SMU configurations can be [locked](04-r-programming) down and protected from runaway code. The `SMU_LOCK` register resets to UNLOCK. Any write other than the unlock code (`0xACCE55`) locks all SMU registers from further updates. The `SMU_STATUS` register contains a `SMULOCK` bitfield with the current lock state of the SMU.

The `SMU_M33CTRL` register can [lock](04-r-programming) down internal security and privileged configurations below.

- Cortex-M33 SAU
- Non-secure MPU
- Secure MPU
- Non-secure Vector Table Offset Register (VTOR)
- Secure AIRCR register

Interrupt flags in the `SMU_IF` register can generate a [Secure or Privileged interrupt](04-r-programming) in the table below when its corresponding interrupt enable bit in the `SMU_IEN` register is set and `IRQn` is enabled.

<table>
    <thead>
        <tr>
            <th>Enable Bit in SMU_IEN Register</th>
            <th>IRQn</th>
            <th>Interrupt Handler</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>BMPUSEC, PPUSEC</p>
            </td>
            <td>
                <p>SMU_SECURE_IRQn</p>
            </td>
            <td>
                <p>SMU_SECURE_IRQHandler()</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PPUPRIV, PPUINST</p>
            </td>
            <td>
                <p>SMU_PRIVILEGED_IRQn</p>
            </td>
            <td>
                <p>SMU_PRIVILEGED_IRQHandler()</p>
            </td>
        </tr>
    </tbody>
</table>

Each interrupt flag in the `SMU_IF` register can be cleared by writing 1 to the corresponding bit of the `SMU_IF_CLR` register.

###### External Secure Attribution Unit (ESAU)

The ESAU is responsible for determining the memory region and [security attribute](02-r-basic) of a given address. Referring to [ARMv8-M TrustZone Implementation on page 16](03-r-bls#system-design), the Cortex-M33 interfaces with an ESAU  and the BMPUs of other Bus Masters interface with lite ESAUs to determine the security attribute of all transactions. The following figure describes the security attributes of different memory regions defined by the ESAU on Series 2 devices.

![System Memory Map of Series 2 Device with TrustZone](/series2-trustzone/0.2/images/sld717-system-memory-map-of-series-2-device-with-trustzone.png)

**Notes**:

- For Series 2 devices with base address `0x08000000` in region 0, the memory address from `0x0` to `0x07FFFFFF` is an invalid region.
- The invalid regions are deemed as Secure.
- The NSC and Exempted attributes are only available to the ESAU, and all lite ESAUs in the system view these attributes as [Secure](05-r-implementation).

The ESAU divides the memory map into 13 memory regions and has a maximum of 6 Non-secure regions.

- Four Movable Region Boundaries (MRBs) determine the size of 6 regions.
- Two regions have configurable security attributes.
- Each memory region consists of a base address that specifies the start of the region and a limit address that specifies the end of the region plus one (**+ 1**).
- The address is valid if it falls between the base (≥ base) and limit (< limit) of a region.
- If the memory region is not defined, it is deemed invalid and Secure.

The MRBs distinguish the Secure, Non-secure Callable, and Non-secure regions in flash and RAM. The two configurable regions determine if the Info flash and Cortex-M33 [EPPB](02-r-basic) regions are Secure or Non-secure. The MRBs have a specific programming sequence. Any [misprogramming](04-r-programming) results in a `SMUPRGERR` in the `SMU_STATUS` register.

###### ARMv8-M CODE Regions (heading level 7)

- [Regions 0, 1, and 2](04-r-programming) are in the Main space of flash. Region 3 is the info space of flash.
- The mrb01 (`ESAUMRB01` in `SMU_ESAURMBR01` register) determines the end of region 0 and the start of region 1.
- The mrb12 (`ESAUMRB12` in `SMU_ESAURMBR12` register) determines the end of region 1 and the start of region 2.
- The size of region 3 is device-dependent.
- Three regions' security attributes are static, and one region is configurable. Region 0 is always Secure, region 1 is always Non-secure Callable, and region 2 is always Non-secure. [Region 3](04-r-programming) is configurable as either Secure or Non-secure (`ESAUR3NS` in `SMU_ESAURTYPES0` register, default is secure after reset).
- Sizes of regions 0, 1, and 2 are adjusted in **4 kB increments** with the lower 12 bits of `ESAUMRB##` in `SMU_ESAURMBR##` ignored.  
  - The Secure region can be set to size 0 when mbr01 = base address of region 0.  
  - The Non-secure Callable regions can be set to size 0 when mbr01 = mbr12.
- The default value of mbr01 is equal to base address + `0x02000000`, so the size of region 0 is 32 MB. Out of reset, all flash is Secure since all Series 2 devices have less than 32 MB of flash.

<table>
    <thead>
        <tr>
            <th>Region</th>
            <th>Memory</th>
            <th>Base Address</th>
            <th>Limit Address</th>
            <th>Security Attribute</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0</p>
            </td>
            <td>
                <p>Main flash</p>
            </td>
            <td>
                <p>0x00000000 or 0x08000000</p>
            </td>
            <td>
                <p>(0x00000000 or 0x08000000) | mbr01</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Main flash</p>
            </td>
            <td>
                <p>(0x00000000 or 0x08000000) | mbr01</p>
            </td>
            <td>
                <p>(0x00000000 or 0x08000000) | mbr12</p>
            </td>
            <td>
                <p>Non-secure Callable</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Main flash</p>
            </td>
            <td>
                <p>(0x00000000 or 0x08000000) | mbr12</p>
            </td>
            <td>
                <p>0x0FE00000</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>3</p>
            </td>
            <td>
                <p>Info flash</p>
            </td>
            <td>
                <p>0x0FE0000</p>
            </td>
            <td>
                <p>0x10000000</p>
            </td>
            <td>
                <p>Secure or Non-secure</p>
            </td>
        </tr>
    </tbody>
</table>

###### ARMv8-M RAM Regions (heading level 7)

- [Regions 4, 5, and 6](04-r-programming) cover the entire available RAM in the device.
- The mrb45 (`ESAUMRB45` in `SMU_ESAURMBR45` register) determines the end of region 4 and the start of region 5.
- The mrb56 (`ESAUMRB56` in `SMU_ESAURMBR56` register) determines the end of region 5 and the start of region 6.
- All three regions' security attributes are static. Region 4 is always Secure, region 5 is always Non-secure Callable, and region 6 is always Non-secure.
- Sizes of all three regions are adjusted in **4 kB increments** with the lower 12 bits of `ESAUMRB##` in `SMU_ESAURMBR##` ignored.  
  - The Secure region can be set to size 0 when mbr45 = base address of region 4.  
  - The Non-secure Callable region can be set to size 0 when mbr45 = mbr56.
- The default value of mbr45 is equal to `0x02000000`, so the size of region 4 is 32 MB. Out of reset, all RAM is Secure since all Series 2 devices have less than 32 MB of RAM.

<table>
    <thead>
        <tr>
            <th>Region</th>
            <th>Memory</th>
            <th>Base Address</th>
            <th>Limit Address</th>
            <th>Security Attribute</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>SRAM</p>
            </td>
            <td>
                <p>0x20000000</p>
            </td>
            <td>
                <p>0x20000000 | mbr45</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>5</p>
            </td>
            <td>
                <p>SRAM</p>
            </td>
            <td>
                <p>0x20000000 | mbr45</p>
            </td>
            <td>
                <p>0x20000000 | mbr56</p>
            </td>
            <td>
                <p>Non-secure Callable</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>6</p>
            </td>
            <td>
                <p>SRAM</p>
            </td>
            <td>
                <p>0x20000000 | mbr56</p>
            </td>
            <td>
                <p>0x30000000</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
        </tr>
    </tbody>
</table>

###### ARMv8-M Peripheral Regions (heading level 7)

- These regions are aliases to the [chip peripherals and SE mailbox](04-r-programming) (a device with HSE).
- Both regions have a fixed size.
- Both regions' security attributes are static. Region 7 is always Secure, and region 8 is always Non-secure.

<table>
    <thead>
        <tr>
            <th>Region</th>
            <th>Memory</th>
            <th>Base Address</th>
            <th>Limit Address</th>
            <th>Security Attribute</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>7</p>
            </td>
            <td>
                <p>Chip Peripherals</p>
            </td>
            <td>
                <p>0x40000000</p>
            </td>
            <td>
                <p>0x50000000</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>8</p>
            </td>
            <td>
                <p>Chip Peripherals</p>
            </td>
            <td>
                <p>0x50000000</p>
            </td>
            <td>
                <p>0x60000000</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
        </tr>
    </tbody>
</table>

###### ARMv8-M Device Regions (heading level 7)

- These regions are aliases to all radio peripherals and radio RAM.
- Both regions have a fixed size.
- Both regions' security attributes are static. Region 9 is always Secure, and region 10 is always Non-secure.
- From the perspective of the device bus system, the [radio is one peripheral that is either Secure or Non-secure](04-r-programming). So any Bus Master accessing the radio needs to know the security attribute of the radio. From the perspective of the radio, all of its radio bus peripherals are accessible regardless of the security attribute. However, the radio needs to know the security attribute of chip bus peripherals to access them through the correct alias.

<table>
    <thead>
        <tr>
            <th>Region</th>
            <th>Memory</th>
            <th>Base Address</th>
            <th>Limit Address</th>
            <th>Security Attribute</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>9</p>
            </td>
            <td>
                <p>Radio Peripherals</p>
            </td>
            <td>
                <p>0xA0000000</p>
            </td>
            <td>
                <p>0xB0000000</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>10</p>
            </td>
            <td>
                <p>Radio Peripherals</p>
            </td>
            <td>
                <p>0xB0000000</p>
            </td>
            <td>
                <p>0xC0000000</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
        </tr>
    </tbody>
</table>

###### ARMv8-M System Private Peripheral Bus (PPB) Regions (heading level 7)

- Both regions have a fixed size.
- [Region 11](04-r-programming) is the Cortex-M33 EPPB memory region and is configurable as either Secure or Non-secure (`ESAUR11NS` in `SMU_ESAURTYPES1` register, default is secure after reset). It is important to note that the Cortex-M33 core is the only Bus Master that sees these memory regions. All other Bus Masters in the system do not have access to the System PPB, and it is an invalid region.
- Region 12 has a static security attribute of Exempted. It means that the Cortex-M33 core allows the transaction in all cases. It permits debuggers to read the system ROM Table regardless of the state of the Cortex-M33 core.

<table>
    <thead>
        <tr>
            <th>Region</th>
            <th>Memory</th>
            <th>Base Address</th>
            <th>Limit Address</th>
            <th>Security Attribute</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>11</p>
            </td>
            <td>
                <p>EPPB</p>
            </td>
            <td>
                <p>0xE0044000</p>
            </td>
            <td>
                <p>0xE00FE000</p>
            </td>
            <td>
                <p>Secure or Non-secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>12</p>
            </td>
            <td>
                <p>System ROM Table</p>
            </td>
            <td>
                <p>0xE00FE000</p>
            </td>
            <td>
                <p>0xE00FF000</p>
            </td>
            <td>
                <p>Exempted</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- The regions in flash (0/1/2) and RAM (4/5/6) can only create in the order of Secure, Non-secure Callable, and Non-secure.
- The [ESAU and lite ESAUs](#bus-level-security-bls) handle the transactions of Bus Masters and must have consistent security attribute mapping. Therefore, configurations in the SMU registers apply to ESAU and lite ESAUs.
- Unlike other Bus Masters using BMPU and lite ESAU, merging the address lookup results from the [internal SAU and ESAU](02-r-basic) determines the [security attribute](#security-attribution-unit) of the Cortex-M33 transaction.

<table>
    <thead>
        <tr>
            <th>Bus Master</th>
            <th>Security Attribution</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Cortex-M33</p>
            </td>
            <td>
                <p>SAU and ESAU</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Other</p>
            </td>
            <td>
                <p>Lite ESAU</p>
            </td>
        </tr>
    </tbody>
</table>

###### Security Attribution Unit

In Series 2 devices, the combination of the integrated SAU in the Cortex-M33 processor and an ESAU determine the security attribute of a Cortex-M33 transaction.

The SAU consists of several [programmable registers](https://developer.arm.com/documentation/100690/0201/SAU-register-summary). These registers are placed in the [System Control Space (SCS)](02-r-basic) and are only accessible from the Secure privileged state.

- SAU Control Register (`SAU_CTRL`) — The SAU is disabled after RESET
- SAU Type Register (`SAU_TYPE`) — Indicates the number of [available regions](01-series-2-security-features) (read-only)
- SAU Region Number Register (`SMU_RNR`) — Assigns a region number
- SAU Region Base Address Register (`SAU->RBAR`) — Configures selected region base address
- SAU Region Limit Address Register (`SAU->RLAR`) — Configures selected region limit address and security attribute (NSC or NS), enable or disable the region

The following figure shows three different SAU configurations for determining the security attribute of a Cortex-M33 transaction.

![Configuration of SAU_CTRL Register](/series2-trustzone/0.2/images/sld717-configuration-of-sau-ctrl-register.png)

**Notes**:

- All address ranges after RESET in SAU are Secure by default.
- The SAU can configure a **32 bytes aligned** region as Non-secure or Non-secure Callable. Any address not defined in the SAU defaults to Secure.
- An [ESAU](#external-secure-attribution-unit-esau) can configure or hard-code a region as Secure, Non-secure Callable, Non-secure, or Exempted. An [Exempted](02-r-basic) region enables Non-secure debuggers to access debugging components and establish a debug connection to the processor before the SAU is configured.
- The processor determines the final attribute of the address based on the higher security attribute (Exempted > S > NSC > NS) from either the SAU or the ESAU.  
  ![state_hierarchy](/series2-trustzone/0.2/images/sld717-state-hierarchy.png)

###### All Secure Configuration (heading level 7)

Highlights:

- SAU is disabled.
- `ALLNS` bit in the SAU Control register is clear.
- The whole memory is in a Secure state (highest security attribute apart from Exempted).
- All Cortex-M33 transactions in this configuration are Secure or Exempted and give the Cortex-M33 access to all memory locations through either the Secure or Non-secure alias after RESET.  
  ![all_s](/series2-trustzone/0.2/images/sld717-all-s.png)
- It is up to the boot procedure in a Secure state to keep the current configuration or use other configurations once the boot process is complete.

###### All Non-secure Configuration (heading level 7)

Highlights:

- SAU is disabled.
- `ALLNS` bit in the SAU Control register is set.
- The whole memory is in a Non-secure state (lowest security attribute).
- Therefore the [ESAU configuration](#external-secure-attribution-unit-esau) determines the security attribute of all Cortex-M33 transactions.  
  ![all_ns](/series2-trustzone/0.2/images/sld717-all-ns.png)
- Except for the `SAU_CTRL` [register](04-r-programming), this configuration does not require programming on other SAU registers.

###### Configurable Configuration (heading level 7)

Highlights:

- SAU is enabled.
- `ALLNS` bit in the SAU Control register can be 0 or 1 (do not care).
- The `NSC` bit on the `SAU_RLAR` register determines the security attribute of an address as Non-secure or Non-secure Callable if an address matches an SAU region.
- The security attribute of an address is Secure by default if the address does not match any SAU region.
- This configuration [programs](04-r-programming)`SAU_RNR`, `SAU_RBAR`, and `SAU_RLAR` registers to correlate the [Non-secure regions](03-r-bls#configurable-configuration) in ESAU.
- The SAU or ESAU [overrides](02-r-basic) the attribute to a [higher security level](#security-attribution-unit) if any security attribute mismatch occurs in a memory region.  
  ![address_lookup](/series2-trustzone/0.2/images/sld717-address-lookup.png)
- The following figure is an example of a configurable configuration with the size of ESAU regions 0 and 5 are set to zero.  
  ![all_config](/series2-trustzone/0.2/images/sld717-all-config.png)

> **Note**: The Cortex-M33 has an internal SAU that defaults all undefined addresses to Secure if enabled. If the Secure regions do not align between the [Cortex-M33 (SAU + ESAU) and other Bus Masters (lite ESAU)](#bus-level-security-bls), the Cortex-M33 treats a memory region as Secure while other Bus Masters treat it as Non-secure. It can lead to the leaking of secure data if the Cortex-M33 stores secure data in what other Bus Masters think is a Non-secure area ([Main Flash Layout on page 34](05-r-implementation)).

###### Bus Master Protection Unit (BMPU)

The BMPU is a security wrapper used for assigning a Bus Master specific security and privileged states. Referring to [Figure 3.1 ARMv8-M TrustZone Implementation on page 16](#system-design), the BMPU generally lies between the Bus Master and the Advanced High-performance Bus (AHB) Matrix. BMPU interfaces with a [lite ESAU](#bus-level-security-bls) to determine the security attribute of all Bus Master transactions.

The registers below in SMU configure the [security](04-r-programming) and [privileged](04-r-programming) state of a Bus Master. The Bus Masters in group 0 are device-dependent. Out of reset, each Bus Master is Secure and privileged.

<table>
    <thead>
        <tr>
            <th>Register</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SMU_BMPUPATD0</p>
            </td>
            <td>
                <p>Bitfields (privileged if set) for privileged attribute configuration on Bus Master group 0</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_BMPUSATD0</p>
            </td>
            <td>
                <p>Bitfields (Secure if set) for security attribute configuration on Bus Master group 0</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The Bus Master privileged attribute only applies to peripheral accesses. Flash and RAM accesses ignore the privileged attribute of the Bus Master.

The BMPU generates a security fault when the security attribute of the bus transaction is Secure, and the security attribute (`SMU_BMPUSATD0`) for the BMPU is configured as Non-secure.

Below is the security fault table that shows how the security attribute on the bus is driven based on the lite ESAU attribute and the BMPU security configuration. The interrupt is triggered if `BMPUSEC` in `SMU_IEN` is set and the `SMU_SECURE_IRQn` is enabled.

<table>
    <thead>
        <tr>
            <th>Lite ESAU Attribute</th>
            <th>Secure Bus Master</th>
            <th>Non-secure Bus Master</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Non-secure</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
            <td>
                <p>Non-secure</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Secure</p>
            </td>
            <td>
                <p>Secure</p>
            </td>
            <td>
                <p>FAULT</p>
            </td>
        </tr>
    </tbody>
</table>

Upon a BMPU fault, the registers in SMU below notify that a BMPU security fault occurred and on which Bus Master. The registers also identify the offending fault address. If a fault is detected, the response is Read As Zero (RAZ) or Write Ignored (WI) and the corresponding interrupt flag is set in the `SMU_IF` register. The values in `SMU_BMPUFS` and `SMU_BMPUFSADDR` do not change until the BMPU fault (`BMPUSEC`) in the `SMU_IF` register is cleared by software.

<table>
    <thead>
        <tr>
            <th>Register</th>
            <th>Bitfield</th>
            <th>Fault</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SMU_IF</p>
            </td>
            <td>
                <p>BMPUSEC</p>
            </td>
            <td>
                <p>Security Fault if set</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_BMPUFS</p>
            </td>
            <td>
                <p>BMPUFSMASTERID</p>
            </td>
            <td>
                <p>ID of the Bus Master that triggered the fault</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_BMPUFSADDR</p>
            </td>
            <td>
                <p>BMPUFSADDR</p>
            </td>
            <td>
                <p>Access address that triggered the fault</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: No privileged fault is generated because all the other Bus Masters in the system do not drive the privileged attribute.

###### Peripheral Protection Unit (PPU)

The PPU is a security wrapper used for assigning a Bus Slave peripheral specific security and privileged states. Referring to [Figure
3.1 ARMv8-M TrustZone Implementation on page 16](#system-design), the PPU comes in the form of a PPU in Advanced High-performance Bus (AHB) and a PPU in Advanced Peripheral Bus (APB).

- The PPU AHB generally lies between the Bus Matrix and an AHB Bus Slave peripheral.
- The PPU APB lies between the output of an AHB to APB bridge and all of the APB Slaves on that APB bus.

The registers below in SMU configure the [security](04-r-programming) and [privileged](04-r-programming) state of a peripheral. The peripherals in groups 0 and 1 are device-dependent. Out of reset, each peripheral is Secure and privileged. While each peripheral in address `0x40000000` (region 7) or `0x50000000` (region 8) can be configured independently, the radio subsystem in `0xA0000000` (region 9) or `0xB0000000` (region 10) is configured as a [unit](04-r-programming).

<table>
    <tbody>
        <tr>
            <th>Register</th>
            <th>Description</th>
        </tr>
        <tr>
            <td>SMU_PPUPATD0</td>
            <td>Bitfields (privileged if set) for privileged access configuration on peripheral group 0</td>
        </tr>
        <tr>
            <td>SMU_PPUPATD1</td>
            <td>Bitfields (privileged if set) for privileged access configuration on peripheral group 0</td>
        </tr>
        <tr>
            <td>SMU_PPUSATD0</td>
            <td>Bitfields (Secure if set) for security access configuration on peripheral group 0</td>
        </tr>
        <tr>
            <td>SMU_PPUSATD1</td>
            <td>Bitfields (Secure if set) for security access configuration on peripheral group 1</td>
        </tr>
    </tbody>
</table>

The PPU can generate three types of faults:

1. Privileged faults occur on unprivileged transactions to privileged peripherals. Below is the privileged fault table that shows when a privileged fault occurs based on the PPU peripheral privileged configuration and the bus transaction privileged attribute. The interrupt is triggered if `PPUPRIV` in `SMU_IEN` is set and the `SMU_PRIVILEGED_IRQn` is enabled.  
   <table>  
       <thead>  
           <tr>  
               <th>Bus Attribute</th>  
               <th>Privileged Peripheral</th>  
               <th>Unprivileged Peripheral</th>  
           </tr>  
       </thead>  
       <tbody>  
           <tr>  
               <td>  
                   <p>Privileged</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
           </tr>  
           <tr>  
               <td>  
                   <p>Unprivileged</p>  
               </td>  
               <td>  
                   <p>FAULT</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
           </tr>  
       </tbody>  
   </table>
2. Security faults occur on Secure transactions to Non-secure peripherals and Non-secure transactions to Secure peripherals. Below is the security fault table that shows when a security fault occurs based on the PPU Peripheral security configuration and the bus transaction security attribute. The interrupt is triggered if `PPUSEC` in `SMU_IEN` is set and the `SMU_SECURE_IRQn` is enabled.  
   <table>  
       <thead>  
           <tr>  
               <th>Bus Attribute</th>  
               <th>Secure Peripheral</th>  
               <th>Non-secure Peripheral</th>  
           </tr>  
       </thead>  
       <tbody>  
           <tr>  
               <td>  
                   <p>Secure</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
               <td>  
                   <p>FAULT</p>  
               </td>  
           </tr>  
           <tr>  
               <td>  
                   <p>Non-secure</p>  
               </td>  
               <td>  
                   <p>FAULT</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
           </tr>  
       </tbody>  
   </table>
3. Instruction faults occur on any transaction marked as an instruction fetch. Below is the instruction fault table that shows when a PPU instruction fault occurs based on the bus transaction instruction attribute. The interrupt is triggered if `PPUINST` in `SMU_IEN` is set and the `SMU_PRIVILEGED_IRQn` is enabled.  
   <table>  
       <thead>  
           <tr>  
               <th>Bus Attribute</th>  
               <th>Secure Peripheral</th>  
               <th>Non-secure Peripheral</th>  
           </tr>  
       </thead>  
       <tbody>  
           <tr>  
               <td>  
                   <p>Secure</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
               <td>  
                   <p>FAULT</p>  
               </td>  
           </tr>  
           <tr>  
               <td>  
                   <p>Non-secure</p>  
               </td>  
               <td>  
                   <p>FAULT</p>  
               </td>  
               <td>  
                   <p>SUCCESS</p>  
               </td>  
           </tr>  
       </tbody>  
   </table>

Upon a [PPU fault](04-r-programming), the registers below in [SMU](#security-management-unit-smu) notifies which PPU fault occurred and on which peripheral. If a fault is detected, the response is Read As Zero (RAZ) or Write Ignored (WI) and set the corresponding interrupt flag in the `SMU_IF` register. The values in `SMU_IF` and `SMU_PPUFS` do not change until all PPU faults in the `SMU_IF` register are cleared by software.

<table>
    <thead>
        <tr>
            <th>Register</th>
            <th>Bitfield</th>
            <th>Fault</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SMU_IF</p>
            </td>
            <td>
                <p>PPUPRIV</p>
            </td>
            <td>
                <p>Privilege Fault if set</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_IF</p>
            </td>
            <td>
                <p>PPUSEC</p>
            </td>
            <td>
                <p>Security Fault if set</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_IF</p>
            </td>
            <td>
                <p>PPUINST</p>
            </td>
            <td>
                <p>Instruction Fault if set</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_PPUFS</p>
            </td>
            <td>
                <p>PPUFSPERIPHID</p>
            </td>
            <td>
                <p>ID of the peripheral that caused the fault</p>
            </td>
        </tr>
    </tbody>
</table>

###### Compatibility

Secure software usually controls the [SYSCFG and SMU](05-r-implementation) peripherals to prevent Non-secure software from changing critical configurations in the Secure domain. It requires switching between Secure and Non-secure states when Non-secure software wants to update the registers in these peripherals. Therefore dedicated registers for Non-secure access are added to SYSCFG and SMU peripherals on newer Series 2 devices.

###### System Configuration (SYSCFG) (heading level 7)

Except for EFR32xG21 devices, the following tables apply to all Series 2 devices.

**Table**: Dedicated Bitfield to Configure Access for Non-secure SYSCFG Registers

<table>
    <thead>
        <tr>
            <th>Bitfield (Register)</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SYSCFGCFGNS (SMU_PPUPATD0)</p>
            </td>
            <td>
                <p>Bitfields (privileged if set) for privileged access configuration on NS SYSCFG registers</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SYSCFGCFGNS (SMU_PPUSATD0)</p>
            </td>
            <td>
                <p>Bitfields (Secure if set) for security access configuration on NS SYSCFG registers</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: Reset `SYSCFGCFGNS` bit in `SMU_PPUSATD0` to allow Non-secure software to access NS SYSCFG registers.

**Table**: Dedicated SYSCFG Registers for Non-secure State

<table>
    <thead>
        <tr>
            <th>SYSCFG Non-secure Registers</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SYSCFG_CFGNS_CFGNSTCALIB</p>
            </td>
            <td>
                <p>NS SysTick calibration value register</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SYSCFG_CFGNS_ROOTNSDATA0</p>
            </td>
            <td>
                <p>NS root data register 0</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SYSCFG_CFGNS_ROOTNSDATA0</p>
            </td>
            <td>
                <p>NS root data register 1</p>
            </td>
        </tr>
    </tbody>
</table>

###### Security Management Unit (SMU) (heading level 7)

Except for EFR32xG21 devices, the following tables apply to all Series 2 devices.

**Table**: Dedicated Bitfield to Configure Access for Non-secure SMU Registers

<table>
    <thead>
        <tr>
            <th>Bitfield (Register)</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SMUCFGNS (SMU_PPUPATD1)</p>
            </td>
            <td>
                <p>Bitfields (privileged if set) for privileged access configuration on NS SMU registers</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMUCFGNS (SMU_PPUSATD1)</p>
            </td>
            <td>
                <p>Bitfields (Secure if set) for security access configuration on NS registers</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: Reset `SMUCFGNS` bit in `SMU_PPUSATD1` to allow Non-secure software to access NS SMU registers.

The SMU_CFGNS register file is for the TrustZone Non-secure state and has its register lock (`NSLOCK`). It allows hardware to maintain the privileged assignments for the NS state. The privileged configuration within the NS state is the same as the Secure state, except it has an "NS" to differentiate the registers.

**Table**: Dedicated SMU Registers for Non-secure State

<table>
    <thead>
        <tr>
            <th>SMU Non-secure Registers</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SMU_CFGNS_NSSTATUS</p>
            </td>
            <td>
                <p>Lock status of SMU_CFGNS registers</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_NSLCOK</p>
            </td>
            <td>
                <p>Lock and unlock the SMU_CFGNS registers</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_NSIF</p>
            </td>
            <td>
                <p>Interrupt flags for NS privilege (PPUNSPRIVIF) and instruction (PPUNSINSTIF) faults</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_NSIEN</p>
            </td>
            <td>
                <p>Interrupt enable flags for NS privilege (PPUNSPRIVIEN) and instruction (PPUNSINSTIEN) faults</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_PPUNSPATD0</p>
            </td>
            <td>
                <p>Bitfields (privileged if set) for NS privileged access configuration on peripheral group 0</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_PPUNSPATD1</p>
            </td>
            <td>
                <p>Bitfields (privileged if set) for NS privileged access configuration on peripheral group 1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_PPUNSFS</p>
            </td>
            <td>
                <p>ID (PPUFSPERIPHID) of the NS peripheral that caused the fault</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SMU_CFGNS_BMPUNSPATD0</p>
            </td>
            <td>
                <p>Bitfields (privileged if set) for privileged attribute configuration on NS Bus Master group 0</p>
            </td>
        </tr>
    </tbody>
</table>

**Table**: Fault Statuses Only for Secure State

<table>
    <thead>
        <tr>
            <th>Bitfield (Register)</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>PPUPRIV (SMU_IF)</p>
            </td>
            <td>
                <p>Fault status now limited only to Secure state</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PPUINST (SMU_IF)</p>
            </td>
            <td>
                <p>Fault status now limited only to Secure state</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PPUPRIV (SMU_IEN)</p>
            </td>
            <td>
                <p>Fault status now limited only to Secure state</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PPUINST (SMU_IEN)</p>
            </td>
            <td>
                <p>Fault status now limited only to Secure state</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PPUFSPERIPHID (SMU_PPUFS)</p>
            </td>
            <td>
                <p>Fault status now limited only to Secure state</p>
            </td>
        </tr>
    </tbody>
</table>

**Table** Dedicated SMU Interrupt for Non-secure State

<table>
    <thead>
        <tr>
            <th>Interrupt</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SMU_NS_PRIVILEGED_IRQHandler()</p>
            </td>
            <td>
                <p>An interrupt flag in the SMU_CFGNS_NSIF register can generate an NS privileged interrupt when its corresponding interrupt enable bit in the SMU_CFGNS_NSIEN register is set and SMU_NS_PRIVILEGED_IRQn is enabled, and in which the peripheral (ID) that triggers the fault is in the SMU_CFGNS_PPUNSFS register.</p>
            </td>
        </tr>
    </tbody>
</table>

##### Secure and Privileged Programming Model

The implementation of BLS on Series 2 devices, both flash and RAM, use a programmable watermark to delineate Secure, Non-secure Callable, and Non-secure regions. On the other hand, peripherals exist in both a Secure and Non-secure alias of memory.

###### BLS SMU Programming

###### Enabling SMU Clock (heading level 7)

Except for the EFR32xG21 devices, all Series 2 devices enable the SMU clock in CMU before programming the SMU registers.

```C

#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
  CMU->CLKEN1_SET = CMU_CLKEN1_SMU;
#endif

```

###### Cortex-M33 Lock Control (heading level 7)

The Cortex-M33 security and privileged configurations can be locked by programming the `SMU_M33CTRL` register.

```C

  // Lock Secure MPU configuration
  SMU->M33CTRL |= SMU_M33CTRL_LOCKSMPU;

```

###### Locking SMU Configuration (heading level 7)

Th entire SMU configuration can be locked down to avoid runaway code. Below is an example of how to lock and unlock the SMU.

```C

  uint32_t lock_status;
  // Lock Down SMU
  SMU->LOCK = ~SMU_LOCK_SMULOCKKEY_UNLOCK;
  // Grab Lock Status
  lock_status = (SMU->STATUS & _SMU_STATUS_SMULOCK_MASK) >> _SMU_STATUS_SMULOCK_SHIFT;
  // Unlock SMU
  SMU->LOCK = SMU_LOCK_SMULOCKKEY_UNLOCK;

```

###### Interrupt Control (heading level 7)

Each interrupt flag in `SMU_IF` can generate an interrupt when its corresponding interrupt enable flag in the `SMU_IEN` register is set. Each interrupt flag can be cleared by writing the clear alias of the `SMU_IF` register.

```C

  // Clear and enable the SMU PPUSEC and BMPUSEC interrupt
  NVIC_ClearPendingIRQ(SMU_SECURE_IRQn);
  SMU->IF_CLR = SMU_IF_PPUSEC | SMU_IF_BMPUSEC;
  NVIC_EnableIRQ(SMU_SECURE_IRQn);
  SMU->IEN = SMU_IEN_PPUSEC | SMU_IEN_BMPUSEC;

```

###### BLS ESAU Programming

###### Region Types (heading level 7)

The `SMU_ESAURTYESn` registers are used to configure memory regions with a specific security attribute. All configurable memory regions reset to Secure. Below is an example of programming regions 3 and 11 to Non-secure.

```C

  // Region 3 (Info flash) is Non-secure
  SMU->ESAURTYPES0 = SMU_ESAURTYPES0_ESAUR3NS;
  // Region 11 (EPPB) is Non-secure
  SMU->ESAURTYPES1 = SMU_ESAURTYPES1_ESAUR11NS;

```

###### Region Sizes (heading level 7)

The code and figure below highlight how to program the Movable Region Boundaries (MRBs) of ESAU.

```C

  // ESAU region 0/1/2 programming
  // Boundary01 at 252kB and  Boundary12 at 256kB
  SMU->ESAUMRB01 = 0x0003F000U & _SMU_ESAUMRB01_MASK;
  SMU->ESAUMRB12 = 0x00040000U & _SMU_ESAUMRB12_MASK;
  // ESAU region 4/5/6 programming
  // Boundary45 at 44kB and Boundary56 at 44kB (region 5 size = 0)
  SMU->ESAUMRB45 = 0x0000B000U & _SMU_ESAUMRB45_MASK;
  SMU->ESAUMRB56 = 0x0000B000U & _SMU_ESAUMRB56_MASK;

```

![esau_prog](/series2-trustzone/0.2/images/sld717-esau-prog.png)

**Notes**:

- The mrb12 (`ESAUMRB12` in `SMU_ESAURMBR12`) has to be greater than or equal to mrb01 (`ESAUMRB12` in `SMU_ESAURMBR12`).
- The mrb56 (`ESAUMRB56` in `SMU_ESAURMBR562`) has to be greater than or equal to mrb45 (`ESAUMRB45` in `SMU_ESAURMBR45`).
- If one of the rules above is violated, the `SMU_STATUS.SMUPRGERR` is asserted.
- When mrb01 and mrb12 are equal, region 1 (NSC) is a size of 0 and is not seen by the system.
- When mrb45 and mrb56 are equal, region 5 (NSC) is a size of 0 and is not seen by the system.

###### BLS SAU Programming

###### All Secure Configuration (heading level 7)

[All secure configuration](03-r-bls) is the default state after reset. It clears the `SAU_CTRL.ENABLE` and the `SAU_CTRL.ALLNS` bits in SAU, and the entire memory is in a Secure attribute.

###### All Non-secure Configuration (heading level 7)

[All Non-secure Configuration](03-r-bls) occurs when the `SAU_CTRL.ENABLE` bit is cleared, and the `SAU_CTRL.ALLNS` bit is set. The ESAU controls the security attribute of a Cortex-M33 transaction.

```C

  // Disable SAU (ALLNS = 1) and clear data and instruction pipe
  SAU->CTRL = SAU_CTRL_ALLNS_Msk;
  __DSB();
  __ISB();

```

###### Configurable Configuration (heading level 7)

[Configurable configuration](03-r-bls) occurs when the `SAU_CTRL.ENABLE` bit is set (`SAU_CTRL.ALLNS` is irrelevant). Both SAU and [ESAU](#region-sizes) determine the security attribute of a Cortex-M33 transaction. The code and figure below highlight how to program the SAU regions.

```C

  // Define all Non-secure (NS) and Non-secure Callable (NSC) Regions
  #define REGION0_BASE 0x0001E000UL
  #define REGION1_BASE 0x00020000UL
  #define REGION2_BASE 0x20004000UL
  #define REGION0_LIMIT 0x0001FFFFUL
  #define REGION1_LIMIT 0x000FFFFFUL
  #define REGION2_LIMIT 0x20017FFFUL
  // CMSIS calls to enable SAU Regions
  // SAU region 0 - Flash NSC at 120 kB to 128 kB (0x0001E000 - 0x0001FFFF)
  SAU->RNR = (0UL & SAU_RNR_REGION_Msk);
  SAU->RBAR = (REGION0_BASE & SAU_RBAR_BADDR_Msk);
  SAU->RLAR = (REGION0_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_NSC_Msk | SAU_RLAR_ENABLE_Msk;
  // SAU region 1 - Flash NS at 128 KB to 1024 kB (0x00020000 - 0x000FFFFF)
  SAU->RNR = (1UL & SAU_RNR_REGION_Msk);
  SAU->RBAR = (REGION1_BASE & SAU_RBAR_BADDR_Msk);
  SAU->RLAR = (REGION1_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
  // SAU region 2 - RAM NS at 16 kB to 96 kB (0x20004000 - 0x20017FFF)
  SAU->RNR = (2UL & SAU_RNR_REGION_Msk);
  SAU->RBAR = (REGION2_BASE & SAU_RBAR_BADDR_Msk);
  SAU->RLAR = (REGION2_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
  // CMSIS functions to enable SAU and clear data and instruction pipe
  TZ_SAU_Enable();
  __DSB();
  __ISB();

```

![sau-frog](/series2-trustzone/0.2/images/sld717-sau-prog.png)

###### BLS BMPU Programming

###### Bus Master Privileged Attribute (heading level 7)

A Bus Master can be configured as either privileged (default) or unprivileged by programming the corresponding index in the `SMU_BMPUPATDn` register.

```C

  // Configure all odd Bus Masters unprivileged
  for (i = 0; i < SMU_NUM_BMPUS; i++) {
    if (i & 0x01) {
      SMU->BMPUPATD0 &= ~(1 << i);
    }
  }

```

###### Bus Master Security Attribute (heading level 7)

A Bus Master can be configured as either Secure (default) or Non-secure by programming the corresponding index in the `SMU_BMPUPATDn` register. Configure a Bus Master as Non-secure results in the Bus Master only being able to access Non-secure addresses.

```C

  // Configure all odd Bus Masters Non-secure
  for (i = 0; i < SMU_NUM_BMPUS; i++) {
    if (i & 0x01) {
      SMU->BMPUSATD0 &= ~(1 << i);
    }
  }

```

###### Bus Master Fault Status (heading level 7)

The Bus Master ID and the address that triggered the fault can be read from the `SMU_BMPUFS` and `SMU_BMPUFSADDR` registers.

```C

  uint32_t fs_bmpu_id;
  uint32_t fs_bmpu_addr;
  uint32_t fs_bmpu_secfault;
  // Read Bus Master fault status
  fs_bmpu_id = SMU->BMPUFS;
  fs_bmpu_addr = SMU->BMPUFSADDR;
  fs_bmpu_secfault = (SMU->IF & _SMU_IF_BMPUSEC_MASK) >> _SMU_IF_BMPUSEC_SHIFT;
  // Clear the IF to capture a new fault
  SMU->IF_CLR = SMU_IF_BMPUSEC;

```

###### BLS PPU Programming

###### Peripheral Privileged Attributes (heading level 7)

A peripheral can be configured as either privileged (default) or unprivileged by programming the corresponding index in the `SMU_PPUPATDn` register.

```C

  // Configure all odd peripherals unprivileged
  for (i = 0; i < SMU_NUM_PPU_PERIPHS; i++) {
    if (i & 0x01) {
      if (i >= 32){
        SMU->PPUPATD1 &= ~(1 << (i-32));
      } else {
        SMU->PPUPATD0 &= ~(1 << i);
      }
    }
  }

```

**Notes**:

- The peripherals in `SMU_PPUPATD0` and `SMU_PPUPATD0` are device-dependent.
- The privileged attribute of the radio subsystem (`AHBRADIO` index) is configured as a unit.

###### Peripheral Security Attributes (heading level 7)

A peripheral can be configured as either Secure (default) or Non-secure by programming the corresponding index in the `SMU_PPUSATDn` register. The figure below shows the memory map when the ADC, I2C0, USART1, and RADIO are configured as Non-secure and other peripherals (e.g., SMU, RTCC, TIMER1, TIMER0, USART0...) as Secure.

```C

  // Configure all the Non-secure peripherals
  SMU->PPUSATD0 &= ~SMU_PPUSATD0_USART1;
  SMU->PPUSATD1 &= ~(SMU_PPUSATD1_I2C0 | SMU_PPUSATD1_IADC0 | SMU_PPUSATD1_AHBRADIO);

```

![ppu_prog](/series2-trustzone/0.2/images/sld717-ppu-prog.png)

**Notes**:

- The peripherals in `SMU_PPUSATD0` and `SMU->PPUSATD1` are device-dependent.
- The security attribute of the radio subsystem (`AHBRADIO` index) is configured as a unit.

###### Peripheral Fault Status (heading level 7)

The peripheral ID that triggered the fault can be read from the `SMU_PPUFS` register.

```C

  uint32_t fs_ppu_periph_id;
  uint32_t fs_sec_fault;
  uint32_t fs_priv_fault;
  uint32_t fs_inst_fault;
  // Read peripheral fault status
  fs_ppu_periph_id = SMU->PPUFS;
  fs_sec_fault = (SMU->IF & _SMU_IF_PPUSEC_MASK) >> _SMU_IF_PPUSEC_SHIFT;
  fs_priv_fault = (SMU->IF & _SMU_IF_PPUPRIV_MASK) >> _SMU_IF_PPUPRIV_SHIFT;
  fs_inst_fault = (SMU->IF & _SMU_IF_PPUINST_MASK) >> _SMU_IF_PPUINST_SHIFT;
  // Clear the IF to capture a new fault
  SMU->IF_CLR = SMU_IF_PPUSEC | SMU_IF_PPUPRIV | SMU_IF_PPUINST;

```

###### Floating Point Unit (FPU) Programming

If the Non-secure application enables the FPU at initialization, the Secure software needs to set up the `NSACR` register in [SCB](02-r-basic) to grant the FPU access for Non-secure software.

```C

  // Enable Non-secure access to the FPU
  SCB->NSACR |= SCB_NSACR_CP10_Msk + SCB_NSACR_CP11_Msk;

```

##### TrustZone Implementation

The goal of TrustZone implementation is to provide Secure Key Storage that can keep access to keys limited to Secure applications while at the same time allowing Non-secure applications to exercise the keys. It is an added feature for the SVM devices that do not have dedicated hardware for [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/) as in SVH devices.

The [PSA Crypto](https://docs.silabs.com/iot-security/latest/mbedtls-psa-crypto-porting-guide/) is placed in a Secure region to keep key material hidden from the Non-secure application. The exposed PSA Crypto APIs stay the same while the backend provides persistent key encryption and decryption similar to the key wrapping and unwrapping functionality of the SVH device.

The following items need to be considered when upgrading the existing system for Secure Key Storage with TrustZone.

- [System Configuration](#system-configuration)
- [Gecko Bootloader](#gecko-bootloader)
- [Secure Library](#secure-library)
- [TrustZone Secure Key Storage](#trustzone-secure-key-storage)
- [PSA Attestation](#psa-attestation)
- [SE Manager](#se-manager)
- [Common Vulnerabilities and Exposures (CVE)](#common-vulnerabilities-and-exposures-cve)

###### System Configuration

The system configuration includes the following items:

- Enable system exceptions in the Secure state.
- Set the security attributes of different regions in the SAU and ESAU.
- Place peripherals and associated interrupts in either Secure or Non-secure applications.
- Assign the Bus Masters' security attributes.
- The system has two Secure/Non-secure pairs for the bootloader and application. The Secure part of each pair is responsible for properly configuring the split in its Secure application before branching to the Non-secure application.

> **Note**: The secure application will issue a software reset at startup (fatal error) if the device's SE firmware version is lower than the [first version](06-r-migration) that supports TrustZone.

###### System Exceptions (heading level 7)

The following [system exceptions](02-r-basic#type-of-exceptions) are enabled in the Secure state for the bootloader and application.

- MemManage Fault
- BusFault
- UsageFault
- SecureFault

###### Main Flash Layout (heading level 7)

The following figure is an overview of the main flash layout that covers the isolation requirements for the Secure Key Storage solution. The SAU and ESAU configurations provide the required security to the Cortex-M33 and other Bus Masters during boot and normal operation.

![Main Flash Layout](/series2-trustzone/0.2/images/sld717-main-flash-layout.png)

1. Settings:  
   - The application is set to non-executable (XN) by [Secure MPU](02-r-basic#secure-attribution-unit-sau-implementation-defined-attribution-unit-idau-and-memory-protection-unit-mpu) to avoid any code execution in this area during boot.  
   - The bootloader is set to non-executable (XN) by Secure MPU to avoid any code execution in this area during normal operation.
2. The ESAU configuration only uses the NSC section by setting mrb01 to the [base address of region 0](04-r-programming). The reason is that lite ESAU in other Bus Masters treats both S and NSC as a Secure attribute. For the Cortex-M33, the SAU upgrades the NSC in the ESAU to Secure. The 32 bytes region alignment of SAU also relaxes the 4 kB alignment restriction on the start address of the NSC in ESAU.
3. The whole application area is set to Secure in SAU for Cortex-M33 during boot to hide details from the bootloader NS part.
4. The ESAU cannot mark any region that comes after a Non-secure section as Secure (must be in the order of S/NSC/NS). Therefore the Secure application area does not align between the Cortex-M33 (SAU + ESAU) and other Bus Masters (lite ESAU) during boot. The secrets stored in that Secure region expose as Non-secure for other Bus Masters during boot (no such issue in normal operations). So the application must not save any plaintext secrets in that Secure region to overcome this limitation during boot.
5. The NVM storage is in the Non-secure region, so the application must [encrypt](05-r-implementation#secure-library) the persistent keys before storing them in this area.

###### RAM Layout (heading level 7)

The following figure is an overview of the RAM layout used for the bootloader and application. The SAU and ESAU are used to split the RAM into a Secure and Non-secure region (Non-secure Callable is not required).

![RAM Layout](/series2-trustzone/0.2/images/sld717-ram-layout.png)

In practice, the Secure part (bootloader or application) takes ownership of the amount of RAM it needs from the beginning of RAM and leaves the rest (up to the ESAU 4 kB alignment requirement) configured as Non-secure.

The bootloader does not know how the application partitions the RAM between Secure and Non-secure. So bootloader removes any secrets from RAM before handing control to the application.

###### Info Flash and EPPB (heading level 7)

The following figure is an overview of the Info flash and EPPB layout for the application. The Cortex-M33 core is the only Bus Master that can access the EPPB region.

![Info Flash and EPPB Layout](/series2-trustzone/0.2/images/sld717-info-flash-and-eppb-layout.png)

###### Peripheral and Device (heading level 7)

The following figure is an overview of the peripheral and device layout for the bootloader and application. The SAU and ESAU are used to split the peripheral and device into a Secure and Non-secure region.

![Peripheral and Device Layout](/series2-trustzone/0.2/images/sld717-peripheral-and-device-layout.png)

The Secure software is responsible for moving all peripherals and associated interrupts to the Non-secure state at startup, except for the peripherals and interrupts that need to be Secure. The Non-secure software must not include code that attempts to directly access any peripheral that is used by the Secure software.

**Peripherals owned by the Secure software (application)**

1. Security Management Unit (SMU)  
   - It prevents Non-secure software from changing the configuration for the ESAUs, BMPUs, and PPUs.  
   - Except for EFR32xG21 devices, some features are also available in the dedicated [Non-secure version of SMU registers](03-r-bls) (`SMU_CFGNS`).
2. CRYPTOACC (VSE devices) or SEMAILBOX (HSE devices)  
   - The crypto engine is placed in the Secure domain for [Secure library](#secure-library).
3. System Configuration (SYSCFG)  
   - It prevents Non-secure software from changing system configurations for Secure software.  
   - Except for EFR32xG21 devices, some features are also available in the dedicated [Non-secure version of SYSCFG registers](03-r-bls) (`SYSCFG_CFGNS`).
4. Memory System Controller (MSC)  
   - It prevents Non-secure software from writing to Secure flash.

**Peripheral interrupts owned by the Secure software**:

**Table**: Secure Peripheral Interrupts (Application)

<table>
    <tbody>
        <tr>
            <td>VSE Device</td>
            <td>HSE Device</td>
        </tr>
        <tr>
            <td>SMU_SECURE_IRQn</td>
            <td>SMU_SECURE_IRQn</td>
        </tr>
        <tr>
            <td>SYSCFG_IRQn</td>
            <td>SYSCFG_IRQn</td>
        </tr>
        <tr>
            <td>MSC_IRQn</td>
            <td>MSC_IRQn</td>
        </tr>
        <tr>
            <td>CRYTOACC_IRQn</td>
            <td>SEMBRX_IRQn</td>
        </tr>
        <tr>
            <td>TRNG_IRQn</td>
            <td>SEMBTX_IRQn</td>
        </tr>
        <tr>
            <td>PKE_IRQn</td>
            <td></td>
        </tr>
    </tbody>
</table>

The `PRIS` bit in the `AIRCR` register is set to 1 to place all Non-secure exceptions/interrupts in [lower priority level space](02-r-basic). Therefore any Secure exceptions/interrupts can be programmed with higher priority than Non-secure ones.

The [`BMPUSEC`](03-r-bls) and [`PPUSEC`](03-r-bls) interrupt enable flags in the `SMU_IEN` register are set to enable the SMU security fault interrupts (`SMU_SECURE_IRQn`) on Bus Masters and peripherals.

**Floating Point Unit (FPU)**:

The Secure application does not use the FPU. But the Secure startup code also enables the [FPU](04-r-programming) for use by the Non-secure application.

###### Bus Masters (heading level 7)

To keep all secrets from the Non-secure world, only the Bus Masters in the table below can access data in the Secure world. For the Bus Masters living in the Secure world, the secure application must configure their corresponding control interfaces in the peripheral space to Secure. The Cortex-M33 core as a Bus Master is split to run in Secure and Non-secure contexts.

**Table**: Secure Bus Masters (Application)

<table>
    <thead>
        <tr>
            <th>Device</th>
            <th>Secure Bus Master</th>
            <th>Control Interface of Bus Master</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>VSE</p>
            </td>
            <td>
                <p>CRYPTOACC</p>
            </td>
            <td>
                <p>CRYTPOACC</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>HSE</p>
            </td>
            <td>
                <p>SEDMA or SEEXTDMA</p>
            </td>
            <td>
                <p>SEMAILBOX</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- Use `SMU_BMPUSATD0` register to [configure](04-r-programming) the security attribute of a Bus Master.
- Use `SMU_PPUSATDn` register to [configure](04-r-programming) the control interface of Bus Master as a Secure peripheral.
- LDMA is set as a Non-secure Bus Master to make sure it cannot be used to copy out data from the Secure memory.

###### Application Transitions (heading level 7)

The system contains two Secure/Non-secure pairs.

1. The [bootloader pair](#bootloader pair) has a Secure bootloader and a Non-secure bootloader containing the communication interfaces.
2. The [application pair](#application pair) has a Secure application and a Non-secure application consisting of the wireless stacks (if applicable) and application layers.

As described in the preceding sections, the Secure part of these pairs is responsible for setting the security configurations of the system during startup. For the handover between Secure/Non-secure pairs, the software must restore the system so the Secure part of the other pair can execute and reconfigure the system.

The software must reconfigure the following items before transitioning to the next Secure/Non-secure pair:

- Restored all peripherals and interrupts to Secure
- Reset ESAU to default configuration (all configurable regions to Secure)
- Reset SAU to default configuration (Secure for everything)
- Reset MPU to default configuration (removes any XN)

###### Gecko Bootloader

The [Gecko bootloader](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) ensures the Secure assets are protected during the boot flow and normal operation.

![Gecko Bootloader Flow](/series2-trustzone/0.2/images/sld717-gecko-bootloader-flow.png)

1. The SAU and [Secure MPU](02-r-basic) mark all the flash for application and NVM as Secure and non-executable (XN) during boot. It guards against bootloader NS code execution branching into the application code.
2. The bootloader needs to split into Secure and Non-secure software to protect secrets in the system. Secure code can access the entire flash to validate or upgrade the system.
3. For VSE devices, the [GBL Decryption Key (AES-128 key)](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) is moved from the NS memory (last page of the main flash) to the Secure part of the bootloader. The Simplicity Commander v1.13 or higher provides a feature to inject the AES-128 key to the bootloader binary file.  
   ```C  
   commander convert <BL image file> --aeskey <decryption key file> --outfile <BL image with decryption key>  
   ```
4. The bootloader communication interfaces are placed in the NS area to support various [communication components](https://docs.silabs.com/mcu-bootloader/latest/group-Communication) below for firmware upgrades.  
   - BGAPI UART  
   - EZSP-SPI  
   - UART XMODEM
5. The NS communication functions call into the [bootloader APIs](https://docs.silabs.com/mcu-bootloader/latest/group-Interface) placed in the bootloader NSC region. The Secure application [validates](02-r-basic) all input arguments before processing the request.
6. Before transiting from bootloader to normal operation, it resets the SAU to default configuration to make all the flash for bootloader as Secure.
7. The Non-secure application software can call [bootloader APIs](https://docs.silabs.com/mcu-bootloader/latest/group-Interface) through application NSC, and the corresponding Secure function releases the non-executable (XN) restriction on the bootloader during normal operation.

###### Secure Library

The goal of the Secure library is to keep the [PSA Crypto key](#trustzone-secure-key-storage) and [attestation token](#psa-attestation) protected from malicious code on the NSPE. The following figure overviews multiple components to support the Secure library.

![Secure Library Components](/series2-trustzone/0.2/images/sld717-secure-library-components.png)

1. The NS interfaces in NSPE are responsible for packing and passing all input arguments over the [NSC](02-r-basic) functions on wrappers in SPE.
2. The wrappers in SPE validate all input arguments before calling into the corresponding APIs in different drivers.
3. Because of the system memory layout limitation, the [flash](#main-flash-layout) for NVM3 storage is located in the NSPE. Therefore the updated PSA Internal Trusted Storage (ITS) driver needs to encrypt all crypto keys before storing them in Non-secure NVM.
4. Data stored directly using the NVM3 APIs are not encrypted.

The following table describes the new and updated components of the Secure library.

<table>
    <thead>
        <tr>
            <th>Component</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SE Manager NS interface</p>
            </td>
            <td>
                <p>This component contains SE Manager API callable from the NSPE. It packages the list of input arguments in the appropriate format before calling into the SE Manager wrapper's NSC functions.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SE manager wrapper</p>
            </td>
            <td>
                <p>This component contains the interface into SE Manager exposed to the NSPE. These NSC functions grant access to the SE Manager utility API and validate all input arguments before calling into SE Manager.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Crypto &amp; Attestation NS interface</p>
            </td>
            <td>
                <p>This component contains PSA Crypto and attestation API callable from the NSPE. It packages the list of input arguments in the appropriate format before calling into the PSA Crypto and attestation wrapper's NSC functions.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA Crypto &amp; Attestation wrapper</p>
            </td>
            <td>
                <p>This component contains the interface into PSA Crypto and attestation exposed to the NSPE. These NSC functions grant access to the entire PSA Crypto and attestation API and validate all input arguments before calling into PSA Crypto and attestation.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PSA attestation</p>
            </td>
            <td>
                <p>This component in SPE provides the functionality required by the PSA attestation specification.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Encrypted PSA ITS</p>
            </td>
            <td>
                <p>The PSA ITS layer builds on top of NVM3. This component is updated to support encrypted storage to secure stored keys. The encryption is based on the device's TrustZone Root Key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>NVM3 NS interface</p>
            </td>
            <td>
                <p>This component contains NVM3 API callable from the NSPE. It packages the list of input arguments in the appropriate format before calling into the NVM3 wrapper's NSC functions.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>NVM3 wrapper</p>
            </td>
            <td>
                <p>This component contains the interface into NVM3 exposed to the NSPE. These NSC functions grant access to the NVM3 API and validate all input arguments before calling into NVM3.</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- The SE Manager NS interface, PSA Crypto NS interface, and NVM3 NS interface in the NSPE provide drop-in replacement on [SE Manager utility](#se-manager), [PSA Crypto](https://armmbed.github.io/mbed-crypto/html/about.html), and [NVM3](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3) APIs for existing wireless stacks and user applications.
- The NSC calls can only take a limited number of arguments, so all NSC functions take a pointer to a list of parameters to support a long list of arguments. All arguments must be validated using the [intrinsic functions](02-r-basic) from CMSIS.

###### TrustZone Secure Key Storage

The TrustZone Secure Key Storage provides a solution to store a user key in Secure RAM or an encrypted form in Non-secure flash.

The TrustZone Root Key stored in the SE NVM for Secure Key Storage encryption is generated or renewed by following operations.

- The TrustZone Root Key had already existed if the shipped Series 2 device with [SE firmware version](06-r-migration) supports this key.
- Generate a TrustZone Root Key when upgrading from a SE firmware version that did not support this key to the one that does.
- Renew a TrustZone Root Key after performing a [Device Erase](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

> **Note**: The TrustZone Root Key cannot be renewed if Device Erase is disabled.

The TrustZone Root Key is not exposable to the NSPE, and access to this key in SPE is different in HSE and VSE devices.

- HSE - The SPE can access the TrustZone Root Key as a built-in non-exportable key in HSE NVM.
- VSE - The SPE can access the TrustZone Root Key in Secure RAM, which is copied from VSE NVM during boot.

The TrustZone Root Key value after reset is identical to the value before reset. TrustZone Root Keys are unique on each device. The key allows a user to securely store a key in the Non-secure flash, limiting the number of keys that can be saved only by the amount of Non-secure storage. The following figure describes using the TrustZone Root Key to encrypt a plaintext key and store it in Non-secure NVM.

![root_encrypt](/series2-trustzone/0.2/images/sld717-root-encrypt.png)

1. After power-on, the device's TrustZone Root Key is available for the SPE.
2. A user key is generated and imported into the device's Non-secure memory. In this example, the key is imported into Non-secure RAM for easy deletion, and the key is lost if device power is removed.
3. Call PSA Crypto API (`psa_import_key()` or `psa_generate_key()`) through SG in NSC to generate a key for crypto operations.
4. The plaintext key is passed to the PSA Crypto in SPE, where it is encrypted (AES-GCM) with the TrustZone Root Key.
5. The encrypted key is stored to the NVM in NSPE through the PSA ITS and NVM3 drivers.
6. The plaintext key can now be deleted from the Non-secure RAM.
7. Only the PSA Crypto in SPE can retrieve the encrypted key from NVM in NSPE and decrypt it for crypto operations in SPE.

> **Note**: Ignore steps 2 and 6 if the plaintext key is randomly generated by the PSA Crypto.

The following tables describe the storage differences between SVM and SVH devices with and without TrustZone Secure Key Storage (SKS).

<table>
    <thead>
        <tr>
            <th>Key Type</th>
            <th>Storage on SVM Device</th>
            <th>Storage on SVH Device</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Volatile Plaintext (without TrustZone SKS)</p>
            </td>
            <td>
                <p>RAM</p>
            </td>
            <td>
                <p>RAM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Plaintext (without TrustZone SKS)</p>
            </td>
            <td>
                <p>NVM</p>
            </td>
            <td>
                <p>NVM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Volatile Wrapped (without TrustZone SKS)</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
            <td>
                <p>RAM (1)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Wrapped (without TrustZone SKS)</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
            <td>
                <p>NVM (1)</p>
            </td>
        </tr>
    </tbody>
</table>

<table>
    <thead>
        <tr>
            <th>Key Type</th>
            <th>Storage on SVM Device</th>
            <th>Storage on SVH Device</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Volatile Plaintext (with TrustZone SKS)</p>
            </td>
            <td>
                <p>Secure RAM (2)</p>
            </td>
            <td>
                <p>Secure RAM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Plaintext (with TrustZone SKS)</p>
            </td>
            <td>
                <p>Encrypted plaintext key in NS NVM (2)</p>
            </td>
            <td>
                <p>Encrypted plaintext key in NS NVM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Volatile Wrapped (with TrustZone SKS)</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
            <td>
                <p>Secure RAM</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Persistent Wrapped (with TrustZone SKS)</p>
            </td>
            <td>
                <p>Not supported</p>
            </td>
            <td>
                <p>Encrypted wrapped key in NS NVM</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- The NVM or [NS NVM](#main-flash-layout) is at the last part of the main flash.
- It is possible to replace the [wrapped key](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/) solution on the SVH device (1) with TrustZone Secure Key Storage on the SVM device (2), but this is a less secure approach.

###### PSA Attestation

The device attestation service creates a token that contains a fixed set of device-specific data when requested by the caller. Each device must have a unique Initial Attestation Key (IAK) pair. The device uses the private IAK to sign the token, and the caller uses the public IAK to verify the token's authenticity.

The generation of the private IAK is different in SVM and SVH devices.

- SVM - If the private IAK does not exist in NVM3, it is randomly generated when requested from the [PSA Attestation](#secure-library) driver and saved to NVM3 through the [TrustZone Secure Key Storage](#trustzone-secure-key-storage).
- SVH - The private IAK is generated and securely stored in the HSE during chip production.

An Entity Attestation Token (EAT) is a mini-report that is cryptographically signed. An EAT is encoded in either one of two standardized data formats: a Concise Binary Object Representation ([CBOR](https://www.rfc-editor.org/info/rfc7049)) or in the text-based format JSON. A digital signature is then used to protect its content. The technical specification defining the content of the EAT, which are claims about the hardware and the software running on a device, is specified by the Internet Engineering Task Force ([IETF](https://datatracker.ietf.org/doc/html/draft-ietf-rats-eat-11)).

The EAT is a crypto-signed report card with claims. A claim is a data item that is represented as a Key-Value pair. Claims can relate to the device's pedigree or anything one wants the device to attest. Collected data can originate from the Root of Trust (RoT), any protected area, or non-protected areas.

The EAT must be signed following the structure of the CBOR Object Signing and Encryption ([COSE](https://www.rfc-editor.org/info/rfc8152)) specification. For asymmetric key algorithms, the signature structure must be COSE-Sign1. A COSE-Sign1 is a CBOR encoded, self-secured data blob that contains headers, a payload, and a signature.

The primary need for EAT verification is to check correct formation and signing as for any token. In addition, though, the verifier can operate a policy where values of some of the claims in this profile can be compared to reference values that are registered with the verifier for a given deployment, to confirm that the device is endorsed by the manufacturer supply chain.

The [PSA attestation token](https://www.ietf.org/archive/id/draft-tschofenig-rats-psa-token-21.html) (aka Initial Attestation Token - IAT) is a profiled EAT. The Series 2 device will generate this token by (Nonce claim below) unless the SE OTP is uninitialized or the [`SECURE_BOOT_ENABLE`](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) option in SE OTP is disabled.

The following tables describe claims used in the PSA attestation token of the Series 2 device.

**Table**: Claims of PSA Attestation Token

<table>
    <thead>
        <tr>
            <th>Key</th>
            <th>Claim Name (Present)</th>
            <th>Claim Description</th>
            <th>Claim Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>265 (-75000)</p>
            </td>
            <td>
                <p>Profile Definition (Must)</p>
            </td>
            <td>
                <p>The Profile Definition claim encodes the unique identifier corresponds to the EAT profile.</p>
            </td>
            <td>
                <p>http://arm.com/psa/2.0.0</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2394 (-75001)</p>
            </td>
            <td>
                <p>Client ID (Must)</p>
            </td>
            <td>
                <p>The Client ID claim represents the security domain of the caller.</p>
            </td>
            <td>
                <p>See note below (2 byes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2395 (-75002)</p>
            </td>
            <td>
                <p>Security Lifecycle (Must)</p>
            </td>
            <td>
                <p>The Security Lifecycle claim represents the current lifecycle state of the PSA RoT.</p>
            </td>
            <td>
                <p>Device dependent (2 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2396 (-75003)</p>
            </td>
            <td>
                <p>Implementation ID (Must)</p>
            </td>
            <td>
                <p>The Implementation ID claim uniquely identifies the implementation of the immutable PSA RoT.</p>
            </td>
            <td>
                <p>Device dependent (32 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2397 (-75004)</p>
            </td>
            <td>
                <p>Boot Seed (Optional)</p>
            </td>
            <td>
                <p>The Boot Seed claim represents a value created at system boot time that will allow differentiation of reports from different boot sessions.</p>
            </td>
            <td>
                <p>Device dependent (32 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2399 (-75006)</p>
            </td>
            <td>
                <p>Software Components (Must)</p>
            </td>
            <td>
                <p>The Software Components claim is a list of software components that includes all the software loaded by the PSA RoT.</p>
            </td>
            <td>
                <p>See note below</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>10 (-75008)</p>
            </td>
            <td>
                <p>Nonce (Must)</p>
            </td>
            <td>
                <p>The Nonce claim is used to carry the challenge provided by the caller to demonstrate freshness of the generated token. The length must be either 32, 48, or 64 bytes.</p>
            </td>
            <td>
                <p>Random nonce (32/48/64 bytes)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>256 (-75009)</p>
            </td>
            <td>
                <p>Instance ID (Must)</p>
            </td>
            <td>
                <p>The Instance ID claim represents the unique identifier of the IAK. The length must be 33 bytes.</p>
            </td>
            <td>
                <p>SHA-256 hash of public IAK (32 bytes) with header 0x01</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- Some claims MUST be present in a PSA attestation token.
- The keys `-7500x` were defined in a previous version of the PSA attestation token specification (`PSA_IOT_PROFILE_1` profile) that is still used in the HSE-SVH firmware.
- The actual claims returned from the tokens on the SVH device are HSE firmware version-dependent.
- Key 2394: In PSA, a security domain is represented by a signed integer where negative values represent callers from the NSPE and positive IDs represent callers from the SPE. The value 0 is not permitted.
- Key 2395 (For the definitions of these lifecycle states, refer to the ARM [PSA Security Model](https://developer.arm.com/-/media/Files/pdf/PlatformSecurityArchitecture/Architect/DEN0079_PSA_SM_ALPHA-03_RC01.pdf)):  
  - UNKNOWN (`0x0000 - 0x00ff`)  
  - ASSEMBLY_AND_TEST (`0x1000 - 0x10ff`)  
  - PSA_ROT_PROVISIONING (`0x2000 - 0x20ff`)  
  - SECURED (`0x3000 - 0x30ff`)  
  - NON_PSA_ROT_DEBUG (`0x4000 - 0x40ff`)  
  - RECOVERABLE_PSA_ROT_DEBUG (`0x5000 - 0x50ff`)  
  - DECOMMISSIONED (`0x6000 - 0x60ff`)
- Key 2396:  
  - Word[0]: Die revision  
  - Word[1]: SE OTP version (return 0 for VSE SE firmware < [v1.2.14](06-r-migration))  
  - Word[2]: Security capability (not applicable to HSE-SVH device, always returns 1 in this word)    
    - 0: Unknown security capability    
    - 1: Security capability not applicable    
    - 2: Basic security capability    
    - 3: Root of Trust security capability    
    - 4: HSE-SVM security capability    
    - 5: HSE-SVH security capability (run HSE-SVM binary on HSE-SVH device)  
  - Word[3]: Production version  
  - Word[4:7]: Reserved (zeros)
- Key 2399: Each software component uses the attributes described in the following table, and some MUST be present in a software component claim.

<table>
    <thead>
        <tr>
            <th>Key</th>
            <th>Attribute (Present)</th>
            <th>Description</th>
            <th>Value</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>1</p>
            </td>
            <td>
                <p>Measurement Type (Optional)</p>
            </td>
            <td>
                <p>The Measurement Type attribute is a short string representing the role of this software component.</p>
            </td>
            <td>
                <p>See note below</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>2</p>
            </td>
            <td>
                <p>Measurement Value (Must)</p>
            </td>
            <td>
                <p>The Measurement Value attribute represents a hash of the invariant software component in memory at startup time.</p>
            </td>
            <td>
                <p>SHA-256 hash (32 bytes) of the firmware</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>4</p>
            </td>
            <td>
                <p>Version (Optional)</p>
            </td>
            <td>
                <p>The Version attribute is the issued software version in the form of a text string.</p>
            </td>
            <td>
                <p>A string of 8 bytes</p>
            </td>
        </tr>
    </tbody>
</table>

The following measurement types may be used for Key 1:

- "BL": a Bootloader
- "PRoT": a component of the PSA Root of Trust
- "ARoT": a component of the Application Root of Trust
- "App": a component of the NSPE application
- "TS": a component of a Trusted Subsystem

The PSA Attestation API allows access to the PSA attestation token, so an external entity can cryptographically verify the identity and trust status of the device.

**Table**: PSA Attestation API

<table>
    <thead>
        <tr>
            <th>PSA Attestation API</th>
            <th>Usage</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>psa_initial_attest_get_token</p>
            </td>
            <td>
                <p>Retrieve the PSA attestation Token.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>psa_initial_attest_get_token_size</p>
            </td>
            <td>
                <p>Calculate the size of a PSA attestation Token.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_tz_attestation_get_public_key</p>
            </td>
            <td>
                <p>Get the public IAK key for PSA attestation token signature verification.</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The `sl_tz_attestation_get_public_key` is a Silicon Labs custom API.

###### SE Manager

SE Manager is the foundation for the [Secure library](#secure-library) cryptographic operations on HSE devices. It means that SE Manager has to move into the SPE.

The following SE Manager [core](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager-core) APIs are always available in the NSPE.

<table>
    <thead>
        <tr>
            <th>SE Manager Core API</th>
            <th>VSE-SVM</th>
            <th>HSE-SVM</th>
            <th>HSE-SVH</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sl_se_init</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_deinit</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_init_command_context</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_deinit_command_context</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_set_yield</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
    </tbody>
</table>

The following SE Manager [core](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager-core) APIs expose to the NSPE through the NSC interface for the VSE devices.

<table>
    <thead>
        <tr>
            <th>SE Manager Core API</th>
            <th>VSE-SVM</th>
            <th>HSE-SVM</th>
            <th>HSE-SVH</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sl_se_read_executed_command</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_ack_command</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
        </tr>
    </tbody>
</table>

The following SE Manager [utility](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager-util) APIs expose to the NSPE through the NSC interface for configuring the security features of HSE or VSE devices.

<table>
    <thead>
        <tr>
            <th>SE Manager Utility API</th>
            <th>VSE-SVM</th>
            <th>HSE-SVM</th>
            <th>HSE-SVH</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sl_se_check_se_image</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_apply_se_image</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_upgrade_status_se_image</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_check_host_image</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_apply_host_image</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_upgrade_status_host_image</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_init_otp_key</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_read_pubkey</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_init_otp</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_read_otp</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_se_version</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_debug_lock_status</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_apply_debug_lock</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_otp_version</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_write_user_data</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y (EFR32xG21 only)</p>
            </td>
            <td>
                <p>Y (EFR32xG21 only)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_erase_user_data</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y (EFR32xG21 only)</p>
            </td>
            <td>
                <p>Y (EFR32xG21 only)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_reset_cause</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y (EFR32xG21 only)</p>
            </td>
            <td>
                <p>Y (EFR32xG21 only)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_status</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_serialnumber</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_enable_secure_debug</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_disable_secure_debug</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
    </tbody>
</table>

<table>
    <thead>
        <tr>
            <th>SE Manager Utility API</th>
            <th>VSE-SVM</th>
            <th>HSE-SVM</th>
            <th>HSE-SVH</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>sl_se_set_debug_options</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_erase_device</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_disable_device_erase</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_get_challenge</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_roll_challenge</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_open_debug</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_disable_tamper</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_read_cert_size</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>sl_se_read_cert</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>Y</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The NSPE cannot access the other [SE Manager APIs](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager) for cryptographic and attestation operations.

###### Common Vulnerabilities and Exposures (CVE)

At this writing, the following known TrustZone CVE had been fixed in the current implementation.

- [CVE-2020-16273](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-16273): Stack sealing
- [CVE-2021-36465](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-35465): VLLDM instruction/floating-point vulnerability

##### Upgrade Existing Application to TrustZone

The main concerns when upgrading existing deployment to the TrustZone solution are:

- The [Secure/Non-secure pair for the bootloader](05-r-implementation) (24 kB) does not fit inside the current allotted bootloader space (16 kB).
- The [Secure/Non-secure pair for the application](07-r-ex) does not fit inside the current allotted application space.
- The [PSA ITS](05-r-implementation) moves from a non-encrypted to an encrypted format, so the existing stored cryptographic keys in NVM3 cannot be reused after upgrading the current application to TrustZone.

The [Secure Library](05-r-implementation) is based on PSA Crypto, so the existing application cannot integrate with the TrustZone if one of the following conditions is valid.

- Use [SE Manager APIs](https://docs.silabs.com/gecko-platform/latest/service/api/group-sl-se-manager) for cryptographic and attestation operations.
- Use classic Mbed TLS APIs for cryptographic operations (except for X.509 certificate) and Transport Layer Security (TLS) protocol.

###### System Requirements

The following table lists the tools and software required for TrustZone development on Series 2 devices.

<table>
    <thead>
        <tr>
            <th>Tool/Software</th>
            <th>Required Version</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>GCC</p>
            </td>
            <td>
                <p>v10.3.1</p>
            </td>
            <td>
                <p>Fix a bug (ID 99271) on cmse_nonsecure_call attribute.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>IAR EWARM</p>
            </td>
            <td>
                <p>v9.20.4</p>
            </td>
            <td>
                <p>Fix a bug (EWARM-9484) on __cmse_nonsecure_call attribute.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Segger J-Link</p>
            </td>
            <td>
                <p>≥ v7.6.2c</p>
            </td>
            <td>
                <p>v7.6.2c is the first version to add basic TrustZone support on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Simplicity Studio</p>
            </td>
            <td>
                <p>≥ v5.6.3.0</p>
            </td>
            <td>
                <p>v5.6.3.0 is the first version to support TrustZone software development on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Simplicity Commander</p>
            </td>
            <td>
                <p>≥ v1.13.3</p>
            </td>
            <td>
                <p>v1.13.3 includes a TrustZone-aware flash loader and supports features required for TrustZone development.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GSDK</p>
            </td>
            <td>
                <p>≥ v4.2.2</p>
            </td>
            <td>
                <p>GSDK v4.2.2 is the first version to support TrustZone software development on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SE Firmware</p>
            </td>
            <td>
                <p>≥ v1.2.14</p>
            </td>
            <td>
                <p>v1.2.14 is the first version to fully support TrustZone on xG21 (HSE) and xG22 (VSE) devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SE Firmware</p>
            </td>
            <td>
                <p>≥ v2.2.1</p>
            </td>
            <td>
                <p>v2.2.1 is the first version to fully support TrustZone on other Series 2 HSE and VSE devices.</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- Required GCC and IAR EWARM versions are GSDK-dependent.
- [Bug list of GCC v10.3](https://gcc.gnu.org/bugzilla/buglist.cgi?bug_status=RESOLVED&resolution=FIXED&target_milestone=10.3)
- [IAR EWARM release note](https://updates.iar.com/?product=EWARM)
- [Segger J-Link release note](https://www.segger.com/downloads/jlink/ReleaseNotes_JLink.html)
- [Simplicity Studio user guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/)
- [Latest version of Simplicity Commander](https://www.silabs.com/developers/mcu-programming-options)
- [GSDK release note](https://github.com/SiliconLabs/gecko_sdk/releases)
- Silicon Labs strongly recommends installing the latest SE firmware on Series 2 devices to support the required TrustZone features. The latest SE firmware image and release notes after installing the GSDK (Windows folder):  
  C:\Users<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public

###### Peripheral Addresses in Device Header Files

The device header files (e.g., efr32mg21b020f1024im32.h) need to be configurable for different situations. The `SL_TRUSTZONE_SECURE` and `SL_TRUSTZONE_NONSECURE` definitions specify whether the compilation is for Secure or Non-secure applications. The `SL_TRUSTZONE_SECURE` and `SL_TRUSTZONE_NONSECURE` should be exclusive. If none of the definitions are true, the state should be similar to the Non-secure configuration, but the [startup code](#startup-code) (`SystemInit()` in system_*.c) will be responsible for reconfiguring the system.

<table>
    <thead>
        <tr>
            <th>Define (Software Component)</th>
            <th>Default Peripheral Pointer</th>
            <th>Startup Code</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SL_TRUSTZONE_SECURE (TrustZone Secure)</p>
            </td>
            <td>
                <p>Point to Secure peripherals (*_BASE = *_S_BASE)</p>
            </td>
            <td>
                <p>No effect on SystemInit()</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SL_TRUSTZONE_NONSECURE (TrustZone Non-Secure)</p>
            </td>
            <td>
                <p>Point to Non-secure peripherals (*_BASE = *_NS_BASE)</p>
            </td>
            <td>
                <p>No effect on SystemInit()</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>None of the above (-)</p>
            </td>
            <td>
                <p>Point to Non-secure peripherals (*_BASE = *_NS_BASE)</p>
            </td>
            <td>
                <p>SystemInit() moves peripherals to Non-secure</p>
            </td>
        </tr>
    </tbody>
</table>

When building a Secure application (`SL_TRUSTZONE_SECURE` is true), all peripherals shall have their non-suffixed default address pointing to the Secure location of the peripheral (e.g., EMU). But the definitions in sl_trustzone_secure_config.h can force the addresses of specific peripherals pointing to the Non-secure location.

```C

#ifndef SL_TRUSTZONE_SECURE_CONFIG_H
#define SL_TRUSTZONE_SECURE_CONFIG_H
// Specify security configuration of peripherals. Peripherals that are not
// included here will automatically have their _BASE addresses point to their
// secure address. This might not be true, since most peripherals are configured
// to be non-secure -- but it's also not a problem if the peripheral is not
// accessed from the S app.
// Used in multiple places.
#define SL_TRUSTZONE_PERIPHERAL_CMU_S (0)
// Used by SE Manager service.
#define SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S (0)
// Used by MSC service.
#define SL_TRUSTZONE_PERIPHERAL_LDMA_S (1)
// Used by MSC service.
#define SL_TRUSTZONE_PERIPHERAL_LDMAXBAR_S (1)
#endif // SL_TRUSTZONE_SECURE_CONFIG_H

```

```C

#if defined(SL_CATALOG_TRUSTZONE_SECURE_CONFIG_PRESENT)
#include "sl_trustzone_secure_config.h"
#endif
#if ((defined(SL_TRUSTZONE_SECURE) && !defined(SL_TRUSTZONE_PERIPHERAL_EMU_S))
    || (defined(SL_TRUSTZONE_PERIPHERAL_EMU_S) && (SL_TRUSTZONE_PERIPHERAL_EMU_S != 0)))
#define EMU_BASE               (EMU_S_BASE)                  /* EMU base address */
#else

```

In other cases (`SL_TRUSTZONE_NONSECURE` is true or both `SL_TRUSTZONE_SECURE` and `SL_TRUSTZONE_NONSECURE` are false), all peripherals shall have their non-suffixed default address pointing to the Non-secure location of the peripheral (e.g., EMU).

```C

#define EMU_BASE               (EMU_NS_BASE)                 /* EMU base address */

```

> **Note**: Do not install the **TrustZone Secure** or **TrustZone Non-Secure** software component to the [TrustZone-unaware](#startup-code) application.

###### Startup Code

The startup code moves peripherals from Secure to Non-secure to support the [default peripheral locations](#peripheral-addresses-in-device-header-files). In a TrustZone-aware application (either `SL_TRUSTZONE_SECURE` or `SL_TRUSTZONE_NONSECURE` is true), this is the application's responsibility (skip lines 168 to 194 in `SystemInit()`) and is done in the [Secure firmware](02-r-basic) of the system.

For the TrustZone-unaware application (both `SL_TRUSTZONE_SECURE` and `SL_TRUSTZONE_NONSECURE` are false), the `SystemInit()` in system_*.c (e.g., system_efr32mg21.c) moves peripherals to the Non-secure location.

- The `SystemInit()` sets the accesses of all peripherals to Non-secure except for the [SMU](03-r-bls) and HSE SEMAILBOX (lines 172 to 178).
- The `SystemInit()` sets the SAU in [All Non-secure](03-r-bls) configuration (lines 180 to 187).  
  - It ensures Non-secure access to Non-secure peripherals.  
  - The device component files (e.g., `efr32mg21b020f1024im32.slcc`) enable the [CMSE](https://developer.arm.com/documentation/ecm0359818/latest) compiler option (`-mcmse` for GCC and `--cmse` for IAR) to pass the condition in line 181 to program the SAU.  
  - To catch the missing CMSE compiler option, it will generate a preprocessor error (line 186) if the CMSE flag is not set when manually upgrading a project from GSDK v4.0.x to ≥v4.1.x for the TrustZone-unaware application.
- The `SystemInit()` does not program the [ESAU](03-r-bls) (default Secure flash is 32 MB), so the whole program is run in the **Secure** state.
- The `SystemInit()` also enables the [`BMPUSEC`](03-r-bls) and [`PPUSEC`](03-r-bls) interrupts in the SMU (lines 189 to 193). It ensures the TrustZone-unaware application catches any violations of Bus Master and peripheral security access permissions.

![system_init](/series2-trustzone/0.2/images/sld717-system-init.png)

The `SMU_BASE` and HSE `SEMAILBOX_HOST_BASE` in device header files must point to the Secure location regardless of the `SL_TRUSTZONE_SECURE` and `SL_TRUSTZONE_NONSECURE` settings to avoid security violations on peripherals in the TrustZone-unaware application (SMU and HSE SEMAILBOX are set to Secure peripherals).

```C

#if ((defined(SL_TRUSTZONE_SECURE) && !defined(SL_TRUSTZONE_PERIPHERAL_SMU_S))
    || (defined(SL_TRUSTZONE_PERIPHERAL_SMU_S) && (SL_TRUSTZONE_PERIPHERAL_SMU_S != 0)))
#define SMU_BASE               (SMU_S_BASE)                  /* SMU base address */
#else
#define SMU_BASE               (SMU_S_BASE)                  /* SMU base address */

```

```C

#if ((defined(SL_TRUSTZONE_SECURE) && !defined(SL_TRUSTZONE_PERIPHERAL_SEMAILBOX_HOST_S))
    || (defined(SL_TRUSTZONE_PERIPHERAL_SEMAILBOX_HOST_S) && (SL_TRUSTZONE_PERIPHERAL_SEMAILBOX_HOST_S != 0)))
#define SEMAILBOX_HOST_BASE    (SEMAILBOX_S_HOST_BASE)       /* SEMAILBOX_HOST base address */
#else
#define SEMAILBOX_HOST_BASE    (SEMAILBOX_S_HOST_BASE)       /* SEMAILBOX_HOST base address */

```

**Notes**:

- The CMSE compiler option of GCC is in the Other flagswindow under C/C++ Build → Settings → Tool Settings → GNU ARM C Compiler→ Miscellaneous.  
  ![gcc_cmse](/series2-trustzone/0.2/images/sld717-gcc-cmse.png)
- The CMSE compiler option of IAR is in the Command line options: (one per line) window under Options... → C/C++ Compiler → Extra Options.  
  ![iar_cmse](/series2-trustzone/0.2/images/sld717-iar-cmse.png)

###### Linker File

The [`template_contribution`](https://siliconlabs.github.io/slc-specification/latest/format/component/template_contribution/) defined in the [slcp](https://siliconlabs.github.io/slc-specification/latest/format/project/) files of [Secure and Non-secure projects](07-r-ex) will override the default memory settings defined in the device component files (e.g., `efr32mg21b020f1024im32.slcc`) to generate the linker files for [Secure](07-r-ex) and [Non-secure](07-r-ex) applications.

<table>
    <thead>
        <tr>
            <th>Memory Region</th>
            <th>Default Setting in Device Component File</th>
            <th>Override Setting in template_contribution</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Flash start address</p>
            </td>
            <td>
                <p>device_flash_addr</p>
            </td>
            <td>
                <p>memory_flash_start</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Flash size</p>
            </td>
            <td>
                <p>device_flash_size</p>
            </td>
            <td>
                <p>memory_flash_size</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>RAM start address</p>
            </td>
            <td>
                <p>device_ram_addr</p>
            </td>
            <td>
                <p>memory_ram_start</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>RAM size</p>
            </td>
            <td>
                <p>device_ram_size</p>
            </td>
            <td>
                <p>memory_ram_size</p>
            </td>
        </tr>
    </tbody>
</table>

![linker_file](/series2-trustzone/0.2/images/sld717-linker-file.png)

The [ESAU](03-r-bls) sets the flash and RAM start address, so these addresses should be alignment at **4 kB** (0x1000). The Secure project linker file needs to have a section for [NSC](02-r-basic) (Secure Gateway) at the end of the Secure flash section. The [SAU](03-r-bls) sets the start address of the NSC section, so this section only needs to be **32 bytes** aligned.

- GCC NSC: The `.gnu.sgstubs` region in the Secure application map file (.map)
- IAR NSC: The `Veneer$$CMSE` region in the Secure application map file (.map)

The Secure and Non-secure flash and RAM sizes are incremented or decremented in **4 kB**. The memory configurations in Secure and Non-secure applications are correlated, so the flash and RAM settings are in pairs.

![mem_config](/series2-trustzone/0.2/images/sld717-mem-config.png)

> **Note**: Users should not directly edit the `template_contribution` in the `slcp` file, but rather use the [Memory Editor](07-r-ex) in Simplicity Studio to update the memory configuration.

###### Debugger

Simplicity Studio supports two [debuggers](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-testing-and-debugging/using-the-debugger):

- GNU Debugger (GDB) client and SEGGER's GDB server
- Simplicity Studio Debugger

The [TrustZone-unaware](#startup-code) and [TrustZone-aware](05-r-implementation) applications enable the [`PPUSEC`](03-r-bls) interrupts in the SMU. The debugger will trigger the `SMU_SECURE_IRQHandler` if the **[Registers]** or **[Peripherals]** view feature violates peripheral security access permission.

###### Simplicity Studio Debugger (heading level 7)

The **[Registers]** view of Simplicity Studio Debugger can only access the Secure location of a peripheral. The following figure demonstrates the `Default_Handler` (`SMU_SECURE_IRQHandler` not defined) is triggered (`PPUSEC` in `SMU->IF` = 1) when viewing the registers of GPIO peripheral (`PPUFSPERIPHID` = 13) that is set to Non-secure access in the SMU.

The debugger can access the registers of the SMU since this peripheral is set to Secure access in the SMU.

This limitation does not apply to **GSDK < v4.1.0** since no peripherals are configured for Non-secure access.

![ppusec_fault](/series2-trustzone/0.2/images/sld717-ppusec-fault.png)

The Simplicity Studio Debugger is not the preferred choice for TrustZone debugging since it has limitations on viewing Non-secure access peripherals.

###### GNU Debugger (GDB) (heading level 7)

The **[Peripherals]** view of GNU Debugger can access either the Secure or Non-secure location of the peripheral to avoid conflicts on security access permission. The following figure shows the registers of GPIO on Secure (`GPIO` at `0x4003C000`) and Non-secure (`GPIO_NS` at `0x5003C000`) addresses. The GPIO peripheral is set to Non-secure access in the SMU, so the registers in the Secure address are displayed as zero.

![register-view](/series2-trustzone/0.2/images/sld717-register-view.png)

The GNU Debugger is the preferred choice for TrustZone debugging and is the default debugger for Simplicity Studio ≥ v5.5.0.0.

##### TrustZone Platform Examples

The following TrustZone platform examples located in the C:\Users<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\app\common\example folder (Windows) demonstrate the TrustZone implementation on Series 2 devices. All TrustZone platform examples do not include [Gecko Bootloader](05-r-implementation).

###### TrustZone PSA Attestation

![tz_attestation](/series2-trustzone/0.2/images/sld717-tz-attestation.png)

![tz_attestation_folder](/series2-trustzone/0.2/images/sld717-tz-attestation-folder.png)

<table>
    <thead>
        <tr>
            <th>Example Folder</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>tz_psa_attestation</p>
            </td>
            <td>
                <p>The workspace description file (tz_psa_attestation_ws.slcw) creates the TrustZone PSA Attestation example. The project description file (tz_psa_attestation_s.slcp) configures a Secure application that provides the Secure Library functionality required by the Non-secure application.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>tz_psa_attestation_ns</p>
            </td>
            <td>
                <p>The project description file (tz_psa_attestation_ns.slcp) configures a Non-secure application for the TrustZone PSA Attestation example.</p>
            </td>
        </tr>
    </tbody>
</table>

**Notes**:

- This example cannot run if the `SECURE_BOOT_ENABLE` (root of trust of the attestation) option in SE OTP is disabled.
- The combined image of Secure and Non-secure applications is signed by the `example_signing_key.pem` (private key) in C:\Users<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\platform\commonfolder (Windows). The `example_signing_pubkey.pem` (public key) in the same folder is installed to the SE OTP to verify the image signature during [Secure Boot](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

###### TrustZone PSA Crypto ECDH

![tz-ecdh](/series2-trustzone/0.2/images/sld717-tz-ecdh.png)

![tz-cdh-folder](/series2-trustzone/0.2/images/sld717-tz-ecdh-folder.png)

|Example Folder|Description|
|---|---|
|tz_psa_crypto_ecdh|The workspace description file (tz_psa_crypto_ecdh_ws.slcw) upgrades the existing Platform - PSA Crypto ECDH example to TrustZone-aware. The project description file (tz_psa_crypto_ecdh_s.slcp) configures a Secure application that provides the Secure Library functionality required by the Non-secure application.|
|tz_psa_crypto_ecdh_ns|The project description file (tz_psa_crypto_ecdh_ns.slcp) configures the existing Platform - PSA Crypto ECDH example as a Non-secure application. The source code can be reused without changes.|

The following sections use Simplicity Studio v5.6.3.0 and GSDK v4.2.2. The procedures and pictures may be different if using higher versions of Simplicity Studio 5 and GSDK.

###### Project Description File

The project description file ([`.slcp`](https://siliconlabs.github.io/slc-specification/1.0/format/project/)) contains references to the GSDK used and a list of components to use from these. The TrustZone-aware application requires separate `slcp` files for the Secure and Non-secure applications.

Users should not directly edit the `slcp` files, but rather use the [Memory Editor](#memory-editor) and Post Build Editor in Simplicity Studio to update the [memory configuration](#memory-configuration) and post-build actions.

###### Secure Application (heading level 7)

The following figure describes which TrustZone software components are installed for the TrustZone Secure library of the [TrustZone PSA Crypto ECDH](#trustzone-platform-examples) example.

![tz_secure_component](/series2-trustzone/0.2/images/sld717-tz-secure-component.png)

**Notes**:

- The services provided by the Secure library are standardized.
- The source files for the Secure library will be automatically added to the application when generating the Secure project from the `slcp` file. For the current TrustZone implementation, modifications of the source files of the Secure library are not recommended.

###### Non-secure Application (heading level 7)

The following figure describes which TrustZone software components are installed for the Non-secure application of the [TrustZone PSA Crypto ECDH](#trustzone-platform-examples) example.

![tz_nonsecure_component](/series2-trustzone/0.2/images/sld717-tz-nonsecure-component.png)

**Notes**:

- The following software components are automatically installed when [PSA Crypto and ITS](05-r-implementation) services are used on the Non-secure application.  
  - MSC Service for TrustZone Secure Key Library  
  - NVM3 Service for TrustZone Secure Key Library  
  - PSA Crypto Service for TrustZone Secure Key Library  
  - PSA ITS Service for TrustZone Secure Key Library  
  - SYSCFG Service for TrustZone Secure Key Library
- The following software components can be installed to the Non-secure application when those services are required.  
  - [PSA Attestation Service for TrustZone Secure Key Library](05-r-implementation#psa-attestation)  
  - [SE Manager Service for TrustZone Secure Key Library](05-r-implementation#se-manager)

###### Workspace

A workspace is a structure that can contain multiple projects. 'Workspace' is a generic term for this construct. In the context of Simplicity Studio, where workspace has a different, Eclipse-based, meaning, workspaces are referred to as [Solutions](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-developing-with-project-configurator/project-solutions).

The workspace description file ([`.slcw`](https://siliconlabs.github.io/slc-specification/latest/format/workspace/)) contains references to projects ([`.slcp`](https://siliconlabs.github.io/slc-specification/latest/format/project/)) that make up the workspace. Users should not directly edit the `slcw` file, but rather use the Post Build Editor in Simplicity Studio to update the post-build actions.

###### Memory Configuration

The [memory configurations](06-r-migration#linker-file) in the TrustZone platform examples are based on the Series 2 radio board with minimum flash (512 kB) and RAM (32 kB), so these configurations can run on all Series 2 radio boards. Users can customize the settings when more flash and RAM are available on the selected device.

- Memory flash size (total) = `memory_flash_size` (S) + `memory_flash_size` (NS) = 512 kB
- Memory RAM size (total) = `memory_ram_size` (S) + `memory_ram_size` (NS) = 32 kB

###### Secure Application (heading level 7)

The project description file of the Secure application (`*_s.slcp`) uses the default memory setting below to generate the [Secure linker file](06-r-migration) (linkerfile.ld for GCC and linkerfile.icf for IAR in the project autogen folder).

The actual memory usage during software development is unknown, so it needs to reserve enough flash (`memory_flash_size`: 176 kB) and RAM (`memory_ram_size`: 12 kB) for the Secure part of all TrustZone platform examples. The bigger RAM size (including stack and heap) is mainly for the software fallback on cryptographic operations in PSA Crypto.

<table>
    <thead>
        <tr>
            <th>Default Memory Setting (Secure)</th>
            <th>xG21 and xG22 Devices</th>
            <th>Other Series 2 Devices</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>memory_flash_start</p>
            </td>
            <td>
                <p>0x00000000</p>
            </td>
            <td>
                <p>0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>memory_flash_size</p>
            </td>
            <td>
                <p>0x0002C000 (176 kB)</p>
            </td>
            <td>
                <p>0x0002C000 (176 kB)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>memory_ram_start</p>
            </td>
            <td>
                <p>0x20000000</p>
            </td>
            <td>
                <p>0x20000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>memory_ram_size</p>
            </td>
            <td>
                <p>0x00003000 (12 kB)</p>
            </td>
            <td>
                <p>0x00003000 (12 kB)</p>
            </td>
        </tr>
    </tbody>
</table>

```C

 MEMORY
 {
   FLASH   (rx)  : ORIGIN = 0x0, LENGTH = 0x2c000
   RAM     (rwx) : ORIGIN = 0x20000000, LENGTH = 0x3000
 }

```

###### Non-secure Application (heading level 7)

The project description files of the Non-secure application (*_ns.slcp) use the default memory setting below to generate the [Non-secure linker file](06-r-migration) (linkerfile.ld for GCC and linkerfile.icf for IAR in the project autogen folder).

The actual memory usage during software development is unknown, so the remaining flash (`memory_flash_size`: 336 kB) and RAM (`memory_ram_size`: 20 kB) should be big enough for the Non-secure part of all TrustZone platform examples.

<table>
    <thead>
        <tr>
            <th>Default Memory Setting (Non-secure)</th>
            <th>xG21 and xG22 Devices</th>
            <th>Other Series 2 Devices</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>memory_flash_start</p>
            </td>
            <td>
                <p>0x0002C000 (176 kB)</p>
            </td>
            <td>
                <p>0x0802C000 (176 kB)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>memory_flash_size</p>
            </td>
            <td>
                <p>0x00054000 (336 kB)</p>
            </td>
            <td>
                <p>0x00054000 (336 kB)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>memory_ram_start</p>
            </td>
            <td>
                <p>0x20003000 (12 kB)</p>
            </td>
            <td>
                <p>0x20003000 (12 kB)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>memory_ram_size</p>
            </td>
            <td>
                <p>0x00005000 (20 kB)</p>
            </td>
            <td>
                <p>0x00005000 (20 kB)</p>
            </td>
        </tr>
    </tbody>
</table>

```C

 MEMORY
 {
   FLASH   (rx)  : ORIGIN = 0x2c000, LENGTH = 0x54000
   RAM     (rwx) : ORIGIN = 0x20003000, LENGTH = 0x5000
 }

```

> **Note**: The usable flash for Non-secure code should be equal to `memory_flash_size` - `NVM size` (default is 40 kB) if NVM3 storage is required.

###### Memory Editor (heading level 7)

The default memory setting of [Secure](#secure-application) and [Non-secure](#non-secure-application) applications are good enough for software development and debugging. The final memory layouts of Secure and Non-secure projects are deduced by inspecting the flash and RAM usage in the Secure application memory map file (.map).

The [Memory Editor](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/start-a-project#memory-editor) in Simplicity Studio 5 is a graphical tool for editing the memory layout (flash and RAM) of the applications in the workspace. The Memory Editor will update the linker file in the project `autogen` folder with the custom settings. [Rebuild](#build) the projects to use the new memory configurations in the linker files.

The Memory Editor is located at the **Quick Links** and **CONFIGURATION TOOLS** of Secure or Non-secure `slcp` file.

![quick_links](/series2-trustzone/0.2/images/sld717-quick-links.png)

![conf_tools](/series2-trustzone/0.2/images/sld717-conf-tools.png)

The following items will be determined by the flash usage in the Secure application memory map file:

- memory_flash_size (S)
- memory_flash_start (NS)
- memory_flash_szie (NS)

![memory_edit_flash](/series2-trustzone/0.2/images/sld717-memory-edit-flash.png)

> **Note**: The Memory Editor in Simplicity Studio v5.6.3.0 can only adjust the flash size in **8 kB** (page size) alignment, which may not fit the [4kB alignment](06-r-migration) between the Secure and Non-secure flash boundary.

The following items will be determined by the RAM usage in the Secure application memory map file:

- memory_ram_size (S)
- memory_ram_start (NS)
- memory_ram_szie (NS)

![memory_edit_ram](/series2-trustzone/0.2/images/sld717-memory-edit-ram.png)

###### Build

The Secure project must be built first to create the Secure object library (trustzone_secure_library.o) with function entries for the Non-secure project. Both projects need to be rebuilt if any changes in the Secure project. Users can use Simplicity IDE in Simplicity Studio 5 or IAR EWARM v9.20.4 to build the TrustZone platform examples.

###### Simplicity IDE (heading level 7)

The following procedures are based on the **TrustZone PSA Crypto ECDH** example on BRD4182A Radio Board (EFR32MG22C224F512IM40).

1. Use the `tz_psa_crypto` keyword to search in **EXAMPLE PROJECTS & DEMOS** tab. Select the **`tz_psa_crypto_ecdh_ws`** example.

![tz_gcc_search_ws](/series2-trustzone/0.2/images/sld717-tz-gcc-search-ws.png)
2. Click **[CREATE]** to generate the [solution](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-developing-with-project-configurator/project-solutions).

![./resources/sld717-tz_ecdh](/series2-trustzone/0.2/images/sld717-tz-ecdh.png)
3. The **Project Configuration** dialog shows the Secure and Non-secure projects in the target solution. Click **[FINISH]** to start the creation process.

![tz_gcc_proj_conf](/series2-trustzone/0.2/images/sld717-tz-gcc-proj-conf.png)
4. The Simplicity IDE perspective opens after finishing the solution creation. Click **Build** on the Simplicity IDE perspective toolbar to build the projects of a selected solution in order (Secure then Non-secure).

![tz_gcc_build](/series2-trustzone/0.2/images/sld717-tz-gcc-build.png)
5. The post-build actions (`.slpb` files) of the Secure project, Non-secure project, and workspace will be processed in sequence if the solution is successfully built. The combined image (tz_psa_crypto_ecdh_ws-combined.s37) in the Secure project artifact folder can be used for programming the device or debugging.

![tz_gcc_combine](/series2-trustzone/0.2/images/sld717-tz-gcc-combine.png)
6. Use [Memory Editor](#memory-editor) to finalize the memory layouts of Secure and Non-secure applications and rebuild the solution to update the memory configurations.

> **Note**: The Simplicity IDE can only apply the post-build action to a particular project if multiple Secure or Non-secure projects exist in the solution.

###### IAR EWARM (heading level 7)

The following procedures are based on the **TrustZone PSA Crypto ECDH** example on BRD4181A Radio Board (EFR32MG21A010F1024IM32).

1. Follow steps 1 to 3 in [TrustZone PSA Crypto ECDH](#simplicity-ide) to generate the solution for the `tz_psa_crypto_ws`. Select the `tz_psa_crypto_ecdh_s.slcp` file.
2. The **Overview** tab shows the **Target and Tool Settings** card on the left side. Scroll down if necessary and click **[ChangeTarget/SDK/Generators]**.

![tz_iar_s_change](/series2-trustzone/0.2/images/sld717-tz-iar-s-change.png)
3. Drop down the **CHANGE PROJECT GENERATORS** list and select **IAR Embedded Workbench Project**.

![tz_iar_s_select](/series2-trustzone/0.2/images/sld717-tz-iar-s-select.png)
4. Click **[Save]** to generate an IAR **Secure** project (tz_psa_crypto_ecdh_s.ewp).

![tz_iar_s_save](/series2-trustzone/0.2/images/sld717-tz-iar-s-save.png)
5. Select the `tz_psa_crypto_ecdh_ns.slcp` file. Repeat steps 2 to 4 to generate an IAR **Non-secure*** project (tz_psa_crypto_ecdh_ns.ewp).
6. Use a text editor to create an IAR tz_psa_crypto_ecdh_ws.ewwfile (shown below) to house the projects (tz_psa_crypto_ecdh_s.ewpand tz_psa_crypto_ecdh_ns.ewp) generated in steps 4 and 5. The location of the tz_psa_crypto_ecdh_ws.eww is the directory for WS_DIR.

```C

<?xml version ="1.0" encoding="iso-8859-1"?>
<workspace>
  <project>
    <path>$WS_DIR$\tz_psa_crypto_ecdh_s\tz_psa_crypto_ecdh_s.ewp</path>
  </project>
  <project>
    <path>$WS_DIR$\tz_psa_crypto_ecdh_ns\tz_psa_crypto_ecdh_ns.ewp</path>
  </project>
  <batchBuild/>
</workspace>

```

![./resources/sld717-tz_iar_folder](/series2-trustzone/0.2/images/sld717-tz-iar-folder.png)
7. Double-click the tz_psa_crypto_ecdh_ws.ewwfile to open the workspace that includes Secure and Non-secure projects.
![./resources/sld717-tz_iar_ws](/series2-trustzone/0.2/images/sld717-tz-iar-ws.png)
8. Click the tz_psa_crypto_ecdh_s tab to open the Secure project. Click ![tz_iar_make_icon](/series2-trustzone/0.2/images/sld717-tz-iar-make-icon.png) (Make) to build. It exports the Secure object library (trustzone_secure_library.o) for function entries that will be used by the Non-secure project.

![tz_iar_s](/series2-trustzone/0.2/images/sld717-tz-iar-s.png)
9. Click the tz_psa_crypto_ecdh_ns tab to open the Non-secure project.

![./resources/sld717-tz_iar_ns](/series2-trustzone/0.2/images/sld717-tz-iar-ns.png)
10. The [`SL_TRUSTZONE_NONSECURE`](06-r-migration#peripheral-addresses-in-device-header-files) defined in the Non-secure project disables the [CMSE compiler option](06-r-migration#startup-code) (`--cmse`) regardless of whether the **Project → Options... → General Options → 32-bit → TrustZone → Mode:** setting is Secure or Non-secure. So changing this configuration from Secure to Non-secure is optional. Click **[OK]** to exit.

![tz_iar_select_ns](/series2-trustzone/0.2/images/sld717-tz-iar-select-ns.png)
11. Click ![tz_iar_make_icon](/series2-trustzone/0.2/images/sld717-tz-iar-make-icon.png) (Make) to build the Non-secure project. The post-build actions of the workspace (tz_psa_crypto_ecdh_ws.slpb) will be triggered in IAR to combine the Secure and Non-secure images (tz_psa_crypto_ecdh_ws-combined.s37) to the artifact folder of `tz_psa_crypto_ecdh_s` for programming the device.

![tz_iar_combine](/series2-trustzone/0.2/images/sld717-tz-iar-combine.png)
12. Use [Memory Editor](#memory-editor) to finalize the memory layouts of Secure and Non-secure applications and rebuild the Secure and Non-secure projects to update the memory configurations.

> **Note**: The IAR EWARM can only apply the workspace post-build action to a particular project if multiple Secure or Non-secure projects exist in the workspace.

###### Debugging

Users can use Simplicity IDE in Simplicity Studio 5 or IAR EWARM v9.20.4 to debug the TrustZone platform examples. Building the projects with Optimization Level None (-O0) is recommended for debugging.

###### Simplicity IDE (heading level 7)

The TrustZone debugging process on Simplicity IDE is similar to the existing sample projects in Simplicity Studio.

1. [GNU Debugger (GDB)](06-r-migration#debugger) is recommended to debug TrustZone applications.
2. Flash the combined image (tz_psa_crypto_ecdh_ws-combined.s37) generated in [Simplicity IDE](#simplicity-ide) to the device.
3. Select the Secure or Non-secure project and use the **Debug** icon to launch a debug session.

![gcc_debug_launch](/series2-trustzone/0.2/images/sld717-gcc-debug-launch.png)
4. Follow the instructions in the **[Using the Debugger](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-testing-and-debugging/using-the-debugger)** section in Simplicity Studio 5 User's Guide to debug the Secure or Non-secure application.
5. The debugger cannot step into the function in a Non-secure application when debugging the Secure application and vice versa. Use the **Program Counter** (PC in Secure or Non-secure address) in the **Registers** window to determine the program status.

![gcc_debug_state](/series2-trustzone/0.2/images/sld717-gcc-debug-state.png)

###### IAR EWARM (heading level 7)

Use the tz_psa_crypto_ecdh_ws.eww workspace created in [IAR EWARM](#iar-ewarm) for the debugger settings. Except for a minor difference in step 3, the following steps are the same as those to set up the Secure (tz_psa_crypto_ecdh_s) and Non-secure (tz_psa_crypto_ecdh_ns) projects for debugging.

1. Select **Options...** in the ![tools_menu](/series2-trustzone/0.2/images/sld717-tools-menu.png) context menu of the Secure or Non-secure project and open the **IDE Options → Stack** dialog. Uncheck the **Stack pointer(s) not valid until program reaches*** checkbox. Click **[OK]** to exit.

![uncheck_stack](/series2-trustzone/0.2/images/sld717-uncheck-stack.png)
2. Select **Options...** in the ![project_menu](/series2-trustzone/0.2/images/sld717-project-menu.png) context menu of the Secure or Non-secure project and open the window for **Debugger** options. Click the **Setup** tab to open a dialog, and uncheck the **Run to → main** checkbox. Click the **Images** tab to set up another option.

![uncheck_main](/series2-trustzone/0.2/images/sld717-uncheck-main.png)
3. Check the **ownload extra image** option. Enter the location of the .out file to **Path:** with **Offset:** set to 0. All project relative paths are resolved from the directory location of the tz_psa_crypto_ecdh_ws.eww workspace file.

Location of Non-secure .out file for Secure project: tz_psa_crypto_ecdh_ns\ewarm-iar\exe\tz_psa_crypto_ecdh_ns.out

![set_image_s](/series2-trustzone/0.2/images/sld717-set-image-s.png)

Location of Secure .out file for Non-secure project: tz_psa_crypto_ecdh_s\ewarm-iar\exe\tz_psa_crypto_ecdh_s.out

![set_image_ns](/series2-trustzone/0.2/images/sld717-set-image-ns.png)
4. Click the **Extra Options** tab to set up another option.
5. Check the **Use command line options**. Enter --drv_vector_table_base=0x00000000 to **Command line options: (one per line)** window. Click **[OK]** to exit.

![set_extra](/series2-trustzone/0.2/images/sld717-set-extra.png)
6. Finish the debug settings in Secure and Non-secure projects, and click ![debug_icon](/series2-trustzone/0.2/images/sld717-debug-icon.png) (Download and Debug) in the Secure or Non-secure project to download the Secure and Non-secure images for debugging (assume both projects had successfully [built](#iar-ewarm) before). Click ![go_icon](/series2-trustzone/0.2/images/sld717-go-icon.png) (Go) to start running the code in a Secure or Non-secure project.
7. The debugger will automatically switch between Secure and Non-secure projects when stepping into a function or hitting a breakpoint in a Secure or Non-secure project. Use the **Program Counter** (PC in Secure or Non-secure address) or **SECURE** (0 or 1) in the **Registers** window to determine the program status.

![debug_state](/series2-trustzone/0.2/images/sld717-debug-state.png)
8. Click ![stop_icon](/series2-trustzone/0.2/images/sld717-stop-icon.png) (Stop Debugging) to end the debug session.

###### Benchmark

The TrustZone implementation will affect the memory footprint and performance of cryptographic operations. The following comparisons are based on the **TrustZone PSA Crypto ECDH** example on BRD4182A Radio Board (EFR32MG22C224F512IM40) with SE firmware v1.2.14.

###### Memory Footprint (heading level 7)

The memory footprint of a TrustZone project depends on which services (software components in the figure below) provided by the [Secure Library](05-r-implementation) are used in the Non-secure application (`tz_psa_crypto_ecdh_ns` project).

![tz_nonsecure_component](/series2-trustzone/0.2/images/sld717-tz-nonsecure-component.png)

The following tables compare the memory footprint of the [TrustZone-unaware](06-r-migration#startup-code) (`Platform - PSA Crypto ECDH`) and [TrustZone-aware](07-r-ex#memory-configuration) projects (`tz_psa_crypto_ecdh_ws`) based on the following conditions.

- The `tz_psa_crypto_ecdh_ns` reuses the source code from the `Platform - PSA Crypto ECDH` example without any changes.
- The total size in `tz_psa_crypto_ecdh_ns` does not consider the [4 kB alignment](06-r-migration) on the Secure and Non-secure flash and RAM. The 4 kB alignment requirement will increase the actual usage of flash and RAM.
- All source code is compiled with Optimize for size (-Os) in Simplicity IDE (GNU ARM v10.3.1) of Simplicity Studio 5.

**Table**: Flash Size Comparison

<table>
    <thead>
        <tr>
            <th>Platform Example</th>
            <th>Secure</th>
            <th>NSC</th>
            <th>Non-secure</th>
            <th>Total</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Platform - PSA Crypto ECDH</p>
            </td>
            <td>
                <p>64688 B</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>64688 B</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>tz_psa_crypto_ecdh_ws</p>
            </td>
            <td>
                <p>79172 B</p>
            </td>
            <td>
                <p>288 B</p>
            </td>
            <td>
                <p>29264 B</p>
            </td>
            <td>
                <p>108724 B</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The NSC is part of the Secure code, and the total size does not include the flash for NVM3 storage.

**Table**: RAM Size Comparison

<table>
    <thead>
        <tr>
            <th>Platform Example</th>
            <th>Secure</th>
            <th>NSC</th>
            <th>Non-secure</th>
            <th>Total</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Platform - PSA Crypto ECDH</p>
            </td>
            <td>
                <p>3784 B</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>3764 B</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>tz_psa_crypto_ecdh_ws</p>
            </td>
            <td>
                <p>2156 B</p>
            </td>
            <td>
                <p>-</p>
            </td>
            <td>
                <p>1200 B</p>
            </td>
            <td>
                <p>3356 B</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The total size does not include the RAM for the stack and heap. The Secure and Non-secure applications have their independent stack and heap.

###### PSA Crypto Performance (heading level 7)

The following sections compare the PSA Crypto performance of the [TrustZone-unaware](06-r-migration) (`Platform - PSA Crypto ECDH`) and [TrustZone-aware](#memory-configuration) projects (`tz_psa_crypto_ecdh_ws`) based on the following conditions.

- The `tz_psa_crypto_ecdh_ns` reuses the source code from the `Platform - PSA Crypto ECDH` example without any changes.
- All source code is compiled with Optimize most (-O3) in Simplicity IDE (GNU ARM v10.3.1) of Simplicity Studio 5.
- Use ECC curve `SECP256R1` on volatile and persistent keys.
- The EFR32MG22C224 runs at 38 MHz HFRCODPLL.

###### Volatile key ECDH operation on `Platform - PSA Crypto ECDH` (heading level 8)

```C

  . ECDH Client
  + Creating a SECP256R1 (256-bit) VOLATILE PLAIN client key... PSA_SUCCESS (cycles: 2928 time: 77 us)
  + Creating a SECP256R1 (256-bit) VOLATILE PLAIN server key... PSA_SUCCESS (cycles: 2960 time: 77 us)
  + Exporting a public key of a SECP256R1 (256-bit) VOLATILE PLAIN server key... PSA_SUCCESS (cycles: 332134 time: 8740 us)
  + Computing client shared secret with a SECP256R1 (256-bit) server public key... PSA_SUCCESS (cycles: 336860 time: 8864 us)

```

###### Volatile key ECDH operation on `tz_psa_crypto_ecdh_ws` (heading level 8)

```C

  . ECDH Client
  + Creating a SECP256R1 (256-bit) VOLATILE PLAIN client key... PSA_SUCCESS (cycles: 5047 time: 132 us)
  + Creating a SECP256R1 (256-bit) VOLATILE PLAIN server key... PSA_SUCCESS (cycles: 5067 time: 133 us)
  + Exporting a public key of a SECP256R1 (256-bit) VOLATILE PLAIN server key... PSA_SUCCESS (cycles: 333956 time: 8788 us)
  + Computing client shared secret with a SECP256R1 (256-bit) server public key... PSA_SUCCESS (cycles: 338470 time: 8907 us)

```

###### Persistent key ECDH operation on `Platform - PSA Crypto ECDH` (heading level 8)

```C

  . ECDH Client
  + Creating a SECP256R1 (256-bit) PERSISTENT PLAIN client key... PSA_SUCCESS (cycles: 27489 time: 723 us)
  + Creating a SECP256R1 (256-bit) PERSISTENT PLAIN server key... PSA_SUCCESS (cycles: 27587 time: 725 us)
  + Exporting a public key of a SECP256R1 (256-bit) PERSISTENT PLAIN server key... PSA_SUCCESS (cycles: 332949 time: 8761 us)
  + Computing client shared secret with a SECP256R1 (256-bit) server public key... PSA_SUCCESS (cycles: 337803 time: 8889 us)

```

###### Persistent key ECDH operation on `tz_psa_crypto_ecdh_ws` (heading level 8)

```C

  . ECDH Client
  + Creating a SECP256R1 (256-bit) PERSISTENT PLAIN client key... PSA_SUCCESS (cycles: 46998 time: 1236 us)
  + Creating a SECP256R1 (256-bit) PERSISTENT PLAIN server key... PSA_SUCCESS (cycles: 45962 time: 1209 us)
  + Exporting a public key of a SECP256R1 (256-bit) PERSISTENT PLAIN server key... PSA_SUCCESS (cycles: 334127 time: 8792 us)
  + Computing client shared secret with a SECP256R1 (256-bit) server public key... PSA_SUCCESS (cycles: 338321 time: 8903 us)

```

The overheads on the TrustZone-aware project (`tz_psa_crypto_ecdh_ws`) are due to the following operations of [Secure Library](05-r-implementation) implementation.

- Packages the list of input arguments in the appropriate format before calling into the NSC function.
- Switches from a Non-secure to a Secure state.
- Validates all input arguments before calling into the function in SPE.
- Encrypts PSA ITS if using a persistent key.
- Returns to a Non-secure state.

### Coexistence

#### Coexistence

This section describes implementing managed coexistence to improve coexistence of Bluetooth with other protocol traffic.

- [**Wi-Fi Coexistence Fundamentals**](/bluetooth/11.0.1/multiprotocol-wifi-coexistence-fundamentals): Introduces methods to improve the coexistence of 2.4 GHz IEEE 802.11b/g/n Wi-Fi and other 2.4 GHz radios such as Bluetooth, Bluetooth Mesh, and Bluetooth Low Energy with IEEE 802.15.4-based radios such as Zigbee and OpenThread.
- [**Bluetooth Coexistence with Wi-Fi**](/bluetooth/11.0.1/bluetooth-coexistence-with-wifi): Describes the Wi-Fi impact on Bluetooth and methods to improve Bluetooth coexistence with Wi-Fi. Explains design considerations to improve coexistence without direct interaction between Bluetooth and Wi-Fi radios. These techniques are applicable to the EFR32MGx and EFR32BGx series. Discusses the Silicon Labs Packet Traffic Arbitration (PTA) support to coordinate 2.4GHz RF traffic for co-located Bluetooth and Wi-Fi radios.

#### Wi-Fi Coexistence Fundamentals

##### Wi-Fi Coexistence Fundamentals

> **Note: This section replaces _UG103.17: Wi-Fi Coexistence Fundamentals_. Further updates to this user guide will be provided here**.

These pages describe methods to improve coexistence of 2.4 GHz IEEE 802.11b/g/n Wi-Fi and other 2.4 GHz radios such as Bluetooth®, Bluetooth Mesh, Bluetooth Low Energy, and IEEE 802.15.4-based radios such as Zigbee® and OpenThread. These techniques are applicable to the EFR32MGxx and EFR32BGxx families.

For additional details about the implementation of managed coexistence for EFR32 devices refer to the following application notes:

- [Bluetooth Coexistence with Wi-Fi](https://docs.silabs.com/bluetooth/latest/bluetooth-coexistence-with-wifi/)
- [Zigbee and OpenThread Coexistence with Wi-Fi](https://docs.silabs.com/multiprotocol/latest/zigbee-openthread-coexistence-wifi/)
- _AN1243: Timing and Test Data for EFR32 Coexistence with Wi-Fi_ (available under non-disclosure from Silicon Labs Sales).

For evaluating the Silicon Labs EFR32 software coexistence solution, order EFR32MG Wireless SoC Starter Kit (WSTK) #SLWSTK6000B and Coexistence Backplane EVB (#SLWSTK-COEXBP). Detailed instructions for using the Starter Kit and Backplane EVB are found in [Silicon Labs Coexistence Development Kit (SLWSTK-COEXBP)](https://docs.silabs.com/multiprotocol/latest/coexistence-development-kit/). To see a demonstration of Wi-Fi coexistence, access links for ordering the WSTK and EVB, and to download additional coexistence documentation, visit the [Silicon Labs Wi-Fi Coexistence Learning Center](https://www.silabs.com/products/wireless/learning-center/wi-fi-coexistence).

###### Silicon Labs' Fundamentals Series

Silicon Labs’ Fundamentals series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs Bluetooth®, and associated development tools. The documents can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

###### Coexistence of Radio Standards

The 2.4 GHz Industrial, Scientific and Medical (ISM) band supports Wi-Fi, Bluetooth, and 802.15.4. The simultaneous and co-located operation of these different 2.4 GHz radio standards can degrade performance of one or more of the radios. To improve interference robustness, each of the 2.4 GHz ISM radio standards support some level of collision avoidance and/or message retry capability. At low data throughput rates, low power levels, and/or sufficient physical separation, these 2.4 GHz ISM standards can co-exist without significant performance impacts. However, recent customer trends are making coexistence more difficult:

- Increased Wi-Fi transmit power level for “extended range.”  
  +30 dBm Wi-Fi Access Points are now common.
- Increased Wi-Fi throughput.  
  Depending on achievable Signal-to-Noise Ratio (SNR), high throughput requirements for file transfers and/or video streaming may result in high Wi-Fi duty cycle within the 2.4 GHz ISM band.
- Integrating Wi-Fi, Bluetooth, and 802.15.4 into the same device for gateway functionality.  
  This is required by Home Automation and Security applications and provides easier end-node commissioning.

> **Note**: Zigbee and OpenThread devices (802.15.4) operate at less than +20 dBm transmit power level. With normal network activity, Zigbee/Thread solutions have a relatively low RF duty cycle and Bluetooth solutions implement Adaptive Frequency Hopping (AFH). Silicon Labs’ testing of Bluetooth blocked by Zigbee/Thread shows low impact on Bluetooth with AFH enabled and normal Zigbee/Thread network activity. However, if 100% RF duty cycle, Zigbee/Thread can degrade co-located Bluetooth performance.

##### Wi-Fi Impact on Bluetooth and 802.15.4 Radios

Worldwide, Wi-Fi supports up to 14 overlapping 20/22 MHz bandwidth channels across the 2.4 GHz ISM band with transmit power levels up to +30 dBm. Bluetooth supports 40 non-overlapping channels at 2 MHz spacing with transmit powers up to +20 dBm (Bluetooth Core Specification v5.0). IEEE 802.15.4 supports 16 non-overlapping 2 MHz bandwidth channels at 5 MHz spacing with transmit powers up to +20 dBm. The Bluetooth and 802.15.4 channel mappings are shown in the following figure, where yellow highlighted channels are the three Bluetooth advertising (ADV) channels.

![Wi-Fi, Bluetooth, and 802.15.4 Channel Mapping (World-Wide)](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image8.png)

Actual channels available vary by country. For example, in the USA, only Wi-Fi channels 1 through 11 are available. Bluetooth channels 0 through 39 are available worldwide and Zigbee channels 11 through 26 are available, although channels 25 and 26 require reduced transmit power levels to meet FCC requirements (North America only).

###### Impact of a 100% Duty-Cycled Wi-Fi

Silicon Labs completed testing to understand the effects of Wi-Fi on Bluetooth and 802.15.4 radios. The following subsections summarize the key findings and results from this testing.

###### Bluetooth (heading level 7)

To better understand the effects of Wi-Fi on Bluetooth, Silicon Labs measured the impact of a 100% duty-cycled 802.11n (MCS3, 20 MHz bandwidth) blocker transmitting at various power levels while receiving a Bluetooth 1Mbps 37-byte payload message transmitted at power level sufficient to achieve 0.1% BER (receive sensitivity). The results for co-channel, adjacent channel, and “far-away” channels are shown in the following figure. All 802.11n and Bluetooth power levels are referenced to the Silicon Labs EFR32MG21 RF input. The test application was developed using the Silicon Labs Bluetooth 2.11.0 or later stack with the soc-dtm sample application running on the EFR32 DUT (Device Under Test) and a test script to control the DUT and RF test equipment.

![Bluetooth Low Energy Receive Sensitivity with 100% Duty-Cycled 802.11n (MCS3/20 MHz) Wi-Fi Blocker](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image9.jpg)

From the figure above, the key observations about the impact of Wi-Fi (channel 1, MCS3/20 MHz) on Bluetooth are:

- Co-Channel (Bluetooth overlapping Wi-Fi):  
  - For Bluetooth RF channels 0 through 10, EFR32MG21 can receive a Bluetooth 1Mbps signal at 4 dB weaker than aggregate Wi-Fi transmit power (100% duty cycle).  
  - This receive sensitivity limitation impacts both co-located and remote, not co-located, Bluetooth radios.
- Adjacent Channel (Bluetooth within one Wi-Fi bandwidth):  
  - At Bluetooth RF channel 11, EFR32MG21 can receive a -90 dBm Bluetooth 1Mbps with -40 dBm or weaker Wi-Fi transmit power (100% duty cycle).
- “Far-Away” Channel (Bluetooth beyond one Wi-Fi bandwidth):  
  - At Bluetooth RF channels 19 through 39, EFR32MG21 can receive a -96 dBm Bluetooth 1Mbps signal with -40 dBm or weaker Wi-Fi transmit power (100% duty cycle).

In a real-world environment, Wi-Fi is typically not 100% duty cycle and only approaches 100% duty cycle during file transfers or video stream in low Wi-Fi SNR conditions. As seen in the previous figure, the EFR32xGxx receive sensitivity varies as the Wi-Fi blocker turns ON/OFF. The net result is the ability to see weaker signals when Wi-Fi is OFF, but not when strong Wi-Fi is ON (actively transmitting).

The following figure illustrates the receive range of a node (blue node) near a strong Wi-Fi transmitter. Relative to the blue Bluetooth node, the area inside the green circle represents the receive range when Wi-Fi is ON. The area between the green and yellow circles represents the receive range when Wi-Fi is OFF. From this figure:

- The green node is always receivable by the blue node.
- The yellow node is only receivable by the blue node when Wi-Fi is OFF.
- The red node is never receivable by the blue node.
- The yellow and red nodes are always receivable by the green node.

![EFR32 Receiver Desensitized when Wi-Fi Transmitting](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/efr32-receiver.png)

Depending on each Bluetooth device’s TX level, RX sensitivity vs. blocker, channel, and relative attenuation and Wi-Fi TX level and duty cycle, the impact of strong Wi-Fi turning ON/OFF will vary. Based on the figure above, the following example assumes:

- Wi-Fi co-located with Blue device
- Bluetooth channel is “far-away” (RF channel 39) from Wi-Fi channel (channel 1), indicating minimum Bluetooth RX sensitivity vs. Wi-Fi RX levels:  
  ![Bluetooth RX sensitivity vs. Wi-Fi RX levels](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image11.png)
- Typical radio TX levels:  
  ![Typical radio TX levels](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image12.png)
- Attenuation between radios  
  ![Attenuation between radios](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image13.png)
- Bluetooth device RX **success**/**fail** with Wi-Fi **OFF**:  
  ![Bluetooth device RX success/fail with Wi-Fi OFF](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image14.png)
- Bluetooth device RX **success**/**fail** with Wi-Fi **ON**:  
  ![Bluetooth device RX success/fail with Wi-Fi ON](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image15.png)

Using the example assumptions, all radio communication is maintained between Wi-Fi ON/OFF except:

- Blue device receives yellow device when Wi-Fi ON, but not Wi-Fi OFF.
- Green device receives red device when Wi-Fi ON, but not Wi-Fi OFF.

If devices are Bluetooth devices (point-to-point), blue device communication with:

- Green device is not impacted by Wi-Fi TX.
- Yellow device is erratic as Wi-Fi TX goes ON/OFF.  
  - For high-duty cycle Wi-Fi TX, connection can become unstable as multiple connection intervals fail.
- Red device is not possible.

If devices are Bluetooth mesh devices (mesh network), blue device communication with:

- Green device is not impacted by Wi-Fi TX.
- Yellow device shows erratic communication as Wi-Fi TX goes ON/OFF.  
  - For high-duty cycle Wi-Fi TX, communication would require a relay to forward/repeat missed RX messages from yellow device to blue device.
- Red device is not directly possible, and a relay is required to forward messages between blue device and red device.  
  - If green device is relay, communication with red device shows erratic communication as Wi-Fi TX goes ON/OFF.  
  - If yellow device is relay, communication with red device is not impacted by Wi-Fi TX.

###### 802.15.4 (heading level 7)

To better understand the effects of Wi-Fi on 802.15.4 radios, Silicon Labs measured the impact of a 100% duty-cycled 802.11n (MCS3, 20 MHz bandwidth) blocker transmitting at various power levels while receiving an 802.15.4 message transmitted at power level sufficient to achieve 1% PER (receive sensitivity). The following figure shows the results for co-channel, adjacent channel, and “far-away” channel. All 802.11n and 802.15.4 power levels are referenced to the Silicon Labs’ EFR32MG21 RF input. The test application was developed using Silicon Labs’ EmberZNet PRO (Zigbee) stack with NodeTest running on the EFR32 DUT (Device Under Test) and a test script to control the DUT and RF test equipment.

![802.15.4 Receive Sensitivity with 100% Duty Cycled 802.11n (MCS3/20 MHz) Wi-Fi Blocker](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image16.jpg)

These are the key observations about the impact of Wi-Fi on 802.15.4 from the figure above.

- Co-Channel (Zigbee overlapping Wi-Fi):  
  - At channel 12, Zigbee can receive an 802.15.4 signal down to 9 dBm weaker than aggregate Wi-Fi transmit power (100% duty cycle).    
    - This receive sensitivity limitation impacts both co-located and remote, not co-located, 802.15.4 radios.  
  - At channel 12, Zigbee with and without LNA (Low Noise Amplifier) can receive an 802.15.4 signal down to 9 dB weaker than aggregate Wi-Fi transmit power (100% duty cycle).  
  - 802.15.4 transmits can also be blocked by Wi-Fi transmit power tripping the 802.15.4 -75 dBm CCA (Clear Channel Assessment) threshold.
- Adjacent Channel (Zigbee within one Wi-Fi bandwidth):  
  - At channel 15, Zigbee can receive a -87 dBm 802.15.4 signal with -30 dBm or weaker Wi-Fi transmit power (100% duty cycle).    
    - Maximum receive sensitivity is attained at -38 dBm or weaker Wi-Fi transmit power (100% duty cycle).  
  - At channel 15, Zigbee without LNA can receive a -87 dBm 802.15.4 signal with -30 dBm or weaker Wi-Fi transmit power (100% duty cycle); -34 dBm or weaker with LNA enabled.
- “Far-Away” Channel (Zigbee beyond one Wi-Fi bandwidth):  
  - At channels 17 through 26, Zigbee can receive a -96 dBm 802.15.4 signal with -30 dBm or weaker Wi-Fi transmit power (100% duty cycle).    
    - Maximum receive sensitivity is attained at -40 dBm or weaker Wi-Fi transmit power (100% duty cycle).  
  - At channels 17 through 26, Zigbee without LNA can receive a -96 dBm 802.15.4 signal with -30 dBm or weaker 100% Wi-Fi transmit power (100% duty cycle); -34 dBm or weaker with LNA enabled.

In a real-world environment, Wi-Fi is typically not 100% duty cycle and only approaches 100% duty cycle during file transfers or video stream in low Wi-Fi SNR (Signal to Noise Ratio) conditions. As seen in the figure above, the EFR32xGxx receive sensitivity varies as the Wi-Fi blocker turns ON/OFF. The net result is the ability to see weaker signals when Wi-Fi is OFF, but not when strong Wi-Fi is ON (actively transmitting).

The following figure illustrates the receive range of a node (blue node) near a strong Wi-Fi transmitter. Relative to the blue 802.15.4 node, the area inside the green circle represents the receive range when Wi-Fi is ON. The area between the green and yellow circles represents the receive range when Wi-Fi is OFF. From this figure:

- The green node is always receivable by the blue node.
- The yellow node is only receivable by the blue node when Wi-Fi is OFF.
- The red node is never receivable by the blue node.
- The yellow and red nodes are always receivable by the green node.

![EFR32MGx Receiver Desensitized when Wi-Fi Transmitting](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/efr32-m-gx-receiver.png)

Depending on each node’s type (Coordinator, Router, or End Device) and the Wi-Fi duty cycle, the impact of strong Wi-Fi turning ON/OFF will vary.

In a Zigbee network:

- **Coordinator**: Tasked with network creation, the control of network parameters, and basic maintenance, in addition to performing an application function, such as aggregating data or serving as a central control point or gateway.
- **Router**: In addition to running an application function, a Router can receive and retransmit data from other nodes.
- **End Device**: Typically, a battery-powered device (Sleepy End Device or SED) running an application function and able to talk to a single parent node (either the Coordinator or a Router). End Devices cannot relay data from other nodes.

In an OpenThread network:

- **Border Router**: Provides network node connectivity to other devices in external networks (for example, Internet access).
- **Router**: In addition to running an application function, a Router can receive and retransmit data from other nodes and provide join and security capability. When routing function is not needed by network, a Router can downgrade to a Router-Eligible End Device (REED).
- **REED**: In addition to running an application function, a REED can receive and retransmit data from other nodes. When additional routers needed by network, a REED can upgrade to a Router.
- **SED**: Typically, a battery-powered device running an application function and able to talk to a single parent node (either a Border Router, Router, or REED). SEDs cannot relay data from other nodes.

Two Zigbee cases are considered below, but many other cases are possible.

###### Case 1: Zigbee Coordinator near strong Wi-Fi plus three end-nodes (heading level 7)

For this case, the figure above is composed of:

- **Coordinator**: Blue node
- **End Devices**: Green, Yellow, and Red nodes

In this simple network, each end device attempts to join the network formed by the coordinator. However, the red node is outside of receive range and cannot join. With Wi-Fi OFF, both the green and yellow nodes successfully join the network and have no issues sending messages to the Coordinator. Regardless of Wi-Fi ON/OFF duty cycle, the green node remains successful sending messages to the Coordinator.

With Wi-Fi ON/OFF at low-duty cycle, some messages from the yellow node are periodically blocked, but Zigbee retry mechanisms are effective in getting the messages to the coordinator. However, with Wi-Fi ON/OFF at high-duty cycle, many messages from the yellow node are blocked and Zigbee retry mechanisms may be exhausted. Even when retry mechanisms are successful, the message latency increases. If the yellow node is a battery-powered Sleepy End Device, it must remain active longer to execute retries, reducing battery life.

###### Case 2: Zigbee Coordinator near strong Wi-Fi, Router within always receive range, plus two end-nodes (heading level 7)

For this case, the figure above is composed of:

- **Coordinator**: Blue node
- **Router**: Green node
- **End Devices**: Yellow and Red nodes

In this simple network, the green Router forms a route directly to the Coordinator, maintained regardless of Wi-Fi ON/OFF duty cycle. With Wi-Fi OFF, the yellow node forms a route directly to the blue Coordinator at a lower route cost than a route via the green Router. The red node cannot be received by the Coordinator and its messages are also routed through the Router to the Coordinator.

With Wi-Fi OFF, the green Router, the yellow node, and the red node (via the green Router) have no issues sending messages to the Coordinator. Regardless of Wi-Fi ON/OFF duty cycle, the green Router and the red node (via the green Router) remain successful sending messages to the Coordinator. With Wi-Fi ON/OFF at low-duty cycle, some messages from the yellow node are periodically blocked, but Zigbee retry mechanisms are effective in getting the messages to the Coordinator.

With Wi-Fi ON/OFF at high-duty cycle, many messages from the yellow node are blocked and Zigbee retry mechanisms may be exhausted. If Wi-Fi ON/OFF stays at high-duty cycle for enough time, the network responds by restructuring the yellow node to route messages to the Coordinator via the Router. However, this route rediscover takes time and messages may be lost. If Wi-Fi ON/OFF remains high-duty cycle, the yellow node messages will continue to go through the Router, which forwards messages to the Coordinator.

However, when Wi-Fi ON/OFF returns to low-duty cycle, the network will, due to lower route cost, return to the original structure with the yellow node sending messages directly to the Coordinator.

Under conditions with Wi-Fi ON/OFF switching between low and high duty cycles, the network may switch back and forth between these two route states. During these switching events, messages from the yellow end-node to the Coordinator are lost.

##### Unmanaged Coexistence

The unmanaged coexistence recommendations that follow provide guidance on how to maximize the EFR32MGxx/EFR32BGxx message success with strong nearby Wi-Fi.

###### Implement Frequency Separation

You can minimize the blocking effect of high-power Wi-Fi on other 2.4 GHz radios by moving the Wi-Fi to one end of the pass band. This impacts fewer Bluetooth channels and allows 802.15.4 channels to move to the other end of the pass band where Wi-Fi will have minimal blocking effect.

###### Bluetooth (heading level 7)

Bluetooth co-channel operation with Wi-Fi has the most impact on Bluetooth communication. For Bluetooth devices (point-to-point) and Bluetooth mesh devices using Generic Attribute Profile (GATT) bearer communication, at least one ADV channel is minimally blocked and supports establishing a connection via Advertising, Scanning, and Initiating link-layer states. While establishing a connection, the Bluetooth connection master specifies the channel map, but the connection master can also update the channel map during connection. However, the Bluetooth connection slave must follow the channel map provided by master.

If EFR32 becomes the connection master, the Bluetooth channel map can be specified via:

`sl_status_t sl_bt_gap_set_data_channel_classification (uint8 channel_map_len, const uint8\* channel_map_data)`

This command can be used to specify a channel classification for data channels. This classification persists until overwritten with a subsequent command or until the system is reset.

`channel_map` is 5 bytes and contains 37 1-bit fields. The _n_th such field (in the range 0 to 36) contains the value for the link layer channel index _n_:

0: Channel _n_ is bad.

1: Channel _n_ is unknown.

The most significant bits are reserved and shall be set to 0 for future use. At least two channels shall be marked as unknown.

For Bluetooth mesh devices using Advertising bearer communication, at least one ADV channel is minimally blocked and supports establishing communication via Advertising and Scanning.

###### 802.15.4 (heading level 7)

From the observations in [802.15.4](./02-wi-fi-impact-on-bluetooth-and-802-15-4-radios#802154) co-channel operation of 802.15.4 with 100% duty cycle Wi-Fi blocks most of the 802.15.4 messages and must be avoided. Also, EFR32MGxx tolerates up to 20 dB stronger Wi-Fi signal in “far-away” channel case than in adjacent channel case. The 802.15.4 network performance is improved by maximizing the frequency separation between the Wi-Fi network and the 802.15.4 network.

If the Wi-Fi and 802.15.4 radios are implemented with a common host (MCU controlling both radios), then the host should attempt to maximize the frequency separation. For Wi-Fi networks, the Access Point (AP) establishes the initial channel and, in auto channel configuration, is free to move the network to another channel using the Channel Switch Announcement (CSA), introduced in 802.11h, to schedule the channel change.

For OpenThread networks, frequency separation implementation depends on the application layer. For Zigbee networks, the Coordinator establishes the initial channel.

###### Operate Wi-Fi with 20 MHz Bandwidth

Because Wi-Fi 802.11n uses OFDM (Orthogonal Frequency-Division Multiplexing) sub-carriers, third-order distortion products from these sub-carriers extend one bandwidth on each side of the Wi-Fi channel. 802.11n can operate in 20 MHz or 40 MHz modes. If operated in 40 MHz mode, 40 MHz of the 80 MHz ISM band is consumed by the Wi-Fi channel. However, an additional 40 MHz on each side can be affected by third-order distortion products. These third-order products can block the Bluetooth and 802.15.4 receiver and is the primary reason adjacent channel performance is up to 20 dB worse than “far-away” channel performance.

In proposing 40 MHz mode for 802.11n, the Wi-Fi standard anticipated potential issues with other 2.4 GHz ISM devices when Wi-Fi operated in 40 MHz mode. During association, any Wi-Fi station can set the **Forty MHz Intolerant** bit in the HT Capabilities Information. This bit informs the Wi-Fi access point that other 2.4 GHz ISM devices are present, forcing the entire Wi-Fi network to 20 MHz mode.

###### Bluetooth (heading level 7)

If the Wi-Fi and Bluetooth radios are implemented with a common host, then the host should have the Wi-Fi radio set the 40 MHz Intolerant bit during association to force the Wi-Fi to 20 MHz mode, increasing the number of channels available to Bluetooth and improving the Bluetooth performance.

If the application requires Wi-Fi to operate in 40 MHz mode, frequency separation can be maximized by placing Wi-Fi channel at upper or lower end of 2.4 MHz ISM band, minimizing the adjacent channels.

###### 802.15.4 (heading level 7)

If the Wi-Fi and 802.15.4 radios are implemented with a common host, then the host should have the Wi-Fi radio set the Forty MHz Intolerant bit during association to force the Wi-Fi to 20 MHz mode, improving the 802.15.4 performance.

If the application requires Wi-Fi to operate in 40 MHz mode, frequency separation must be maximized by placing Wi-Fi channels and 802.15.4 channel at opposite ends of the 2.4 GHz ISM band.

From Silicon Labs’ managed coexistence testing, 802.15.4 performance with 40 MHz Wi-Fi, for the same Wi-Fi RF duty cycle, is comparable to 802.15.4 performance with 20 MHz Wi-Fi. While 802.15.4 performance with 100% Wi-Fi RF duty cycle is inherently impaired, 40 MHz Wi-Fi, for the same target Wi-Fi data rate, has a lower RF duty cycle than 20 MHz Wi-Fi, providing the 802.15.4 radio more frequent and longer time gaps for successful transmits and receives.

###### Increase Antenna Isolation

From the observations in [Wi-Fi Impact on Bluetooth and 802.15.4 Radios](./02-wi-fi-impact-on-bluetooth-and-802-15-4-radios), minimizing the Wi-Fi energy seen by the EFR32 RF input improves the EFR32 receive range. For example, in the “far-away” channel case for Zigbee (Wi-Fi channel 1 and Zigbee channel 25) with 100% Wi-Fi duty cycle, a -96 dBm 802.15.4 message can be received when the average Wi-Fi energy at EFR32MGxx input is -30 dBm or less. If the Wi-Fi average transmit power level is +10 dBm, 40 dB or more antenna isolation between the Wi-Fi transmitter and 802.15.4 RF input is required to always receive a -96 dBm 802.15.4 signal, Wi-Fi ON or OFF.

Increased antenna isolation can be achieved by:

- Increasing the distance between antennas. In open-space, far-field, power received is proportional to 1/R2, where R is the distance between antennas.
- Taking advantage of antenna directionality. A monopole antenna provides a null along the axis of the antenna, which can be directed toward the Wi-Fi antenna(s).

###### Implement Protocol and Stack Retry Mechanisms

You can maximize the use of built-in protocol MAC and stack retry mechanisms to minimize missed messages in the presence of high-power Wi-Fi.

###### Bluetooth (heading level 7)

Bluetooth (point-to-point) messages requires responses. If a response is not received within programmable time, the application can re-send the message up to a programmable limit.

Bluetooth mesh (mesh network) messages are sent via ADV payloads and responses are received during SCAN. Bluetooth mesh specifies:

- Optional relay nodes, which after a programmable time-out with no responses, can retransmit the original message for a programmable number of hops.
- Originator, after a programmable time-out with no response, can retransmit the original message for a programmable number of time-outs.

Both mechanisms improve Bluetooth mesh message success but should be used with caution. More relays nodes, shorter time-outs, and more retries may improve an individual message’s success, but these mechanisms can stress the mesh network by flooding too many identical messages. See [Bluetooth Mesh Network Performance](https://docs.silabs.com/btmesh/latest/btmesh-11-network-performance/) for details on these considerations.

###### 802.15.4 (heading level 7)

The 802.15.4 specification requires retries at the MAC (Media Access Control) layer, which are implemented in Silicon Labs’ EmberZNet PRO stack. To further improve message delivery robustness, Silicon Labs EmberZNet PRO stacks also implements NWK (Zigbee net-work layer) retries, wrapping the MAC retries. The user application can also take advantage of APS (Zigbee Application Support (APS) Sub-Layer) retries, wrapping the NWK retries. More information on the retry mechanisms can be found at:

- [Zigbee Fundamentals](https://docs.silabs.com/zigbee/latest/zigbee-fundamentals/)
- [How does the EmberZNet stack retry work?](https://www.silabs.com/community/wireless/zigbee-and-thread/knowledge-base.entry.html/2012/06/29/how_does_the_emberzn-po1M)

These retry mechanisms are effective at improving message delivery. However, under high interference conditions, message latency increases.

For OpenThread networks, 802.15.4 retries at the MAC layer still apply. However, other message and retry mechanisms depend on the application layer.

###### Remove FEM (or Operate FEM LNA in Bypass)

EFR32xGxx can deliver nearly +20 dBm transmit power and has excellent receiver sensitivity without an external FEM (Front End Module). However, an external FEM can increase transmit power to +20 dBm for increased range (in regions where this is permitted, for example, the Americas). The additional FEM LNA receive gain also improves sensitivity. However, this additional gain also degrades the EFR32xGx linearity performance in the presence of strong Wi-Fi.

For best receive sensitivity in the presence of strong Wi-Fi blockers, either eliminate the FEM or operate the FEM LNA in bypass mode. This recommendation is a trade-off as receive sensitivity without Wi-Fi blockers is improved with FEM LNA gain enabled.

##### Managed Coexistence

The market trends of higher Wi-Fi transmit power, higher Wi-Fi throughput, and integration of Wi-Fi and Bluetooth radios into the same device has the following impacts:

- Advantages:  
  - Host can implement frequency separation between Wi-Fi, Bluetooth, 802.15.4.  
  - Co-located Wi-Fi radio can force Wi-Fi network to operate with 20 MHz bandwidth.  
  - Co-located Wi-Fi, Bluetooth, and 802.15.4 radios can communicate pending and/or in-progress activity on 2.4 GHz ISM transmits and receives.
- Disadvantages:  
  - Higher Wi-Fi transmit power requires greater antenna isolation.  
  - Higher Wi-Fi throughput results in higher Wi-Fi duty cycle.  
  - Antenna isolation is usually limited by the size of the product (only 15-20 dB isolation is not unusual).

Assuming frequency separation achieves the “far-away” channel case and Wi-Fi only uses 20 MHz bandwidth, a +20 dBm Wi-Fi transmit power level at 100% duty cycle requires 50 dB antenna isolation to receive -92 dBm Bluetooth or 45 dB antenna isolation to receive -80 dBm 802.15.4 messages. This is generally not achievable in small devices with co-located Wi-Fi and Bluetooth or 802.15.4.

Managed Coexistence takes advantage of communication between the co-located Wi-Fi, Bluetooth, and 802.15.4 radios to coordinate each radio’s access to the 2.4 GHz ISM band for transmit and receive. For the EFR32, Silicon Labs has implemented a coordination scheme compatible with Wi-Fi devices supporting PTA. This PTA-based coordination allows the EFR32 to signal the Wi-Fi device when receiving a message or wanting to transmit a message. When the Wi-Fi device is made aware of the EFR32 requiring the 2.4 GHz ISM band, any Wi-Fi transmit can be delayed, improving Bluetooth or 802.15.4 message reliability.

> **Note**: EFR32 Bluetooth and Bluetooth Mesh coexistence is supported in Bluetooth 2.13.x and Bluetooth Mesh 2.10.x. Not all coexistence support features in Bluetooth 2.13.x and Bluetooth Mesh 2.10.x are present in earlier versions.

###### PTA Support Options

PTA is described in IEEE 802.15.2 (2003) Clause 6 and is a recommendation, not a standard. 802.15.2 originally addressed coexistence between 802.11b (Wi-Fi) and 802.15.1 (Bluetooth Classic) and does not describe an exact hardware configuration. However, 802.15.2 recommends that the PTA implementation consider the following:

- TX REQUEST from 802.11b to PTA and TX REQUEST from 802.15.1 to PTA
- TX CONFIRM from PTA to 802.11b and TX CONFIRM from PTA to 802.15.1
- STATUS information from both radios:  
  - Radio state [TX, RX, or idle]  
  - Current and future TX/RX frequencies  
  - Future expectation of a TX/RX start and duration  
  - Packet type  
  - Priority (Fixed, Randomized, or QoS based)

The following figure describes how 802.15.2 considers radio state, transmit/receive, and frequencies.

![IEEE 802.15.2 2.4 GHz ISM Co-Located Radio Interference Possibilities](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image17.png)

From the figure above, the frequency separation recommendations from section [Unmanaged Coexistence](./03-unmanaged-coexistence) remain required for managed coexistence:

- 802.15.2 “In-Band” is equivalent to Co-Channel operation, which showed significant Wi-Fi impact on co-channel Bluetooth or 802.15.4.
- 802.15.2 “Out-of-Band” covers both Adjacent and “Far-Away” Channel operation, which showed ~20 dB improvement in “Far-Away” Channel vs. Adjacent Channel (802.15.4).

As such, for Managed Coexistence, Silicon Labs recommends continuing to apply the unmanaged coexistence recommendations in these sections:

- [Implement Frequency Separation](03-unmanaged-coexistence#implement-frequency-separation)
- [Operate Wi-Fi with 20 MHz Bandwidth](./03-unmanaged-coexistence#operate-wi-fi-with-20-mhz-bandwidth)
- [Increase Antenna Isolation](./03-unmanaged-coexistence#increase-antenna-isolation)
- [Implement Protocol and Stack Retry Mechanisms](./03-unmanaged-coexistence#implement-protocol-and-stack-retry-mechanisms)
- [Remove FEM (or Operate FEM LNA in Bypass)](./03-unmanaged-coexistence#remove-fem-or-operate-fem-lna-in-bypass)

In reviewing existing PTA implementations, Silicon Labs finds the PTA master implementation has been integrated into many Wi-Fi devices, but not all Wi-Fi devices support a PTA interface. Although describing typical PTA implementations is sometimes referred to in the industry as Wi-fi/Bluetooth, 802.15.4 can be used interchangeably with Bluetooth for [1-Wire PTA](#1-wire-pta), [2-Wire PTA](#2-wire-pta), [3-Wire PTA](#3-wire-pta), or [4-Wire PTA](#4-wire-pta) when applied to EFR32. The following figure shows the most common Wi-Fi/PTA implementations supporting Bluetooth.

![Typical Wi-Fi/Bluetooth PTA Implementations](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image18.jpg)

###### 1-Wire PTA (heading level 7)

In 1-Wire PTA, the Wi-Fi/PTA device asserts a GRANT signal when Wi-Fi is not busy transmitting or receiving. When GRANT is asserted, the Bluetooth radio is allowed to transmit or receive. This mode does not allow the external radio to request the 2.4 GHz ISM and is not recommended.

An alternate 1-Wire implementation is a REQUEST signal from Bluetooth to Wi-Fi/PTA, where Bluetooth asserts REQUEST whenever it needs the 2.4 GHz ISM band and expects Wi-Fi to always yield. This mode works very well for Bluetooth, but high priority Wi-Fi traffic can be compromised which impacts Wi-Fi performance.

###### 2-Wire PTA (heading level 7)

In 2-Wire, the REQUEST is added with the GRANT signal, allowing the Bluetooth radio to request the 2.4 GHz ISM band. The Wi-Fi/PTA device internally controls the prioritization between Bluetooth and Wi-Fi, and on a conflict, the PTA can choose to either GRANT Bluetooth or Wi-Fi.

###### 3-Wire PTA (heading level 7)

In 3-Wire, the PRIORITY signal is added, allowing the Bluetooth radio to signify a high- or low-priority message is either being received or transmitted. The Wi-Fi/PTA device compares this external priority request against the internal Wi-Fi priority, which may be high/low or high/mid/low and can choose to either GRANT Bluetooth or Wi-Fi.

PRIORITY can be implemented as static or directional (enhanced) priority.

- **Static**: PRIORITY is either high or low during REQUEST asserted for the transmit or receive operation.
- **Directional**: PRIORITY is either high or low for a typically 20µs duration after REQUEST asserted, but switches to low during receive operation and high during transmit operation.

For platforms, such as Wi-Fi data routers that can achieve high Wi-Fi duty cycles, as well as IoT hubs that stream Bluetooth classic audio, implementing PRIORITY is highly recommended as it provides the Wi-Fi/PTA device with insight on the EFR32 REQUEST. PRIORITY is also configurable, both at compile time and at runtime, to address various product optimization requirements. However, PRIORITY may not be necessary for platforms that do not experience high Wi-Fi duty cycles nor support Bluetooth audio streaming, freeing a GPIO pin on the EFR32 and SoC. Low RF duty cycle protocols such as 802.15.4 are even more likely to not require PRIORITY in these conditions.

###### 4-Wire PTA (heading level 7)

In 4-Wire PTA, the FREQ signal is added, allowing the Bluetooth radio to signify an “in-band” or “out-of-band” message is either being received or transmitted. Silicon Labs recommends maximizing frequency separation, making the FREQ signal mute. For this reason, Silicon Labs’ EFR32 does not support the FREQ signal and, for any 4-wire Wi-Fi/PTA with a FREQ input, Silicon Labs therefore recommends asserting the FREQ input to the Wi-Fi/PTA.

Additional details about the implementation of managed coexistence and test results are available in an expanded version of this application note, _AN1243: Timing and Test Data for EFR32 Coexistence with Wi-Fi_, available under non-disclosure from Silicon Labs Sales.

###### Multiple EFR32s Connected to Wi-Fi/PTA (heading level 7)

The 802.15.2 recommendation only addresses a single 802.11b radio connected to a single 802.15.1 radio. However, market trends are requiring multiple co-located 2.4 GHz ISM radios to operate with a Wi-Fi/PTA device only designed for one external radio. Silicon Labs has addressed this requirement by enhancing the REQUEST signal with the “shared” REQUEST feature. For 802.15.4 radios only, the Silicon Labs EFR32 PRIORITY can also be configured as “shared” to support additional multi-EFR32 radio configurations.

The “shared” REQUEST and “shared” PRIORITY features have the following characteristics:

- Operate REQUEST and PRIORITY in open-drain or open-source (an external 1 kΩ ±5% pull-up for open-drain or pull-down for open source is required).
- Before asserting REQUEST, test REQUEST to determine if another EFR32 has already asserted REQUEST.
- If not already asserted, assert REQUEST.
- If already asserted:  
  - Wait for REQUEST to de-assert.  
  - Delay random time (programmable).  
  - Re-test REQUEST.  
  - If not already asserted, assert REQUEST.  
  - If already asserted:    
    - Then another radio has secured REQUEST.    
    - Return to wait for REQUEST to de-assert.

With these enhanced REQUEST and PRIORITY features, multiple EFR32s implement a PTA interface, which to the Wi-Fi/PTA device appears to be a single external radio.

An example of three EFR32 radios using 2-Wire PTA interfaced to one Wi-Fi/PTA interface using 2-Wire PTA is shown in the following figure (REQUEST pull-up or pull-down not shown).

![Three EFR32s Supporting Single Wi-Fi 2-Wire PTA Interface](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image19.jpg)

With these enhanced REQUEST features and “shared” PRIORITY, an example of three EFR32 radios using 3-Wire PTA interfaced to one Wi-Fi/PTA interface using 3-Wire PTA is shown in the following figure (REQUEST and PRIORITY pull-ups or pull-downs not shown).

![Three EFR32s Supporting Single Wi-Fi/PTA 3-Wire PTA Interface](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image20.jpg)

###### Wi-Fi/PTA Considerations

From Silicon Labs’ testing, Wi-Fi/PTA implementations vary. Best results are attained when the Wi-Fi/PTA implementation has the following characteristics.

###### Wi-Fi/PTA Supports Wi-Fi TX Preemption (heading level 7)

Wi-Fi RF duty cycle varies based on the Modulation and Coding Scheme (MCS) index, guard interval, bandwidth, and target data rate. Wi-Fi signal strength and SNR vary with distance and objects/walls between AP and STA, particularly with mobile Wi-Fi devices. When Wi-Fi signal strength and SNR drop, the MCS index is lowered to modulations able to operate at the lower SNR. However, lowering the MSC index also lowers the maximum data rate, and the Wi-Fi RF duty cycle increases as the AP and STA attempt to maintain the target data rate.

After REQUEST asserted, Wi-Fi/PTA devices not supporting Wi-Fi TX preemption delay GRANT to EFR32 until the end of the in-progress packet. At MCS0 with 20MHz bandwidth and large aggregated Wi-Fi packets, this delay can be as long as 16ms. This delay is much longer than the typical REQUEST_WINDOW (Bluetooth) or ~200µs REQUEST to end of CCA, and much longer than the maximum received 802.15.4 packet. (802.15.4). As such, the lack of Wi-Fi TX preemption during high Wi-Fi RF duty cycle increases retries, increases end-node battery consumption, and increases message loss.

After REQUEST asserted, Wi-Fi/PTA devices supporting TX preemption stop the Wi-Fi transmit, ramp down the Wi-Fi PA (within-gate delays up to tens of µs), and quickly GRANT the 2.4GHz band to the radio. The short the time from REQUEST to quiet Wi-Fi and GRANT improves message success on first attempt, which decreases retries, decreases end-node battery consumption, and decreases message loss.

Wi-Fi TX preemption impacts Wi-Fi performance as in-progress Wi-Fi TX packets are aborted and corrupted. In response to a corrupted packet, most Wi-Fi devices assume SNR or interferer and temporarily lower the MCS index to maintain connection but recover to optimum MSC index as subsequent messages are successful. However, Bluetooth and 802.15.4 networks are low duty cycle and the infrequent Wi-Fi TX preemption events have a low impact on Wi-Fi performance.

###### Wi-Fi/PTA Prevents Wi-Fi Transmit when GRANT Asserted (heading level 7)

Some Wi-Fi/PTA devices have been optimized to work with classic Bluetooth devices and have also been optimized to continue Wi-Fi TX events for a short time after asserting GRANT. This works only for that particular Wi-Fi/PTA and classic Bluetooth combination, as the minimum time from REQUEST asserted to Bluetooth TX start was used to determine how long Wi-Fi TX can continue after GRANT asserted. For EFR32 Bluetooth receives, the Wi-Fi/PTA device must stop all Wi-Fi TX when GRANT asserted and/or the EFR32 REQUEST_WINDOW must be increased to equal or exceed the Wi-Fi/PTA continued TX event.

Some Wi-Fi/PTA devices also attempt Wi-Fi TX based on the FREQ feature described in the 4-Wire PTA. If the FREQ feature is set by GPIO pin (or Wi-Fi/PTA internal register) to different frequencies, Wi-Fi/PTA will assert GRANT, but continue to Wi-Fi transmit. Given co-located Wi-Fi and Bluetooth radios with insufficient antenna isolation, the FREQ feature must be set to always blocking, FREQ GPIO pin (or Wi-Fi/PTA internal register) held asserted.

###### Wi-Fi/PTA and Application Implements Reasonable Prioritization (heading level 7)

Wi-Fi TX preemption impacts Wi-Fi performance as in-progress Wi-Fi TX packets are aborted and corrupted. In response to a corrupted packet, most Wi-Fi devices assume SNR or interferer and temporarily lower the MCS index to maintain connection but recover to optimum MSC index as subsequent messages are successful. However, Bluetooth and 802.15.4 networks are low duty cycle and the infrequent Wi-Fi TX preemption events have a low impact on Wi-Fi performance.

###### Bluetooth (heading level 8)

The Bluetooth connection interval and window are fixed. If co-located Bluetooth misses too many connection intervals, the connection is dropped and must be re-established. Frequent drops are unacceptable to end-users. Silicon Labs has implemented priority levels and priority escalation within EFR32. When EFR32 Bluetooth asserts high PRIORITY, the Wi-Fi/PTA devices should GRANT to EFR32, except for only highest priority Wi-Fi traffic.

###### 802.15.4 (heading level 8)

802.15.4 RX packets are asynchronous and missing a packet ensures retries, increased message latency, and decreased end-node battery life. As such, 802.15.4 RX priority should be set as high as possible for the application.

802.15.4 TX packets, originating from the co-located Wi-Fi/802.15.4 may have more discretion, as these devices are typically wall powered. However, 802.15.4 transmits showing high latency can result in an unsatisfactory user experience. As such, 802.15.4 TX should also be set as high as possible for the application.

###### Wi-Fi/PTA Implements Aggregation (heading level 7)

Ensure aggregation is enabled on the Wi-Fi/PTA device. During suitable conditions, aggregation combines multiple smaller packets into fewer larger packets, reducing total packet overhead. As such, aggregation aids Wi-Fi, Bluetooth, and 802.15.4 performance as Wi-Fi TX idle periods combine into larger idle periods for freer RF airtime and improved 802.15.4 PREAMBLE/SYNCH and Bluetooth mesh reception.

###### Wi-Fi/PTA Supports Directional PRIORITY (heading level 7)

Directional PRIORITY is a common feature that can be enabled on Wi-Fi/PTA devices and is recommended due to the additional radio state information provided by the Bluetooth radio which allows the possibility for concurrent Wi-Fi and Bluetooth reception when utilizing channel separation as well as concurrent Wi-Fi and Bluetooth transmission, also when utilizing channel separation. In this way, implementing Pulsed Directional PRIORITY maximizes Wi-Fi and Bluetooth throughput.

###### TX PRIORITY Escalation (802.15.4) (heading level 7)

To improve Wi-Fi performance with 802.15.4 coexistence, it is possible to start all 802.15.4 TX messages at low priority. However, to avoid blocking, all 802.15.4 TX messages during busy Wi-Fi, TX PRIORITY Escalation will escalate TX to high priority after a programmable number of CCA/GRANT or MAC failures. Then, after a successful TX message, de-escalate TX back to low priority.

###### PWM for High Duty Cycle Wi-Fi

PWM is a feature where the EFR32 reserves a timed slot for REQUEST. This is important in high duty-cycle Wi-Fi because planned EFR32 TX and RX, allows Wi-Fi to be more amenable to GRANT airtime when it is expected. Note that GRANT is not guaranteed; Wi-Fi still makes the decision based on its discretion.

###### Background (heading level 7)

The following figure is a 15.485ms capture of a Wi-Fi TX Active signal while Wi-Fi is transmitting iperf TCP at maximum throughput. Within this waveform, there are multiple Wi-Fi TX idle periods of which the first group of idle periods is expanded.

![High-Duty Cycle Wi-Fi TX Active](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image21.png)

From the first group, only the 0.306ms idle period is sufficient for packet receive (Bluetooth) or PREAMBLE/SYNCH detection (802.15.4) with a 0.146ms detection window (0.306ms–0.160ms). The following table lists all Wi-Fi TX idle period durations in the above 15.485ms capture.

|**Wi-Fi TX** **Idle (ms)**|**Detection Window** **(Idle–0.160ms)**|
|---|---|
|0.306|0.146|
|0.113|0.000|
|0.061|0.000|
|0.246|0.086|
|0.077|0.000|
|0.260|0.100|
|0.061|0.000|
|0.065|0.000|
|0.016|0.000|
|0.065|0.000|
|0.016|0.000|
|0.065|0.000|
|0.016|0.000|
|0.245|0.085|
|0.105|0.000|
|0.098|0.000|
|0.016|0.000|
|0.171|0.011|

The sum of all Wi-Fi TX Idle periods is 2.002ms. This Wi-Fi TX Activity indicates 87.1% duty cycle [(15.485–2.002) / 15.485 x 100%], but this calculation does not include the additional Wi-Fi RX activity.

The sum of all Detection Windows is 0.428ms, providing only 2.8% probability of receiving the packet [0.428 / 15.485 x 100%]. But again, this calculation does not include Wi-Fi RX Activity. With only 2.8% probability of packet reception and a target 1% or less BT Mesh message loss, 165 retries are required [CEILING(LOG(1%)/LOG(100%–2.8%)]. This large number of required retries is far beyond the Bluetooth mesh network retries and, even if retries are extended, the message latency becomes impractical. Large retries also quickly degrade lifetime for battery power end-nodes.

To resolve this issue, Bluetooth or 802.15.4 radios need more RF airtime to listen for incoming packets without being blocked by co-located Wi-Fi TX. Two options are possible:

- Co-located Wi-Fi device enforces a maximum allowed Wi-Fi TX RF duty cycle.
- Co-located Bluetooth or 802.15.4 radio asserts REQUEST at high PRIORITY to force regular quiet Wi-Fi TX.

Silicon Labs has not found option #1 to be reliable over various Wi-Fi/PTA devices. Silicon Labs has developed a PWM extension feature to support option #2. This PWM feature can be applied to any use case where EFR32 incoming Bluetooth Passive SCAN, Bluetooth mesh, or 802.15.4 packet receive is impaired by a co-located, controllable, external device. This includes, but is not limited to, the following use cases:

- High duty-cycle co-located Wi-Fi TX
- Bluetooth or 802.15.4 co-channel with Wi-Fi
- External T/R switch requiring Bluetooth or 802.15.4 to share a single antenna with Wi-Fi

###### Bluetooth (heading level 7)

100% Passive SCAN and Bluetooth mesh have no knowledge of when an incoming packet will arrive. As the co-located Wi-Fi TX RF duty cycle increases, the Wi-Fi TX idle periods become smaller and there are fewer idle periods allowing Passive SCAN or Bluetooth mesh receives. As such, the probability of a packet arriving during an acceptably large Wi-Fi TX idle period decreases significantly.

The PWM feature implements regular PTA REQUESTs to interrupt the high Wi-Fi RF duty cycle and ensure adequate windows for receives. However, this feature does degrade Wi-Fi performance. Additionally, the exact PWM period and duty cycle must be carefully selected to not alias PWM period with Wi-Fi beacons to avoid collapsing the Wi-Fi network.

> **Note**: Ensure aggregation is enabled on Wi-Fi/PTA device. During suitable conditions, aggregation combines multiple smaller packets into fewer larger packets which reduces the total packet overhead. As such, aggregation aids Passive SCAN and Bluetooth mesh ADV-Bearer packet detection as Wi-Fi TX idle periods combine into larger idle periods.

###### 802.15.4 (heading level 7)

802.15.4 radios have no knowledge of when an incoming packet will arrive and must capture the 802.15.4 PREAMBLE/SYNCH (160µs duration) to detect an incoming packet. As the co-located Wi-Fi TX RF duty cycle increases, the Wi-Fi TX idle periods become smaller and there are fewer idle periods exceeding 160µs. As such, the probability of a 160µs PREAMBLE/SYNCH arriving during an acceptably large Wi-Fi TX idle period decreases significantly.

The PWM feature implements regular PTA REQUESTs to interrupt the high Wi-Fi RF duty cycle and ensure adequate windows for PREAMBLE/SYNCH detection. However, this feature does degrade Wi-Fi performance. Additionally, the exact PWM period and duty cycle must be carefully selected to not alias PWM period with Wi-Fi beacons to avoid collapsing the Wi-Fi network.

> **Note**:  Ensure aggregation is enabled on Wi-Fi/PTA device. During suitable conditions, aggregation combines multiple smaller packets into fewer larger packets which reduces the total packet overhead. As such, aggregation aids 802.15.4 packet detection as Wi-Fi TX idle periods combine into larger idle periods for improved PREAMBLE/SYNCH detection.

###### PWM Feature Description (heading level 7)

The PWM feature does not require any additional GPIOs for single EFR32 designs. However, multi-EFR32 designs require an additional GPIO to be available for each EFR32.

###### Bluetooth (heading level 8)

The PWM feature is used to periodically stop co-located Wi-Fi TX activity to ensure sufficient idle TX time windows to receive Bluetooth packets during Passive SCAN and Bluetooth mesh ADV-Bearer receive.

The optimum PWM period and duty cycle can vary based on Bluetooth operation and Wi-Fi activity. If Wi-Fi activity is low, PWM could be disabled and fall back to normal PTA activity as described in [PWM for High Duty Cycle Wi-Fi](#pwm-for-high-duty-cycle-wi-fi). During very high Wi-Fi duty cycle for Bluetooth mesh ADC-Bearer, a PWM programmed to 39ms period and >44% duty is effective in reducing message loss to less than 1%. As noted, Wi-Fi throughput is impacted and, under 39ms/>44% condition, the high duty cycle Wi-Fi TX throughput noted above dropped ~50%.

###### 802.15.4 (heading level 8)

Under the same Wi-Fi TX Active throughput conditions as in section [Background](#background), the following figure shows the REQUEST||PWM (shown as REQUEST||TIMER1) signal interrupting the Wi-Fi TX with a 19.5 ms period and 20% duty cycle, sufficient to allow 802.15.4 RX with < 1% message loss.

![EFR32 RX Success with PWM during High-Duty Cycle Wi-Fi TX](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image22.jpg)

The green arrows show cases where the PREAMBLE/SYNCH was detected during a high PWM cycle, driving REQUEST||PWM high. This high PWM cycle stopped Wi-Fi TX Activity to allow detection of incoming 802.15.4 PRERAMBLE/SYNCH. As also seen, the REQUEST||PWM cycle is longer than all other cycles due to assertion of normal PTA REQUEST signal OR’ed with PWM cycle.

The red boxes are cases where the remote 802.15.4 radio executed packet transmits that were not detectable due to Wi-Fi TX Activity and packets’ PREAMBLE/SYNCH not aligning with the PWM cycle.

Optimum PWM period and duty cycle can vary based on 802.15.4 operation and Wi-Fi activity. If Wi-Fi activity is low, PWM could be disabled and fall back to normal PTA activity as described earlier. During very high Wi-Fi duty cycle for unicast 802.15.4 traffic, a PWM programmed to 19.5 ms period and 20% duty is effective in reducing message loss to less than 1% with APS retries disabled. As noted, Wi-Fi throughput is impacted and, under 19.5 ms/20% condition, the high duty cycle Wi-Fi TX throughput noted above dropped ~20% (~270 Mbps without PWM to ~220 Mbps with PWM).

During very high Wi-Fi duty cycle for broadcast 802.15.4 traffic without ACKs (for example, as occurs during network join sequence), a higher PWM duty cycle is required (e.g., 19.5 ms period and 80% duty cycle). This higher duty cycle can be disruptive to Wi-Fi but is only needed during expected broadcast message activity. This higher duty cycle can be reduced as soon as broadcast activity (for example, device join) completes.

###### PWM Implementation (heading level 7)

The optimum PWM implementation varies with single-EFR32 vs. multi-EFR32 applications. This implementation difference is primarily due to the REQUEST sharing feature used in multi-EFR32 applications. However, if addressed during circuit board design, this difference is easily resolved.

###### Bluetooth (heading level 8)

Use of an BGAPI or CLI command are needed to allow the host application to control the PWM period, duty cycle, and priority. For more information, see [Bluetooth Low Energy Coexistence with Wi-Fi](https://docs.silabs.com/bluetooth/latest/bluetooth-coexistence-with-wifi/).

###### 802.15.4 (heading level 8)

Use of an API or coexistence CLI command are needed to allow the host application to control the PWM period, duty cycle, and priority. For more information, see [Zigbee and OpenThread Coexistence with Wi-Fi](https://docs.silabs.com/multiprotocol/latest/zigbee-openthread-coexistence-wifi/).

###### Multi-EFR32 Radio with PWM (heading level 8)

For multi-EFR32 radio applications not implementing PWM, the Shared REQUEST signal is used to arbitrate which EFR32 radio has access to the 2.4 GHz ISM band when GRANT is asserted from the Wi-Fi/PTA. If the PWM signal were to be applied to the shared REQUEST pin, other EFR32 radios would interpret the REQUEST as busy when it might just be forcing Wi-Fi TX idle to allow any of the IoT radios to detect an incoming packet. Instead, the Shared REQUEST feature is accommodated by separating the Shared REQUEST signal from the REQUEST||PWM signal resulting in a separate non-Wi-Fi/PTA signal connection between the EFR32 devices for Shared REQUEST.

The PWM enabled Wi-Fi/PTA connections between the Wi-Fi and Zigbee, OpenThread, and BLE EFR32 radios are the same as the multi-EFR32 radio with typical 3-Wire PTA schema. Only one radio, selected at run time, controls the PWM and ORs the PWM signal in software with its own REQUEST (arbitrated by the Shared REQUEST signal). The other EFR32 radios must also implement PWM in Hardware Configurator to provide their REQUEST to the PTA interface, (also arbitrated by Shared REQUEST). Each EFR32 radio’s REQUEST||PWM GPIO is set to open-drain/open-source, allowing a hardware OR function of any EFR32 radio’s REQUEST with REQUEST||PWM.

If the radio driving REQUEST||PWM needs to go off-line (for example, for a firmware update), its PWM outputs can be halted and another EFR32 radio’s PWM outputs can then be activated for continued PWM operation. In the following figure (REQUEST and PRIORITY pull-ups and pull-downs not shown), the Zigbee radio implements the PWM feature and the Thread radio or the Bluetooth radio provide PWM backup.

![Three EFR32s Supporting PWM and Wi-Fi/PTA with Single 3-Wire PTA Interface](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image23.jpg)

###### Signal Identifier (EFR32xG24)

While the PWM feature improves the radio performance during high duty cycle Wi-Fi TX, it places a cap on the Wi-Fi throughput which is an important aspect in Wi-Fi gateway designs. As an alternative to using the PWM feature that interrupts the Wi-Fi duty cycle periodically to provide Wi-Fi quiet windows for 802.15.4/Bluetooth signal reception, the signal identifier feature in EFR32xG24 devices uses a signal detector to detect IoT signals (802.15.4 and/or Bluetooth) during Wi-Fi’s required inter-frame spacing (IFS) and interrupts the Wi-Fi radio only when a signal is detected. Upon signal detection, PTA REQUEST is asserted to halt Wi-Fi TX and capture the expected retry signal.

###### 4.4.1  802.15.4 (heading level 7)

The standard 802.15.4 packet detection requires PREAMBLE/SYNC (160 us) to be aligned with Wi-Fi TX idle periods which yields low detection probability at high Wi-Fi duty cycle. The improved faster 802.15.4 detection available in EFR32xG24 requires >=34us of

802.15.4 signal at >=-90dBm to ensure signal detection before it can signal PTA to hold off Wi-Fi. Note that the 802.15.4 PREAMBLE/SYNCH alignment is still needed for successful 802.15.4 packet reception so while there would be at least one retry during high-duty cycle Wi-Fi this method increases the detection probability significantly and will greatly reduce end-node retries, latency and improve end-node battery-life.

The following figure illustrates the improved signal detection. When the 802.15.4 signal detector detects a signal during the Wi-Fi IFS, PTA REQUEST is asserted to halt Wi-Fi TX and allow the retransmitted packet to be received. REQUEST is de-asserted after the device

has successfully received the packet, confirmed by an ACK. If an 802.15.4 packet is not received within the programmable Receive Retry timeout, REQUEST is de-asserted allowing Wi-Fi operation to resume.

> **Note**: An additional GPIO input must be configured and driven by Wi-Fi TX Active signal (typical Wi-Fi TX FEM PAEN signal) to restart signal detection upon Wi-Fi TX de-assertion. For more information on configuring the 802.15.4 signal identifier, see [Zigbee and OpenThread Coexistence with Wi-Fi](https://docs.silabs.com/multiprotocol/latest/zigbee-openthread-coexistence-wifi/).

![802.15.4 Signal Identifier](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image24.png)

###### 4.4.2  Bluetooth (heading level 7)

As mentioned in the previous section, the EFR32xG24 chip family introduces the “Signal Identifier” feature. This configurable hardware feature allows the radio transceiver to take advantage of Wi-Fi Inter Frame Space (IFS) during high duty cycles. The improved faster Bluetooth Low Energy 1Mbps detection available in EFR32xG24 requires >= 41us of Bluetooth signal at >=-90dBm to ensure signal detection before it can signal PTA to hold off Wi-Fi.

If the signal identifier module triggers when the Bluetooth radio is scanning and Bluetooth PREAMBLE/SYNCH is not detected, then the radio quickly switches to next primary advertising channel in an effort to capture the ADV event repeated over all three primary advertising channels.

The current Bluetooth specification only allows Bluetooth Low Energy 1Mbps and Long Range PHYs on primary advertising channels and these are supported by the signal identifier. This feature is most useful on BT Mesh using ADV bearer method as all messages are sent over ADV channels at unknown arrival timing.

If a Bluetooth packet is received after switching ADV channels, the packet is processed, which may include multiple RX/TX events. When the ADV event is finished, the REQUEST signal is de-asserted, allowing Wi-Fi operation to resume. The time-out after switching is programmable and, if no packet is received within time-out, the REQUEST signal is de-asserted, allowing Wi-Fi operation to resume.

> **Note**: An additional GPIO input must be configured and driven by Wi-Fi TX Active signal (typical Wi-Fi TX FEM PAEN signal) to restart signal detection upon Wi-Fi TX de-assertion. For more information on configuring the Bluetooth signal identifier, see [Bluetooth Coexistence with Wi-Fi](https://docs.silabs.com/bluetooth/latest/bluetooth-coexistence-with-wifi/).

![Bluetooth Signal Identifier](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image25.png)

###### Directional PRIORITY

Directional PRIORITY provides radio state information on the same signal line as PRIORITY by a timed pulse indicating a priority transaction, followed by a radio state indicating to the Wi-Fi part that the EFR32 is transmitting or receiving. PRIORITY signal options must be configured for implementing Directional PRIORITY.

Directional PRIORITY requires the use of a Timer and either four PRS channels (EFR32xG2x) or five PRS channels (EFR32xG1x). When Directional PRIORITY is enabled, the designer will need to verify the Timer and PRS channels selected for Directional PRIORITY are not used by the protocol SDK stack, plugins or custom application code.

RACPAEN and REQUEST is either one PRS channel which inverts ORs in one operation (EFR32xG2x) or two separate PRS channels (EFR32xG1x).

###### Single-EFR32 PTA with Directional PRIORITY (heading level 7)

The following figures show the GPIO, Radio, and Timer signals for Single-EFR32 PTA with and without SDK PWM and with Directional PRIORITY.

![Single-EFR32 PTA with SDK PWM, with Directional PRIORITY](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image26.jpg)

![Single-EFR32 PTA without SDK PWM, with Directional PRIORITY](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image27.jpg)

###### Directional PRIORITY (heading level 8)

- EFR32 Directional Priority output.
- GPIO connects to Wi-Fi PTA.
- Requires active high Static PRIORITY and active high REQUEST

###### Static PRIORITY (heading level 8)

- EFR32 PTA output.
- Directional PRIORITY input.
- The active high PRIORITY is not assigned to a GPIO.
- Not connected to any external circuit.

###### REQUEST (heading level 8)

- EFR32 PTA output.
- Directional PRIORITY input.
- Compared in Pulse Width Timer.
- GPIO connects to Wi-Fi PTA.

###### GRANT (heading level 8)

- EFR32 PTA input.
- GPIO connects to Wi-Fi PTA.

###### RACPAEN (heading level 8)

- EFR32 radio transmit PA enable output.
- Directional PRIORITY input.

###### Pulse Width (heading level 8)

- EFR32 Timer compared with REQUEST GPIO.
- Directional PRIORITY input.

###### Multi-EFR32 PTA with Directional PRIORITY (heading level 7)

The following figure shows the GPIO, Radio, and Timer signals for Multi-EFR32 PTA with SDK PWM and Directional PRIORITY (1K 5% pull-ups and pull-downs not shown).

![Multi-EFR32 PTA with SDK PWM and Directional PRIORITY](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image28.jpg)

###### Shared REQUEST (heading level 8)

- EFR32 PTA input / output.
- GPIO connects to all EFR32s for PTA bus arbitration between EFR32s  
  - Configured as open source / drain.  
  - The active high Shared REQUEST is open-source and an external 1 kΩ ±5% pull-down is required.

###### Directional PRIORITY (heading level 8)

- EFR32 Directional Priority output
- GPIO Connects to Wi-Fi PTA and all EFR32s  
  - Configured as open source / drain.    
    - The active high Directional PRIORITY is open-source and an external 1 kΩ ±5% pull-down is required.

###### Static PRIORITY (heading level 8)

- EFR32 PTA output.
- Directional PRIORITY input.
- The active high PRIORITY is not assigned to a GPIO.
- Not connected to any external circuit.

###### PWM REQUEST (heading level 8)

- EFR32 PTA output.
- Directional PRIORITY input.
- GPIO Connects to Wi-Fi PTA and all EFR32s.  
  - Configured as open source / drain.    
    If active high, PWM REQUEST is open-source and an external 1 kΩ ±5% pull-down is required.  
  - Compared with Pulse Width in EFR32 Timer.

###### GRANT (heading level 8)

- EFR32 PTA input.
- GPIO connects to Wi-Fi PTA and all EFR32s.

###### RACPAEN (heading level 8)

- EFR32 Radio transmit PA enable output.
- Directional PRIORITY input.

###### Pulse Width (heading level 8)

- EFR32 Timer compared with PWM REQUEST GPIO.
- Directional PRIORITY input.

The following figure shows the PRS and Timer logic diagram for Directional PRIORITY for EFR32xG1x.

![EFR32xG1x Directional PRIORITY Logic Diagram](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image29.jpg)

The following figure shows the PRS and Timer logic diagram for Directional PRIORITY for EFR32xG2x.

![EFR32xG2x Directional PRIORITY Logic Diagram](/multiprotocol-wifi-coexistence-fundamentals/0.1/images/sld484-image30.jpg)

##### Conclusions

Co-located, strong Wi-Fi can have a substantial impact on Bluetooth and 802.15.4 performance. It can be improved by using the following unmanaged coexistence techniques:

1. [Implement Frequency Separation](./03-unmanaged-coexistence#implement-frequency-separation)
2. [Operate Wi-Fi with 20 MHz Bandwidth](./03-unmanaged-coexistence#operate-wi-fi-with-20-m-hz-bandwidth)
3. [Increase Antenna Isolation](./03-unmanaged-coexistence#increase-antenna-isolation)
4. [Implement Protocol and Stack Retry Mechanisms](./03-unmanaged-coexistence#implement-protocol-and-stack-retry-mechanisms)
5. [Remove FEM (or Operate FEM LNA in Bypass)](./03-unmanaged-coexistence#remove-fem-or-operate-fem-lna-in-bypass)

With market trends toward higher Wi-Fi TX power, higher Wi-Fi throughput, and integration of Wi-Fi, Bluetooth, and other radios, into the same device, unmanaged techniques alone may prove insufficient, so a managed coexistence solution is required. Even with a managed coexistence solution, all unmanaged coexistence recommendations are still necessary.

Silicon Labs recommends the following managed coexistence strategies:

- Wi-Fi/PTA devices providing 802.15.4-derived Packet Traffic Arbitration.
- Silicon Labs’ EFR32 PTA solution:  
  - Implement one to four GPIOs as a combination of REQUEST, GRANT, PRIORITY, and RHO (two additional GPIOs are required to implement the PWM with High-Duty Cycle Wi-Fi feature for multi-EFR32 configurations).  
  - Supports both single-EFR32 and multi-EFR32 configurations with single Wi-Fi/PTA interface.  
  - Silicon Labs’ coexistence library and coexistence-hal-config.h #define settings to configure EFR32 PTA support for available GPIO pins and for compatibility with the chosen Wi-Fi/PTA device.  
  - Silicon Labs’ API, supporting run-time PTA reconfiguration. For more information, see [Zigbee and OpenThread Coexistence with Wi-Fi](https://docs.silabs.com/multiprotocol/latest/zigbee-openthread-coexistence-wifi/) or [Bluetooth Coexistence with Wi-Fi](https://docs.silabs.com/bluetooth/latest/bluetooth-coexistence-with-wifi/).

###### Bluetooth

Wi-Fi/Bluetooth coexistence test results show substantial Bluetooth performance improvements when PTA is utilized:

- Connection stability  
  - Prevent user frustration with unstable product function as Wi-Fi throughput varies.
- Substantially reduced message failure with associated throughput improvement:  
  - Improves end-node battery life.  
  - Reduces message latency.  
  - Bluetooth remains operational, even during high Wi-Fi duty cycles.

###### 802.15.4

Wi-Fi/802.15.4 coexistence test results show substantial 802.15.4 performance improvements when PTA is utilized:

- Improved device join success:  
  - However, device join utilizes broadcast messages, which are not retried.  
  - If possible, device join success can be further improved by temporarily reducing Wi-Fi traffic during devices joining 802.15.4 network.
- Substantially reduced MAC retries:  
  - Reduces message latency.  
  - Improves end-node battery life.  
  - Frequency separation remains important, as best managed coexistence performance is for “far-away” channels.
- Substantially reduced message failure:  
  - 802.15.4 network remains operational, even during high Wi-Fi duty cycles.

#### Bluetooth Coexistence with Wi-Fi

##### Bluetooth Coexistence with Wi-Fi

> **Note: This section replaces _AN1128: Bluetooth Coexistence with Wi-Fi_. Further updates to this application note will be provided here**.

These pages describe methods to improve coexistence of 2.4 GHz IEEE 802.11b/g/n Wi-Fi and Bluetooth® radios. These techniques are applicable to the EFR32MGx family and EFR32BGx family. This application note assumes you have a basic understanding of how Wi-Fi coexistence is implemented on EFR32 devices. For more information, see [Wi-Fi Coexistence Fundamentals](https://docs.silabs.com/multiprotocol/latest/multiprotocol-wifi-coexistence-fundamentals/).

Additional details about the implementation of managed coexistence are included in [Wi-Fi Coexistence Fundamentals](https://docs.silabs.com/multiprotocol/latest/multiprotocol-wifi-coexistence-fundamentals/) and _AN1243: Timing and Test Data for EFR32 Coexistence with Wi-Fi_ (available under non-disclosure from Silicon Labs Sales).

- [PTA 3-Wire BLE Functional Overview](./02-pta-3-wire-ble-functional-overview) describes how to configure the Silicon Labs Packet Traffic Arbitration (PTA) for Bluetooth.
- [Support Software Setup](./03-pta-support-software-setup) describes how to configure the Silicon Labs Packet Traffic Arbitration (PTA) for Bluetooth.
- [Code Coexistence Extensions](./04-application-code-coexistence-extensions) describes how to use PRS for radio digital signal output.
- [Coexistence Backplane Evaluation Board (EVB)](./05-coexistence-backplane-evaluation-board-evb) explains how to order the EVB for evaluating the Silicon Labs EFR32 software coexistence solution.

**Notes**:

1. Not all coexistence support features are present in SDK versions earlier than Bluetooth 3.3.1.0 and Bluetooth Mesh 2.2.1.0. Users of Bluetooth SDK 2.13.7 or earlier and Bluetooth Mesh SDK 1.7.1 or earlier may see different features from those documented in this application note.
2. Throughput this application note “Bluetooth Low Energy” is referenced as “Bluetooth”.
3. This application note addresses Bluetooth coexistence applications using EFR32 devices as per Bluetooth Core Specification v5.0 Vol 6 “Low Energy Controller” (point-to-point) and as per Bluetooth Specification Mesh Profile v1.0 (mesh network). These two applications have different coexistence considerations and, where necessary, this application note differentiates using the following terms:  
   - “Bluetooth device” to reference Bluetooth Core Specification v5.3 Vol 6 “Low Energy Controller” (point-to-point) operation.  
   - “Bluetooth mesh device” or “Bluetooth mesh node” to reference Bluetooth Specification Mesh Profile v1.0 (mesh network) operation.

##### PTA 3-Wire BLE Functional Overview

This section describes in practice what is the expected behavior of Packet Traffic Arbitration when using the three signals REQUEST, GRANT, and PRIORITY which is the most used configuration. This section also clarifies the noticeable differences between single EFR32 and multiple EFR32 scenarios.

The 3 wire PTA solution consists of three signals between a PTA master, the Wi-Fi chip, and one or several EFR32 peripherals:

- REQUEST, used by the EFR(s) to signify a request to transmit or receive to the Wi-Fi chip.
- PRIORITY, used by the EFR(s) to ensure that higher priority transmission/reception is processed first.
- GRANT, used by the Wi-Fi chip to grant a time slot to one EFR to transmit/receive. Note that in the case of multiple EFRs, the Wi-Fi PTA master does not control which EFR(s) has transmit/receive medium access. This arbitration is done between EFRs based on the logical state of the REQUEST signal.

![single EFR32](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image1.png)

Alternatively, in case of high Wi-Fi traffic load, the REQUEST signal can be PWM-ed to increase the opportunities of access to transmit/receive medium in a timely manner.

![multiple EFR32](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image2.png)

When the PWM feature is enabled and in the case of multiple EFRs, a back-channel REQUEST signal is shared between all EFRs for arbitration of the access to the PWM|REQUEST signal between the EFRs and the Wi-Fi chip (PTA central).

As described in [Wi-Fi Coexistence Fundamentals](https://docs.silabs.com/multiprotocol/latest/multiprotocol-wifi-coexistence-fundamentals/), the REQUEST back-channel is then used to arbitrate which EFR can access the shared PWM|REQUEST signal between the EFRs and the Wi-Fi chip. For more detail on signal settings please refer to the following section.

##### PTA Support Software Setup

> **Note**: GPIO interrupt numbers are based on the GPIO pin numbers and not the port. This can cause conflicts if the same pin is selected for different ports—for example, PD15 will conflict with PB15. Silicon Labs recommends avoiding these conflicts. If the conflict exists in hardware, manual macros can be added with the assistance of Silicon Labs Support.

###### Standard Project Configuration

To enable PTA coexistence support, the following steps are required:

1. Create a Bluetooth or Bluetooth Mesh project in Simplicity Studio V5.
2. Select **RAIL Utility, Coexistence** and **RAIL Utility, Coexistence CLI**, and then click **Configure**.  
   ![RAIL Utility, Coexistence](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image3.png)
3. The polarity of the signals can be left unchanged. In the case of multiple EFR32s, the “shared mode” for each signal can be activated. For the common PTA 3 wire configuration, select the REQUEST, GRANT, and PRIORITY signals as shown.  
   ![BLE Only Configuration](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image4.png)
4. For each signal, select the corresponding GPIO:  
   ![SL_RAIL_UTIL_COEX_GNT](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image5.png)  
   ![SL_RAIL_UTIL_COEX_PRI](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image6.png)
5. Finally, for debug purposes, ensure that the PRS component is installed in your project.

###### PWM|REQUEST Project Configuration

In case high duty-cycle is required for high Wi-Fi throughput, the “PWM” feature offers a way for EFRs to pull up the REQUEST signal in a way that improves the probabilities to get a time slot granted from the PTA central device. For more details on the feature, refer to [Wi-Fi Coexistence Fundamentals](https://docs.silabs.com/multiprotocol/latest/multiprotocol-wifi-coexistence-fundamentals/).

![PWM Request](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image7.png)

In this particular case, the **SL_RAIL_UTIL_COEX_REQ** signal corresponds to the REQUEST back-channel. The **SL_RAIL_UTIL_COEX_PWM_REQ** corresponds to the PWM|REQ signal between the EFR(s) and the Wi-Fi chip.

![SL_RAIL_UTIL_COEX_PWM_REQ](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image8.png)

###### PTA Signals

This section clarifies the settings that are specific to each signal.

###### REQUEST Signal (heading level 7)

![REQUEST signal](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image9.png)

- BLE Only Request Configuration (Request Window)  
  REQUEST Window adjusts the lead time for REQUEST assertion before the first Bluetooth TX or RX operation and after the REQUEST is asserted. A TX operation will proceed if GRANT is asserted at the end of the REQUEST Window. An RX operation will attempt to proceed regardless of GRANT asserted or de-asserted as Bluetooth RX does not impact other co-located radios. This feature’s setting needs to at least exceed the maximum time for Wi-Fi/PTA to provide GRANT asserted or de-asserted after the REQUEST is asserted.
- REQUEST signal is shared  
  This helps the radio transceiver software to set the electrical status of the corresponding GPIO so it can be driven by other EFRs (open-drain). This should be disabled for single EFR operation.
- REQUEST signal max backoff mask  
  REQUEST signal max backoff determines the random REQUEST delay mask (only valid if REQUEST signal is shared). The random delay (in µs) is computed by masking the internal random variable against the entered mask. The mask should be set to a value of 2n-1 to ensure a continuous random delay range.

In case the PWM feature is used:

![PWM Request](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image7.png)

PWM asserts REQUEST and optionally PRIORITY at a regular period and duty-cycle. PWM can be employed to create idle Wi-Fi TX windows to improve 100% Passive SCAN performance and is essential for Bluetooth mesh using ADV-Bearer to allow sufficient idle Wi-Fi TX time windows. **PWM Request Period** and **PWM Request Duty-Cycle** indicates the period and duty-cycle at reset.

PWM period should not be an integer sub-multiple of Wi-Fi beacon (typically 102.4 ms). This is required to prevent Wi-Fi from losing many beacons and disassociating. Also, the lowest duty-cycle providing sufficient BT performance is recommended as higher PWM duty-cycles reduce RF time available to Wi-Fi with associated reduction in Wi-Fi throughput.

However, for Bluetooth mesh using the ADV-Bearer method, a period of 39 ms and duty-cycle greater than 44% may be required to receive 99% of ADV-bearer messages (exact PWM requirement depends on Bluetooth mesh retry settings). If possible, Bluetooth mesh should use the GATT-bearer method from the co-located Bluetooth mesh radio to relay node.

If **Assert priority when PWM REQUEST asserted** is enabled, then REQUEST is **Shared REQUEST** between multiple EFR32 radios and is used to arbitrate which EFR32 controls PTA interface to Wi-Fi. Operating PWM on **Shared REQUEST** is incompatible with arbitration.  As such, the PWM_REQUEST pin becomes necessary. Shared REQUEST interconnects all EFR32 radios for arbitration and PWM_REQUEST is connected to all EFR32 radios, but drives the REQUEST signal to Wi-Fi/PTA.

If **Assert priority when PWM REQUEST asserted** is disabled, then REQUEST is not shared and is used to drive all PTA requests to Wi-Fi, both from radio states requests and from PWM.

###### GRANT Signal (heading level 7)

![GRANT](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image10.png)

Many Wi-Fi/PTA devices use the term WLAN_DENY or BT_DENY and are considered active-high. These active-high deny signals correlate with EFR32 active-low GRANT.

In 1-wire PTA configurations based on REQUEST-only, GRANT is not implemented. If GRANT is not needed, you can disable the signal.

###### TX Abort (heading level 7)

![TX Abort](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image11.png)

If enabled, losing GRANT (or RHO asserted) during a Bluetooth TX will abort the Bluetooth TX. If not enabled, losing GRANT (or RHO asserted) after the start of a Bluetooth TX will not abort the Bluetooth TX. If disabled, transmission won’t be aborted when GRANT/RHO/REQUEST are de-asserted.

If enabled, transmission will be aborted when GRANT/RHO/REQUEST are de-asserted.

###### PRIORITY Signal (heading level 7)

![PRIORITY Signal](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image12.png)

> **Note**: In 1-Wire or 2-Wire PTA configurations, PRIORITY is not implemented. For single EFR operation, the shared mode for PRIORITY should be disabled

###### Radio Hold Off (heading level 7)

Radio hold-off (RHO) is effectively a second GRANT signal. However, when RHO is asserted, Bluetooth TX operations are blocked.

> **Note**: In most EFR32BG coexistence applications, RHO is not needed. If RHO is not needed this can be just disabled.

###### Directional Priority (heading level 7)

PRIORITY can be “static” where it is asserted or de-asserted for the entire TX/RX/… or RX/TX/… event. Directional PRIORITY can be used to provide priority information and radio state (TX or RX). The EFR32 implementation of Directional PRIORITY is accomplished using static PRIORITY, REQUEST (or PWM_REQUEST if multi-EFR32 using Shared REQUEST), a TIMER, and up to 6 PRS channels. Because on-chip hardware resources are used with this feature, it is very important to understand which are used and ensure no conflicts. Directional PRIORITY is only supported for PTA implementations where REQUEST (PWM_REQUEST) and PRIORITY are active high.

As illustrated in [PTA 3-Wire BLE Functional Overview](./02-pta-3-wire-ble-functional-overview), the Directional PRIORITY signal is a combination of other signals:

- Static PRIORITY signal.
- The REQUEST signal.
- Radio controller state “FEM” (Front End Module) signals. In particular, RACPAEN which is the signal corresponding to the Power Amplifier on the transmit path.
- A Hardware timer for Directional PRIORITY time pulses.
- Additional PRS channels needed for signal routing.

For more details on the mechanisms used to generate the Directional Priority signal, refer to [Wi-Fi Coexistence Fundamentals](https://docs.silabs.com/multiprotocol/latest/multiprotocol-wifi-coexistence-fundamentals/).

If enabled, Directional PRIORITY drives a programmable pulse-width (1µs to 255µs) to indicate the priority of TX/RX/… or the priority of RX/TX/… events.  Following pulse, Directional PRIORITY signal is low for radio in RX state and high for radio in TX state. The Wi-Fi/PTA device can monitor the Directional PRIORITY signals to understand the priority of the TX/RX/… or RX/TX/… event and the current radio state. In this manner, simultaneous TX/TX and RX/RX can be allowed and conflicting TX/RX and RX/TX events can be prioritized by PTA mechanism.

To enable Directional PRIORITY, start by turning on the feature in the **RAIL Utility, Coexistence** component.

![Directional PRIORITY](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image13.png)

When the component UI is modified, the corresponding coexistence configuration files under the config directory in your project are automatically modified to reflect your latest changes:

- sl_rail_util_coex_common_config.h
- sl_rail_util_coex_config.h

The first file (sl_rail_util_coex_common_config.h) contains macros that are software switches for each coexistence feature.

The second file (sl_rail_util_coex_config.h) defines the hardware Inputs/Outputs and PRS and Timer peripherals.

The PRIORITY signal is not assigned a GPIO and is set disabled. It has no physical connection to the Wi-Fi PTA and is used as Static PRIORITY input to the Directional PRIORITY logic block with the remaining PRIORITY signal configuration options.

> **Note**: Component UI for PRIORITY configuration fields are disabled and therefore not editable when Enable PRIORITY is set to true. A workaround is to assign any GPIO to PRIORITY signal, edit the PRIORITY configuration options, and then set PRIORITY signal to disabled. This is valid for SDKs prior to GSDK 4.1.1.

1. Enable REQUEST, GRANT and Directional PRIORITY (the PRIORITY signal should also be enabled).
2. Under the REQUEST signal set "Specify the number of microseconds between asserting Request and starting RX/TX" to 50 us for example.  
   ![BLE ONly Configuration](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image14.png)
3. Set the pin settings for SL_RAIL_UTIL_COEX_GNT, SL_RAIL_UTIL_COEX_REQ, and SL_RAIL_UTIL_COEX_DP_OUT.  
   ![SL_RAIL_UTIL_COEX_DP_OUT](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image15.png)  
   Note that, for series 1, the signal SL_RAIL_UTIL_COEX_DP_REQUEST_INV should also be set according to the wanted polarity.
4. In some earlier version of the GSDK (prior to 4.1.1), the timer settings aren’t present by default in the component definition. In this case it has to be added manually by copy pasting the following snippet of code in the file "config/sl_rail_coex_config.h" and add the timer macros. This gives the expected Hardware Timer settings in the **“RAIL Utility, Coexistence”** component UI:  
   ```c  
   // Directional Priority timer module  
   // <timer channel=CC0 optional=true> SL_RAIL_UTIL_COEX_DP_TIMER  
   // $[TIMER_SL_RAIL_UTIL_COEX_DP_TIMER]  
   #define SL_RAIL_UTIL_COEX_DP_TIMER_PERIPHERAL    TIMER1  
   #define SL_RAIL_UTIL_COEX_DP_TIMER_PERIPHERAL_NO 1  
   // [TIMER_SL_RAIL_UTIL_COEX_DP_TIMER]$  
   #ifndef SL_RAIL_UTIL_COEX_DP_TIMER_PERIPHERAL  
   #error "SL_RAIL_UTIL_COEX_DP_TIMER_PERIPHERAL undefined"  
   #endif //SL_RAIL_UTIL_COEX_DP_TIMER_PERIPHERAL  
   #endif //SL_RAIL_UTIL_COEX_DP_ENABLED  
     
   #endif // SL_RAIL_UTIL_COEX_CONFIG_H  
   ```  
   ![SL_RAIL_UTIL_COEX_DP_TIMER](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image16.png)

> **Note**: REQUEST will assert on valid BLE preamble/sync. REQUEST will also stay asserted through any follow-up TX/RX/... required for this RX packet.

As an extra, you can set the FEM and PTI pins so that the data being sent appear on the logic analyzer waveforms. To do so, in the **RAIL Utility, PTI** component, configure the desired signals as illustrated:

![RAIL Utility, PTI](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image17.png)

Install the FEM component **Radio Utility, FEM** (this section is optional – for debugging purposes):

![RAIL Utility, FEM](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image18.png)

1. In that component, in the **FEM Configuration** pane, toggle on **Enable RX Mode** and **Enable TX Mode**.  
   ![FEM Configuration](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image19.png)
2. Then after enabling the RX (Radio Controller LNA or RACLNA Enabled in short) and TX (Radio Controller PA signals or RACPA  Enabled used for DP generation), set the RX (RACLNAEN) and TX (RACPAEN) pins.  
   ![SL_FEM_UTIL_TX](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image20.png)  
   ![SL_FEM_UTIL_RX](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image21.png)

An example of signals waveform generated (BLE active scanning) by a project configured as above would look like the following on a logic analyzer:

![Logic analyzer output](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image22.png)

The above illustrates a BLE advertising packet being sent on the three primary channels. You can see the RACPAEN pull up during transmit and then RACLNAEN begin pulled up for a short while. The second advertising has an active scanning packet (RACPAEN being pulled after reception for a little while).

###### Wi-Fi TX (EFR32xG24 only) (heading level 7)

On the EFR32xG24 chip family, a hardware feature is available that allows the radio transceiver driver to take advantage of interframe spaces in high duty cycles. For this chip family, this can be an alternative to the PWM|REQUEST feature. When used, this enables a signal detector searching for waves characteristic of IoT devices (802.15.4 and BLE) during Wi-Fi transmission.

The following screenshots illustrate how the feature and the corresponding Wi-Fi TX GPIO can be configured:

![Coexistence signal identified configuration](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image23.png)

![SL_RAIL_UTIL_COEX_WIFI_TX](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image24.png)

For more information on how the feature works, refer to [Wi-Fi Coexistence Fundamentals](https://docs.silabs.com/multiprotocol/latest/multiprotocol-wifi-coexistence-fundamentals/).

###### PTA Code Reference for Older SDKs

This section is a reference for customers using older SDKs (prior to GSDK 3.0.0.0).

Add code to initialize and configure coexistence:

- Add include file to app.c:  
  `#include "coexistence-ble.h"`
- Add one of following variable definition to app.c:  
  `uint8 myCoexConfig[] = { 255, 255, 39, 20 }; // for duty-cycled SCAN and no BT Mesh ADV-Bearer`  
  or  
  `uint8 myCoexConfig[] = { 175, 175, 39, 20 }; // for 100% Passive SCAN or BT Mesh ADV-Bearer`  
  which is based on the following definition:  
  ```c  
   typedef struct{  
        uint8_t threshold_coex_pri; /** Priority line is toggled if priority is below this*/  
        uint8_t threshold_coex_req; /** Coex request is toggled if priority is below this*/  
        uint8_t coex_pwm_period;    /** PWM Period in ms, if 0 pwm is disabled*/  
        uint8_t coex_pwm_dutycycle; /** PWM dutycycle percentage, if 0 pwm is disabled, if >= 100  
                                          pwm line is always enabled*/  
      }sl_bt_ll_coex_config;  
    
      //Default coex configuration  
      #define SL_BT_COEX_DEFAULT_CONFIG { 175, 255, HAL_COEX_PWM_REQ_PERIOD, HAL_COEX_PWM_REQ_DUTYCYCLE  
  ```
- Add one of following variable definition to app.c:  
  ```c  
   // for duty-cycled SCAN and no BT Mesh ADV-Bearer and default link layer priorities  
   uint8 myLinkLayerPriorities[] = { 191, 143, 175, 127, 135, 0, 55, 15, 16, 16, 0, 4, 4 }  
  ```  
  or  
  ```c  
  // for duty-cycled SCAN and no BT Mesh ADV-Bearer  
  uint8 myLinkLayerPriorities[] = { 223, 175, 174, 127, 135, 0, 55, 15, 16, 16, 0, 4, 4 };  
  ```  
  which is based on following definition:  
  ```c  
  typedef struct {  
      uint8_t scan_min;  
      uint8_t scan_max;  
      uint8_t adv_min;  
      uint8_t adv_max;  
      uint8_t conn_min;  
      uint8_t conn_max;  
      uint8_t init_min;  
      uint8_t init_max;  
      uint8_t rail_mapping_offset;  
      uint8_t rail_mapping_range;  
      uint8_t afh_scan_interval;  
      uint8_t adv_step;  
      uint8_t scan_step;  
    
  }sl_bt_bluetooth_ll_priorities;  
  //Default priority configuration  
  #define SL_BT_BLUETOOTH_PRIORITIES_DEFAULT { 191, 143, 175, 127, 135, 0, 55, 15, 16, 16, 0, 4, 4 }  
  ```
- Enable or disable Passive SCAN.  
  `#define SCAN_PASSIVE                        (0)`  
  or  
  `#define SCAN_PASSIVE                        (1)`
- Add point to custom link layer table in config variable in sl_bluetooth.c (instead of the default stack definition SL_BT_CONFIG_DEFAULT):  
  ```c  
   static const sl_bt_configuration_t config = {  
   .config_flags = SL_BT_CONFIG_FLAGS,                                        \  
   .sleep.flags = SL_BT_SLEEP_FLAGS_DEEP_SLEEP_ENABLE,                        \  
   .bluetooth.max_connections = SL_BT_CONFIG_MAX_CONNECTIONS,                 \  
   .bluetooth.max_advertisers = SL_BT_CONFIG_MAX_ADVERTISERS,                 \  
   .bluetooth.max_periodic_sync = SL_BT_CONFIG_MAX_PERIODIC_ADVERTISING_SYNC, \  
   .bluetooth.mem_pool = sl_bt_default_mem_pool,                              \  
   .bluetooth.mem_pool_size = sizeof(sl_bt_default_mem_pool),                 \  
   .bluetooth.sleep_clock_accuracy = SL_BT_CONFIG_SLEEP_CLOCK_ACCURACY,       \  // use modified Link Layer Priorities  
   .bluetooth.linklayer_priorities = myLinkLayerPriorities, // default = NULL  
    
   .scheduler_callback = SL_BT_CONFIG_LL_CALLBACK,                            \  
   .stack_schedule_callback = SL_BT_CONFIG_STACK_CALLBACK,                    \  
   .gattdb = &bg_gattdb_data,                                                 \  
   .max_timers = SL_BT_CONFIG_MAX_SOFTWARE_TIMERS,                            \  
   .rf.tx_gain = SL_BT_CONFIG_RF_PATH_GAIN_TX,                                \  
   .rf.rx_gain = SL_BT_CONFIG_RF_PATH_GAIN_RX,};  
  ```
- Add the coexistence initialization function call and initialize threshold_coex_req and threshold_code_pri within main() in main.c.  
  ```c  
  …  
  // Initialize stack  
  sl_bt_init();  
    
  // Initialize coexistence  
  sl_bt_init_coex_hal();  
    
  // Initialize threshold_coex_req and threshold_code_pri  
  sl_bt_coex_set_parameters(myCoexConfig[0],myCoexConfig[1],myCoexConfig[2],myCoexConfig[3]);  
  ```

###### Run-Time PTA Re-configuration

The following PTA options can also be re-configured at runtime:

1. Disable/Enable the PTA feature  
   At runtime, the following code disables the PTA feature:  
   `sl_bt_coex_set_options(SL_COEX_OPTION_ENABLE,0);`  
   At runtime, the following code enables the PTA feature:  
   `sl_bt_coex_set_options(SL_BT_COEX_OPTION_ENABLE, 1);`
2. REQUEST Window  
   At runtime, the following code can be used to change the REQUEST_WINDOW:  
   ```c  
   sl_bt_coex_set_options(SL_BT_COEX_OPTION_REQUEST_WINDOW_MASK, desired_request_window << SL_BT_COEX_OPTION_REQUEST_WINDOW_SHIFT);  
   ```  
   Where `desired_request_window` is the REQUEST_WINDOW in µs.
3. Abort transmission mid packet if GRANT is lost.  
   At runtime, the following code disables Abort transmission mid packet if GRANT is lost:  
   `Csl_bt_coex_set_options(SL_BT_COEX_OPTION_TX_ABORT, 0);`  
   At runtime, the following code enables Abort transmission mid packet if GRANT is lost:  
   `sl_bt_coex_set_options(SL_BT_COEX_OPTION_TX_ABORT, 1);`
4. PRIORITY Escalation capability  
   At runtime, the following code disables PRIORITY assertion:  
   `sl_bt_coex_set_options(SL_BT_COEX_OPTION_HIGH_PRIORITY, 0);`  
   At runtime, the following code enables PRIORITY assertion:  
   `sl_bt_coex_set_options(SL_BT_COEX_OPTION_HIGH_PRIORITY, 1);`
5. Channel Map Masking  
   If an EFR32BG device enters CONNECTION state as a central device, it controls which of the 37 data channels are used during the AFH. As a CONNECTION central device, the EFR32BG can also update this channel map and communicate this update to a peripheral device. This feature can be used to make Bluetooth avoid being co-channel to Wi-Fi.  
   If EFR32 becomes the connection central device, the Bluetooth channel map can be specified using this function call:  
   ```c  
   sl_status sl_bt_gap_set_data_channel_classification(size_t channel_map_len, const uint8_t*  
   channel_map)  
   ```  
   This command can be used to specify a channel classification for data channels. This classification persists until overwritten with a subsequent command or until the system is reset.  
   `channel_map` is 5 bytes and contains 37 1-bit fields. The _n_th such field (in the range 0 to 36) contains the value for the link layer channel index _n_:  
   0: Channel _n_ is bad.  
   1: Channel _n_ is unknown.  
   The most significant bits are reserved and shall be set to 0 for future use. At least two channels shall be marked as unknown.  
   `threshold_coex_req, threshold_code_pri, pwm_period, and pwm_dutycycle`  
   It may be required during application execution to change the two coex thresholds and PWM period/duty-cycle. These settings can be changed at run time using this function call:  
   `sl_status sl_bt_coex_set_parameters(uint8_t priority, uint8_t request, uint8_t pwm_period, uint8_t pwm_dutycycle)`
6. Link Layer Priority Table  
   It may be required during application execution to change the link layer priority table. This table can be changed at run time using this functional call:  
   `sl_status_t sl_bt_system_linklayer_configure (uint8 key,uint8 data_len, const uint8* data)`  
   where `data` is an array containing:  
   ```c  
   typedef struct {  
     uint8_t scan_min;  
     uint8_t scan_max;  
     uint8_t adv_min;  
     uint8_t adv_max;  
     uint8_t conn_min;  
     uint8_t conn_max;  
     uint8_t init_min;  
     uint8_t init_max;  
     uint8_t rail_mapping_offset;  
     uint8_t rail_mapping_range;  
     uint8_t afh_scan_interval;  
     uint8_t adv_step;  
     uint8_t scan_step;  
   } sl_bt_bluetooth_ll_priorities;  
   ```

This full array is 17 bytes in length. However, if `data_len` is less than 17, only first `data_len` entries will be modified. For example, if `data_len=2`, only `scan_min` and `scan_max` are updated.

###### Run-Time PTA Debug Counters

At runtime, PTA Debug Counters are also available and can be accessed and reset via the following function:

```c
sl_status_t sl_bt_coex_get_counters(uint8_t reset,
                                    size_t max_counters_size,
                                    size_t \*counters_len,
                                    uint8_t \*counters);
```

where:

- `reset = 0` leaves counters unchanged
- `reset = 1` resets all counters to 0 (after reading current counter values)  
  where, since startup or last reset:  
  - `result` is success (== 0) or failure (!= 0) of `sl_bt_coex_get_counters()` command  
  - `max_counters_size` is the size of output buffer passed in pointer counters.  
  - `counters_len` is a pointer to the buffer length variable.  
  - `counters` is the counters buffer. Counters in the list are in following order: low priority requested, high priority requested, low priority denied, high priority denied, low-priority TX aborted, and high-priority TX aborted. Passing a non-zero value also resets counter.

###### Coexistence Configuration Setup Examples for Different Wi-Fi/PTA Applications

###### Example 1: Configure EFR32 PTA support to operate as single EFR32 with typical 3-Wire Wi-Fi/PTA (for Series 1) (heading level 7)

- Single EFR32 radio
- REQUEST unshared, active high, PC10  
  - Compatible 3-Wire Wi-Fi/PTA devices sometimes refer to this signal as RF_ACTIVE or BT_ACTIVE (active high)
- GRANT, active low, PF3  
  - Compatible 3-Wire Wi-Fi/PTA devices sometimes refer to this signal as WLAN_DENY (deny is active high, making grant active low)
- PRIORITY, active high, PD12  
  - Compatible 3-Wire Wi-Fi/PTA devices sometimes refer to this signal as RF_STATUS or BT_STATUS (active high)  
  - PRIORITY is static, not directional. If operated with a 3-Wire Wi-Fi/PTA expecting directional:    
    - Static high PRIORITY is interpreted as high PRIORITY and always in TX mode, regardless of actual TX or RX    
    - Static low PRIORITY is interpreted as low PRIORITY and always in RX mode, regardless of actual TX or RX
- REQUEST_WINDOW is 50 µs
- Disabled Abort transmission mid packet if GRANT is lost
- PRIORITY is always high
- RHO unused

The required #defines in `sl_rail_util_coex_config.h` and `sl_rail_util_coex_common_config.h` are:

```c
// $[COEX]
#ifndef SL_RAIL_UTIL_COEX_CONFIG_H
#define SL_RAIL_UTIL_COEX_CONFIG_H

#define SL_RAIL_UTIL_COEX_REQ_PIN                             (10U)
#define SL_RAIL_UTIL_COEX_REQ_PORT                            (gpioPortC)
#define SL_RAIL_UTIL_COEX_PWM_REQ_ASSERT_LEVEL                    (1)
#define SL_RAIL_UTIL_COEX_REQ_WINDOW                          (50U)
#define SL_RAIL_UTIL_COEX_REQ_SHARED                          (0)
#define SL_RAIL_UTIL_COEX_REQ_BACKOFF                         (15U)

#define SL_RAIL_UTIL_COEX_GNT_PIN                             (3U)
#define SL_RAIL_UTIL_COEX_GNT_PORT                            (gpioPortF)
#define SL_RAIL_UTIL_COEX_GNT_ASSERT_LEVEL                    (0)
#define SL_RAIL_UTIL_COEX_TX_ABORT                            (0)
#define SL_RAIL_UTIL_COEX_PRI_PIN                             (12U)
#define SL_RAIL_UTIL_COEX_PRI_PORT                            (gpioPortD)
#define SL_RAIL_UTIL_COEX_PRI_ASSERT_LEVEL                    (1)
#define SL_RAIL_UTIL_COEX_PRIORITY_DEFAULT                    (1)
#define SL_RAIL_UTIL_COEX_PRI_SHARED                          (0)

#define SL_RAIL_UTIL_COEX_PWM_DEFAULT_ENABLED                 (0)
#define SL_RAIL_UTIL_COEX_PWM_REQ_PERIOD                      (39U)
#define SL_RAIL_UTIL_COEX_PWM_REQ_DUTYCYCLE                   (20U)
#define SL_RAIL_UTIL_COEX_PWM_PRIORITY                        (0)

#define SL_RAIL_UTIL_COEX_DP_ENABLED                          (0)
// [COEX]$
```

The logic analyzer capture in the following figure shows the PTA interface, Wi-Fi TX state, and EFR32 radio state for an EFR32 radio configured for typical 3-Wire Wi-Fi/PTA during a CONNECTION event (peripheral):

![CONNECTION event (peripheral) for Single EFR32 typical 3-Wire Wi-Fi/PTA Logic Analyzer Capture](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image25.png)

where:

- **REQUEST**: active high, push-pull REQUEST output
- **nGRANT**: active low GRANT input
- **PRIORITY**: active high PRIORITY output
- **CoEx TX ACTIVE**: EFR32 TX Active control signal (configured via sample code in [Application Code Coexistence Extensions](./04-application-code-coexistence-extensions))
- **CoEx RX ACTIVE**: EFR32 RX Active control signal (configured via sample code in [Application Code Coexistence Extensions](./04-application-code-coexistence-extensions))
- **CoEx PTI FRAME**: EFR32 Frame Control Data Frame signal (packet trace frame/synch)
- **CoEx PTI DATA**: EFR32 Frame Control Data Out signal (packet trace data)
- **WiFi TX ACTIVE**: Wi-Fi TX Active signal

The logic analyzer sequence above shows:

1. Wi-Fi is transmitting and EFR32BG asserts REQUEST, then high PRIORITY.
2. GRANT is momentarily de-asserted by Wi-Fi/PTA but is reasserted as Wi-Fi finished.
3. EFR32 radio enables RX mode awaiting central TX.
4. EFR32 radio receives the central TX.
5. EFR32 radio exits receive mode.
6. At start of 150µs IFS, EFR32 radio transmits back to central.
7. After transmit, EFR32 reasserts PRIORITY and then REQUEST.
8. Wi-Fi resumes transmission.

###### Example 2: Configure EFR32 PTA support to operate with multi-radio 2-Wire PTA with active-low REQUEST (for Series 1) (heading level 7)

- Multiple EFR32 radios (external 1 kΩ ±5% pull-up required on REQUEST)
- REQUEST shared, active low, PC10
- GRANT, active low, PF3
- PRIORITY unused
- REQUEST_WINDOW is 50 µs
- Disabled Abort transmission mid packet if GRANT is lost
- RHO unused

The required #defines in sl_rail_util_coex_common_config.h and sl_rail_util_coex_config.h are:

```c
// $[COEX]

#define SL_RAIL_UTIL_COEX_REQ_PIN                             (10U)
#define SL_RAIL_UTIL_COEX_REQ_PORT                            (gpioPortC)
#define SL_RAIL_UTIL_COEX_REQ_ASSERT_LEVEL                    (0)
#define SL_RAIL_UTIL_COEX_REQ_WINDOW                          (50U)
#define SL_RAIL_UTIL_COEX_REQ_SHARED                          (1)
#define SL_RAIL_UTIL_COEX_REQ_BACKOFF                         (15U)

#define SL_RAIL_UTIL_COEX_GNT_PIN                             (3U)
#define SL_RAIL_UTIL_COEX_GNT_PORT                            (gpioPortF)
#define SL_RAIL_UTIL_COEX_GNT_ASSERT_LEVEL                    (0)
#define SL_RAIL_UTIL_COEX_TX_ABORT                            (0)

#define SL_RAIL_UTIL_COEX_PWM_DEFAULT_ENABLED                 (0)
#define SL_RAIL_UTIL_COEX_PWM_REQ_PERIOD                      (78U)
#define SL_RAIL_UTIL_COEX_PWM_REQ_DUTYCYCLE                   (20U)
#define SL_RAIL_UTIL_COEX_PWM_PRIORITY                        (0)

#define SL_RAIL_UTIL_COEX_DP_ENABLED                          (0)
// [COEX]$
```

The logic analyzer capture below shows the PTA interface, Wi-Fi radio state, and EFR32 radio state for an EFR32 radio configured for multi-radio 2-Wire PTA with active-low REQUEST:

![CONNECTION event (central) for Multi-EFR32 2-Wire Wi-Fi/PTA Logic Analyzer Capture(first anchor point in CONNECTION, using active-low REQUEST)](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image26.png)

where:

- **REQUEST**: active low, shared (open-drain) REQUEST input/output
- **GRANT**: active low GRANT input
- **CoEx TX ACTIVE**: EFR32 TX Active control signal (configured via sample code in [Application Code Coexistence Extensions](./04-application-code-coexistence-extensions))
- **CoEx RX ACTIVE**: EFR32 RX Active control signal (configured via sample code in [Application Code Coexistence Extensions](./04-application-code-coexistence-extensions))
- **CoEx PTI FRAME**: EFR32 Frame Control Data Frame signal (packet trace frame/synch)
- **CoEx PTI DATA**: EFR32 Frame Control Data Out signal (packet trace data)

The logic analyzer sequence above shows:

1. At REQUEST_WINDOW before the CONNECTION event, Shared REQUEST signal is tested and found not asserted by another EFR32 radio, so EFR32 radio asserts REQUEST.
2. Wi-Fi/PTA responds with GRANT asserted.
3. At end of REQUEST_WINDOW (start of CONNECTION event), EFR32 tests GRANTS, which is asserted.
4. With GRANT asserted at start of CONNECTION event, EFR32 executes transmit.
5. After transmit is complete and before end if 150µs IFS, EFR32 enables receive to capture expected response from CONNECTION peripheral device.
6. EFR32 device receives device and disables receive.
7. EFR32 repeats transmit/receive for four additional cycles as part of this first anchor point.
8. After last receive, EFR32 de-asserts REQUEST.
9. Wi-Fi/PTA responds with GRANT deasserted.

##### Application Code Coexistence Extensions

###### Code Example TX_ACTIVE/RX_ACTIVE on Series 1

It is helpful to access the EFR32 radio state during PTA coexistence debugging. The following code examples create the TX_ACTIVE and RX_ACTIVE signals seen in the previous logic analyzer captures. This EFR32MG1P232F256GM48 example pushes TX_ACTIVE out PD10 and RX_ACTIVE out PD11. Other GPIOs can be used with changes in #defines. Consult the design-specific EFR32xG datasheet and reference manual for details on changing #defines values to other EFR32 devices and to alternate GPIOs.

```c
   // Enable TX_ACT signal through GPIO PD10
   #define PRS_CH_CTRL_SOURCESEL_RAC2             (0x00000020UL<< 8)
   #define PRS_CH_CTRL_SIGSEL_RACPAEN             (0x00000004UL<< 0)
   #define TX_ACTIVE_PRS_SOURCE PRS_CH_CTRL_SOURCESEL_RAC2
   #define TX_ACTIVE_PRS_SIGNAL PRS_CH_CTRL_SIGSEL_RACPAEN

   #define TX_ACTIVE_PRS_CHANNEL 5
   #define TX_ACTIVE_PRS_LOCATION 0
   #define TX_ACTIVE_PRS_PORT gpioPortD
   #define TX_ACTIVE_PRS_PIN 10
   #define TX_ACTIVE_PRS_ROUTELOC_REG ROUTELOC1
   #define TX_ACTIVE_PRS_ROUTELOC_MASK (~0x00003F00UL)
   #define TX_ACTIVE_PRS_ROUTELOC_VALUE PRS_ROUTELOC1_CH5LOC_LOC0 // PD10
   #define TX_ACTIVE_PRS_ROUTEPEN PRS_ROUTEPEN_CH5PEN

   // Enable RX_ACT signal through GPIO PD11
   #define PRS_CH_CTRL_SOURCESEL_RAC2             (0x00000020UL<< 8)
   #define PRS_CH_CTRL_SIGSEL_RACRX               (0x00000002UL<< 0)
   #define RX_ACTIVE_PRS_SOURCE PRS_CH_CTRL_SOURCESEL_RAC2
   #define RX_ACTIVE_PRS_SIGNAL PRS_CH_CTRL_SIGSEL_RACRX

   #define RX_ACTIVE_PRS_CHANNEL 6
   #define RX_ACTIVE_PRS_LOCATION 13
   #define RX_ACTIVE_PRS_PORT gpioPortD
   #define RX_ACTIVE_PRS_PIN 11
   #define RX_ACTIVE_PRS_ROUTELOC_REG ROUTELOC1
   #define RX_ACTIVE_PRS_ROUTELOC_MASK (~0x003F0000UL)
   #define RX_ACTIVE_PRS_ROUTELOC_VALUE PRS_ROUTELOC1_CH6LOC_LOC13 // PD11
   #define RX_ACTIVE_PRS_ROUTEPEN PRS_ROUTEPEN_CH6PEN

   CMU_ClockEnable(cmuClock_PRS, true); // enable clock to PRS

   // Setup PRS input as TX_ACTIVE signal
   PRS_SourceAsyncSignalSet(TX_ACTIVE_PRS_CHANNEL, TX_ACTIVE_PRS_SOURCE, TX_ACTIVE_PRS_SIGNAL);
   // enable TX_ACTIVE output pin with initial value of 0
   GPIO_PinModeSet(TX_ACTIVE_PRS_PORT, TX_ACTIVE_PRS_PIN, gpioModePushPull, 0);
   // Route PRS CH/LOC to TX Active GPIO output
   PRS->TX_ACTIVE_PRS_ROUTELOC_REG = (PRS->TX_ACTIVE_PRS_ROUTELOC_REG & TX_ACTIVE_PRS_ROUTELOC_MASK) | TX_ACTIVE_PRS_ROUTELOC_VALUE;
   PRS->ROUTEPEN |= TX_ACTIVE_PRS_ROUTEPEN;

   // Setup PRS input as RX_ACTIVE signal
   PRS_SourceAsyncSignalSet(RX_ACTIVE_PRS_CHANNEL, RX_ACTIVE_PRS_SOURCE, RX_ACTIVE_PRS_SIGNAL);
   // enable RX_ACTIVE output pin with initial value of 0
   GPIO_PinModeSet(RX_ACTIVE_PRS_PORT, RX_ACTIVE_PRS_PIN, gpioModePushPull, 0);
   // Route PRS CH/LOC to RX Active GPIO output
   PRS->RX_ACTIVE_PRS_ROUTELOC_REG = (PRS->RX_ACTIVE_PRS_ROUTELOC_REG & RX_ACTIVE_PRS_ROUTELOC_MASK) | RX_ACTIVE_PRS_ROUTELOC_VALUE;
   PRS->ROUTEPEN |= RX_ACTIVE_PRS_ROUTEPEN;
```

###### Code Example TX_ACTIVE/RX_ACTIVE on Series 2

It is helpful to access the EFR32 radio state during PTA coexistence debugging. The following code examples create the TX_ACTIVE and RX_ACTIVE signals seen in the previous logic analyzer captures. This EFR32MG21 example pushes TX_ACTIVE out PD02 and RX_ACTIVE out PD03. Other GPIOs can be used with changes in #defines. Consult the design-specific EFR32xG21 reference manual to get information relative to PRS sources and signals. Note that on series 2, PRS channels aren’t available on all GPIO ports.

```c
// Enable TX_ACT and RX_ACT signal through GPIO PD02 and PD03

/* Signals */
#define RAC_RX_PRS_SOURCE (0x00000031UL\<\< 8)
#define RAC_RX_PRS_SIGNAL (0x03)
#define RAC_RX_PRS_CHANNEL 6
#define RAC_RX_PRS_PORT gpioPortD
#define RAC_RX_PRS_PIN 2

#define RAC_TX_PRS_SOURCE PRS_ASYNC_CH CTRL_SOURCESEL_RAC
#define RAC_TX_PRS_SIGNAL (0x04)
#define RAC_TX_PRS_CHANNEL 7
#define RAC_TX_PRS_PORT gpioPortD
#define RAC_TX_PRS_PIN 3

static void initPrs(void)
{

  /* On xG21 chips, PRS ASYNC Chan 6 11 are on port C/D. ASYNC chan 1 to 5 are on Port A/B. */
  PRS_SourceAsyncSignalSet( RAC_RX_PRS_CHANNEL, RAC_RX_PRS_SOURCE, RAC_RX_PRS_SIGNAL);
  PRS_SourceAsyncSignalSet( RAC_TX_PRS_CHANNEL, RAC_TX_PRS_SOURCE, RAC_TX_PRS_SIGNAL);

  /* Route output to PD02/PD03. No extra PRS logic needed here. */
  PRS_PinOutput(RAC_RX_PRS_CHANNEL,prsTypeAsync, RAC_RX_PRS_PORT , RAC_RX_PRS_PIN);
  PRS_PinOutput(RAC_TX_PRS_CHANNEL,prsTypeAsync, RAC_TX_PRS_PORT , RAC_TX_PRS_PIN);

  /* Enable PRS clock */
  CMU_ClockEnable(cmuClock_PRS, true);
}

static void initGpio(void)
{
  // Set Pins
  GPIO_PinModeSet(RAC_RX_PRS_PORT, RAC_RX_PRS_PIN, gpioModePushPull, 0);
  GPIO_PinModeSet(RAC_TX_PRS_PORT, RAC_TX_PRS_PIN, gpioModePushPull, 0);

  /* Set up GPIO clock */
  CMU_ClockEnable(cmuClock_GPIO,true);
}

void app_init(void)
{
  /////////////////////////////////////////////////////////////////////////////
  // Put your additional application init code here!                         //
  // This is called once during start-up.                                    //
  /////////////////////////////////////////////////////////////////////////////
  initGpio();
  initPrs();
}
```

The following illustrate a device advertising on the three primary channels. On each channel, the radio transceiver transmits a legacy advertisement and then transition back to the receive state for a short period of time to listen for incoming advertising request (active scanning).

![a device advertising on the three primary channels](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image27.png)

##### Coexistence Backplane Evaluation Board (EVB)

For evaluating the Silicon Labs EFR32 software coexistence solution, order EFR32MG Wireless SoC Starter Kit (WSTK) #SLWSTK6000B and Coexistence Backplane EVB (#SLWSTK-COEXBP). Detailed instructions for using the Starter Kit and Backplane EVB are found in [Silicon Labs Coexistence Development Kit (SLWSTK-COEXBP)](https://docs.silabs.com/multiprotocol/latest/coexistence-development-kit/). To see a demonstration of Wi-Fi coexistence and obtain links to additional coexistence documentation, visit the [Silicon Labs Wi-Fi Coexistence Learning Center](https://www.silabs.com/products/wireless/learning-center/wi-fi-coexistence).

![Coexistence Backplane EVB (#SLWSTK-COEXBP)](/bluetooth-coexistence-with-wifi/0.1/images/sld514-image28.jpg)

### iOS and Android ADK

#### iOS and Android ADK

Silicon Labs offers an application note that provides a high-level architecture overview of the Silicon Labs Bluetooth Mesh library, how it relates to the Bluetooth LE stack provided by the iOS and Android operating systems, and what APIs are available.

- [**iOS and Android ADK for Bluetooth Mesh SDK 2.x and Higher**](/btmesh/11.0.0/bluetooth-mesh-for-android-and-ios-adk): Describes how to get started with Bluetooth Mesh application development for iOS and Android smart phones and tablets using the Silicon Labs Bluetooth Mesh for iOS and Android Application Development Kit (ADK).

#### iOS And Android ADK for Bluetooth Mesh SDK v2.x and Higher

##### iOS and Android ADK for Bluetooth® Mesh SDK 2.x and Higher

> **NOTE: This section replaces _AN1200.1: iOS and Android ADK for Bluetooth® Mesh SDK 2.x and Higher_. Further updates to this application note will be provided here**.

This document describes how to get started with Bluetooth mesh application development for iOS and Android smart phones and tablets using the Silicon Labs Bluetooth Mesh for iOS and Android Application Development Kit (ADK).

The document also provides a high-level architecture overview of the Silicon Labs Bluetooth mesh library, how it relates to the Bluetooth LE stack provided by the iOS and Android operating systems and what APIs are available. It also contains code snippets and explanations for the most common Bluetooth mesh use cases.

The Bluetooth mesh mobile app is intended to demonstrate the Silicon Labs Bluetooth mesh technology together with the Bluetooth mesh SDK sample apps. The mobile app is a reference app for the Bluetooth mesh mobile ADK but it should not be taken as a starting point for customers to create their own mobile apps.

###### Key Points

- Introduction to the Silicon Labs’ Bluetooth mesh for iOS and Android ADK
- Getting started with development
- ADK usage

##### Introduction

The iOS and Android (API version 27 or older) Bluetooth LE stacks do not have native support for Bluetooth mesh and therefore devices with these operating systems cannot directly interact with Bluetooth mesh nodes using the Bluetooth mesh advertisement bearer. However, the Bluetooth mesh specification 1.0 also defines a GATT bearer, which enables any Bluetooth LE-capable device to interact with Bluetooth mesh nodes over GATT. iOS and Android (since API version 18) have included support for the Bluetooth GATT layer, and therefore it is possible to implement an iOS or Android application to provision, configure, and interact with Bluetooth mesh networks and nodes.

Silicon Labs provides a Bluetooth mesh stack for Gecko SoCs and Modules. The Silicon Labs Bluetooth Mesh ADK embeds the same stack and enable development of Bluetooth mesh applications for the iOS and Android systems.

The basic concept is that the native Bluetooth APIs of iOS and Android are used to discover and connect Bluetooth LE devices, while the ADK is used to manage the Bluetooth mesh-specific operations such as Bluetooth mesh security, device and node management, network, transport, and application layer operations.

##### Installation

###### Download

You have downloaded the ADK zip file from [SiliconLabs/gecko_sdk](https://github.com/SiliconLabs/gecko_sdk/releases/tag/v4.3.0) GitHub site.

###### ADK Structure

The ADK zip contains:

```bash
./app/bluetooth/
    android/                - Android ADK frameworks (debug and release)
    android/dokka/          - Android ADK reference documentation
    android_application/    - Android reference application (source code)
    ios/                    - iOS ADK Frameworks (debug and release)
    ios/docs/               - iOS ADK reference documentation
    ios_application/        - iOS reference application (source code)
```

> **Disclaimer**: The mobile apps are a reference apps for the Bluetooth Mesh mobile ADK, but it should not be taken as a starting point for customers to create their own mobile apps.

###### Set Up iOS Project

- Copy the BluetoothMesh.xcframework to a folder with the new iOS project (see section [ADK Structure](#adk-structure) for frameworks location).
- Open the main target in your project.
- Go to the General view.
- Add BluetoothMesh.xcframework to Frameworks, Libraries and Embedded Content.

![Frameworks, Libraries and Embedded Content](/bluetooth-mesh-for-android-and-ios-adk/11.0.0/images/sld811-image1.png)

![Add Files](/bluetooth-mesh-for-android-and-ios-adk/11.0.0/images/sld811-image2.png)

![BluetoothMesh.xcframework](/bluetooth-mesh-for-android-and-ios-adk/11.0.0/images/sld811-image3.png)

BluetoothMesh.xcframework should be visible in Frameworks, Libraries and Embedded Content section with “Embed & Sign” chosen.

![BluetoothMesh.xcframework visible in Frameworks](/bluetooth-mesh-for-android-and-ios-adk/11.0.0/images/sld811-image4.png)

Disable Bitcode in the project. BluetoothMesh.xcframework does not use Bitcode.

1. Select the main target in the project.
2. Go to the **Build Settings** view.
3. Search for _Bitcode_.
4. Set **Enable Bitcode** to **No**.

![Disable Bitcode](/bluetooth-mesh-for-android-and-ios-adk/11.0.0/images/sld811-image5.png)

###### Set Up Android Project

1. Create a project in Android Studio.
2. Copy the `*.aar` file to `<root path>/app/libs/` from the ADK package.
3. Add to `dependencies {...}` section of `<root path>/app/build.gradle:`  
   ```C  
   dependencies {  
     ...  
     implementation files('libs/ble_mesh-android_api-release.aar')  
     implementation 'com.google.code.gson:gson:2.10.1'  
   }  
   ```
4. Synchronize project after changes.
5. Initialize a `BluetoothMesh` object as shown in the following example.  
   ```C  
   import com.siliconlab.bluetoothmesh.adk.BluetoothMesh  
   import com.siliconlab.bluetoothmesh.adk.configuration.BluetoothMeshConfiguration  
     
   class MainActivity : AppCompatActivity() {  
       override fun onCreate(savedInstanceState: Bundle?) {  
           super.onCreate(savedInstanceState)  
           setContentView(R.layout.activity_main)  
     
           BluetoothMesh.initialize(applicationContext, BluetoothMeshConfiguration())  
       }  
   }  
   ```
6. Compile and run the project.

##### Usage: Basic Use Cases

The API is provided with support objects that help the user manage the Bluetooth mesh network. These are:

- Network – the main container in the mesh structure. Network is the owner of subnets and nodes.
- Subnet – a specific subnet belongs to a network.
- Node – a node can be added to many subnets. A node contains elements.
- Element – an addressable entity within a device containing models.
- Model – defines a set of States, State Transitions, State Bindings, Messages, and other associated behaviors.

![Node Structure](/bluetooth-mesh-for-android-and-ios-adk/11.0.0/images/sld811-image6.png)

Application developers are responsible for keeping track of any changes in the Bluetooth mesh structure. Objects are mutable and will change over time.

**Full API documentation and the reference applications’ source code are provided in the ADK package - see [ADK Structure](02-installation#adk-structure) for its location**.

###### Provisioning a Device (Over GATT Bearer)

Bluetooth device discovery must be done on the application side. Devices that can be provisioned advertise themselves with the Unprovisioned Device beacon and Bluetooth Mesh Provisioning Service shall be present in the GATT database.

To provision a new node, the ADK expects that object implementing:

    iOS: `SBMConnectableDevice`

    Android: `ConnectableDevice`

    Represents the device you want to provision, which can be connected to before provisioning.

and

    iOS: `SBMSubnet`

    Android: `Subnet`

    Represents the target subnet to which to provision node.

are provided.

The subnet can be created using:

    iOS: `SBMNetwork.createSubnet`

    Android: `Network.createSubnet`

To initiate the provisioning process, create

    iOS: `SBMProvisionerConnection`

    Android: `ProvisionerConnection`

Initiate the provisioning session using:

    iOS: `SBMProvisionerConnection.provision`

    Android: `ProvisionerConnection.provision`

###### Proxy Connection and Configuration

To configure provisioned nodes, the application must connect to subnet via proxy node.

The newly provisioned device will accept incoming proxy connection only for 60 seconds. If you intend to keep it as a proxy node you have to confirm its proxy role in this time window. Once you have one or more proxy nodes in your subnet, you may connect to that subnet and change settings of any node (including its proxy role) at any time.

To establish a proxy connection, initialize:

    iOS: `SBMProxyConnection`

    Android: `ProxyConnection`

object using:

    iOS: `SBMConnectableDevice`

    Android: `ConnectableDevice`

object, which represents a Bluetooth device advertising with a Bluetooth Mesh Proxy Service. This device will be used to send messages to the network.

After initializing ProxyConnection object, function:

    iOS: `SBMProxyConnection.connect`

    Android: `ProxyConnection.connectToProxy`

must be invoked to establish the connection. There is an overloaded ProxyConnection.connectToProxy method in Android with an additional boolean refreshBluetoothDevice argument, which supports deciding if BluetoothDevice should be refreshed before connecting to the proxy node. This is needed to obtain current GATT services after they have been changed during the provisioning process, because subsequent discoverServices method calls on the BluetoothGatt object can result in cached services from the first call (even if device was disconnected). Refreshing BluetoothDevice before connecting to the proxy node is required only during the first connection and configuration after provisioning.

After establishing the connection, class:

    iOS: `SBMConfigurationControl`

    Android: `ConfigurationControl`

can be used to set proxy service and get device composition data using:

    iOS: `SBMConfigurationControl.setProxy`

    Android: `ConfigurationControl.setProxy`

and

    iOS: `SBMConfiruationControl.getDeviceCompositionData`

    Android: `ConfigurationControl. getDeviceCompositionData`

After getting raw Device Composition Data it should be passed to node using:

    iOS: `SBMNode.overrideDeviceCompositionData`

    Android: `Node.overrideDeviceCompositionData`

It will parse raw data into elements and models.

After establishing a connection with a proxy node, using the proxy server creates a filter list, which can be used to reduce the number of packets exchanged with the proxy node. This can be done using:

    iOS: `SMBProxyControl.accept, SBMProxyControl.reject`

    Android: `ProxyControl.accept, ProxyControl.reject`

which adds addresses to or removes them from the proxy filter list, depending on the list type.

The filter list can be either an accept list or a reject list. An Accept list is a list of destination addresses of the packets which the Proxy Server passes through to the Client. Other packets will not be received. Reject list is a list of destination addresses of the packets which the Proxy Server will not pass through to the Client. All other packets will be received.

By default, the Proxy Server always initiates the filter as an empty accept list. The type of list can be changed using:

    iOS: `SBMProxyControl.setFilterType`

    Android: `ProxyControl.setFilterType`

Whenever the Proxy Client sends a message to the network, the source address is added to its accept list or removed from its reject list, to let the Client receive a response. The following method can be used to get the current filter list type and number of entries in list on the Proxy Server:

    iOS: `SBMProxyControl.getFilterStatus`

    Android: `ProxyControl.getFilterStatus`

###### Binding Models

Supported mesh models are listed in ModelIdentifier class.

To bind application key to a model within the node, the following steps should be done:

- An application key exists within the subnet to which the node belongs. An application key can be created using:

    iOS: `SBMSubnet.createAppKey`

    Android: `Subnet.createAppKey`

- An application key must be bound to node using:

    iOS: `SBMNodeControl.bind`

    Android: `NodeControl.bind`

- An application key must be bound to model using:

    iOS: `SBMFunctionalityBinder.bindModel`

    Android: `FunctionalityBinder.bindModel`

Models can be found within elements of the node. The property

    iOS: `SBMNode.elements`

    Android: `Node.elements`

contains elements of a node. Each element contains an array of sigModels and vendorModels.

For example, to send Generic OnOff get message to the node, first we need to find:

    iOS: `SBMSigModel`

    Android: `SigModel`

in that Node’s sigModels array, where the modelIdentifier is equal to:

    iOS: `SBMModelIdentifier.genericOnOffServer`

    Android: `ModelIdentifier.GenericOnOffServer`

###### Sending the Message

To send the Generic message use:

    iOS: `SBMControlElement`

    Android: `GenericClient`

Initialize it with:

    iOS: `SBMElement` and `SBMApplicationKey`

which contains the previously found GenericOnOffServer model.

To send get message use:

Initialize it with iOS: `SBMControlElement.getStatus`

Initialize it with Android: `ControlElement.getStatus`

Since we want to receive Generic OnOff status, the first argument needs to be:

Initialize it with iOS: `SBMGenericOnOff.self.`

Initialize it with Android: `ModelIdentifier.GenericOnOffClient`

The response will be received in the success callback on iOS side and related flow on Android side.

##### Resources

###### Silicon Labs Resources

- [Silicon Labs: Bluetooth LE](https://www.silabs.com/developers/bluetooth-low-energy)
- [Silicon Labs: Bluetooth Mesh Android and iOS Mobile Applications](https://www.silabs.com/developers/bluetooth-mesh-mobile-app)

###### Bluetooth SIG Resources

- [Bluetooth Mesh specifications](https://www.bluetooth.com/specifications/specs/?types=specs-docs&keyword=Mesh+adopted&filter=)
- [Bluetooth Mesh glossary](https://www.bluetooth.com/learn-about-bluetooth/feature-enhancements/mesh/mesh-glossary/)
- [Bluetooth Mesh articles](https://www.bluetooth.com/?s=Mesh)

###### iOS: Complying with Encryption Export Regulations

Every app submitted to TestFlight, or the App Store is uploaded to a server in the United States. It is a developer responsibility to make sure that the uploaded app is fully legal and contains all necessary information. For that reason, each developer should become familiar with Encryption Export Regulations. If the app uses, accesses, contains, implements, or incorporates encryption, this is considered an export of encryption software, which means that the app is subject to U.S. export compliance requirements, as well as the import compliance requirements of the countries where the app is distributed.

A more detailed explanation can be found at [Encryption Export Regulations](https://developer.apple.com/documentation/security/complying_with_encryption_export_regulations).

The following authentication, encryption and hash algorithms are used by the Bluetooth Mesh ADK:

- AES, 256 bit
- AES CCM, 128 bit
- AES ECB, 128 bit
- Elliptic Curve Diffie-Hellman

###### Android: Known Bluetooth Issues

While developing applications using Bluetooth LE for Android devices many problems can occur. Unfortunately, troubleshooting is not as straightforward as for the iOS. This section describes collected information how Bluetooth LE on Android works, common issues, and advice on how to solve them. It can help you to develop your application faster.

Working with Bluetooth LE on Android is difficult, because:

- Device manufacturers make changes to the Android Bluetooth LE stack. Your application can work well on one device but could have problems on another.
- Documentation on Bluetooth LE describes only basic concepts, but does not provide enough information about managing connections, need for queuing operations, or dealing with bugs.

###### Scanning (heading level 7)

Scanning for Bluetooth LE devices is power consuming. Four scan modes are available:

- SCAN_MODE_BALANCED: good trade-off between scan frequency and power consumption
- SCAN_MODE_LOW_LATENCY: highest scanning frequency
- SCAN_MODE_LOW_POWER: default scan mode consuming the least power
- SCAN_MODE_OPPORTUNISTIC: application that is using this mode will get scan results if another application is scanning (it does not start its own scanning)

Some applications may scan continuously, which would consume the phone’s battery power. In order to limit this Android has implemented changes related to scanning. In Android 7.0 and newer versions there is protection against Bluetooth LE scanning abuse. If your app starts and stops Bluetooth LE scans more than 5 times within 30 seconds, scan results will not be received temporarily. Moreover, starting with Android 7.0, you can perform one scan with a maximum time of 30 minutes. After this time Android will change the scan mode to SCAN_MODE_OPPORTUNISTIC. As of Android 8.1, if you do not set any ScanFilters scanning will be paused when the user turns off the screen, and will resume after the screen is turned on again.

Remember that the scanning process has to be stopped in your application. If you know the devices the user is looking for, stop the process when all devices are found. If you do not know which devices the user is looking for, stop scanning after a fixed period. Also consider stopping the scanning process if the user goes to another Activity or your application goes background.

###### Connecting (heading level 7)

Some phones have problems with connecting during scanning, so it would be better to stop scanning if you do not need to find another device. It is also recommended to wait about 500 milliseconds after stopping the scan before trying to connect to a device in order to avoid GATT_ERROR.

**Auto connect**

When you get a proper _BluetoothDevice_ object from _ScanResult_ you can connect to it by calling one of _connectGatt()_ method on _BluetoothDevice_. All versions of this method contain a parameter named _autoConnect_. Official documentation describes it only as “Boolean: It determines whether to directly connect to the remote device (false) or to automatically connect as soon as the remote device becomes available (true).”

When you connect to a device with _autoConnect_ set to false (direct connect) Android will try to connect to the device with a 30 second timeout. After that (if there was no other callback) you will receive an update with status GATT_ERROR (code 133). If there are pending connection attempts with _autoConnect_ set to true they will be suspended for this time. This direct connect attempt will not be executed until another pending direct connect is finished. A direct connect attempt usually takes less time to succeed than an auto connect one.

Android waits until it sees this device and connects when it is available. Using auto connect allows you to have more than one pending connection at the same time. These connections have no timeout, but they will be canceled when Bluetooth is turned off. If you are using _autoConnect_ set to true, you could be able to reconnect to the device as well. But the device must be in Bluetooth cache or be bonded before. Remember that turning Bluetooth off, rebooting your phone or manually clearing cache in settings menu will clear device information, so check the cache before attempting to reconnect.

###### Managing a Connection (heading level 7)

**Connection State**

After trying to connect to a device with the _connectGatt()_ method you should be informed about the result with the _onConnectionStateChange_ callback. It provides information about _status_ and _newState_, which you will use to perform appropriate steps.Remember to use the _close()_ method on the _BluetoothGatt_ object if the status is different than GATT_SUCCESS, or it is GATT_SUCCESS and the state is equal to STATE_DISCONNECTED, which means that device was successfully disconnected. If you do not call _close()_ the client registered for this connection will not be removed. Once 30 clients are reached (usually 5 are used by default after rebooting the phone) the user will not be able to connect to another device (until they clear the cache).

**Changing MTU**

Maximum Transmission Unit (MTU) determines the maximum length of the data packet sent between phone and Bluetooth LE device. You can request changing MTU size after successfully connecting with the device, before exchanging data with it. The default value of MTU is 23 (GATT_DEF_BLE_MTU_SIZE), but usually 3 bytes contain ATT headers, so only 20 bytes can be sent. Change MTU by calling _requestMtu(size)_ on the _BluetoothGatt_ object, where _size_ parameter is the new MTU length. Remember that the maximum available value is 517 (GATT_MAX_MTU_SIZE). If calling _requestMtu(size)_ returns true, wait for the _onMtuChanged_ callback with the result.

**Discovering Services**

Remember also that many Bluetooth LE operations are asynchronous, and you need to wait for a callback to perform next operation. For example, after getting _onConnectionStateChange_ with _status_ GATT_SUCCESS and _newState_ STATE_CONNECTED you need to call _discoverServices()_. It returns true if service discovery started and you must wait for the _onServicesDiscovered_ callback containing the status of this process. If you receive GATT_SUCCESS you can, for example, read/write characteristics, but if the result was not successful you need to disconnect from the device, because without services discovered you cannot perform those operations.

**Reading/Writing Characteristics**

These operations are also asynchronous, and you can perform only one operation at a time. To solve this, use a queue for your operations. Add the next operation to it and, when the first is completed, it is removed from queue and the next command is executed.

When writing data to a characteristic you can specify the write type. There are two available types: WRITE_TYPE_DEFAULT and WRITE_TYPE_NO_RESPONSE. Bluetooth Mesh supports only WRITE_TYPE_NO_RESPONSE.

**Disconnecting**

In Android you might have problems with performing some operations, as reconnecting, after improperly disconnecting from a device. There is a timeout while the phone continues opening connection events and the device is not fully disconnected, so you could have trouble connecting to it again. In Android this timeout was hardcoded to 20 seconds and has been changed to 5 seconds in Android 10, so it can take a lot of time until you are notified about the closed connection. In iOS this usually takes less than 1 second. If you want to reconnect immediately after disconnecting you could get status code 22, so it would be better to wait about 500 milliseconds before the connection attempt.

###### Errors (heading level 7)

Many errors can be received on some callback when working with a Bluetooth LE device. Unfortunately, not all of them have descriptions to help you to determine the problem. A common error is status 133 named GATT_ERROR. Unfortunately, no information about it is in _BluetoothGatt_ class documentation. If you got this error, the problem could be one of the following:

- You try to connect with _autoConnect_ set to false and receive the error after the 30 second timeout.
- After disconnecting from the device you do not invoke _close()_ so you get the error when next trying to connect.
- The Bluetooth cache contains some invalid data, so restart your phone.
- You use a device that has problems with Bluetooth LE. Some models, for example older Huawei phones, are known to have low Bluetooth LE quality. Try using another phone.
- There was a problem on the Bluetooth side. After calling _close()_ and waiting a little time, try connecting again.

##### Open-Source Licenses Used

**Table Open-Source Licenses Used**

|Feature|License|Comment|
|---|---|---|
|**Mbed TLS**|[Apache License 2.0](https://github.com/ARMmbed/mbedtls/blob/development/LICENSE)|Used for AES and ECDH and other cryptographic algorithms.|
|**GSON (Android only)**|[Apache License 2.0](https://github.com/google/gson/blob/master/LICENSE)|Used to store and load the Bluetooth mesh and device database to the Android secure storage.|

## Bluetooth Mesh API Reference Guide

### BGAPI Functions

Functions provided by the BGAPI protocol. 

#### Functions

##### sl_bgapi_obtain_message_buffer

`sl_status_t sl_bgapi_obtain_message_buffer(size_t max_payload_size, void **buffer)`

**Description:** Obtain a buffer that can be used to execute BGAPI or user commands.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|max_payload_size|The maximum payload size of the messages that the buffer will be used for. The value may not exceed the BGAPI configuration value SL_BGAPI_MAX_PAYLOAD_SIZE.|
|void **|[out]|buffer|Set to point to the buffer that the caller can use to execute BGAPI or user commands|

This function is provided as a convenience for NCP/CPC components that need to handle BGAPI or user commands and responses in their binary format. If the user of [sl_bgapi_execute_binary_command](sl-bgapi-functions#sl-bgapi-execute-binary-command) already has memory available for the command and response buffer (such as the memory allocated for UART RX/TX buffers), the user is encouraged to use the already existing memory when executing [sl_bgapi_execute_binary_command](sl-bgapi-functions#sl-bgapi-execute-binary-command).

If the user needs to allocate dedicated memory for any reason, using this function for the allocation may reduce the overall memory usage depending on the application configuration. If the configuration allows safe sharing of a message buffer (this is the case in a single-threaded baremetal application), the function returns the shared message buffer instead of making a separate allocation. When an RTOS is used, the function allocates a dedicated buffer for the caller.

Callers that use this function must call [sl_bgapi_release_message_buffer](sl-bgapi-functions#sl-bgapi-release-message-buffer) to release the message buffer when it is no longer needed.

**Returns**

- SL_STATUS_OK if the buffer was obtained, otherwise an error code

##### sl_bgapi_release_message_buffer

`void sl_bgapi_release_message_buffer(void *buffer)`

**Description:** Release a buffer that was obtained with [sl_bgapi_obtain_message_buffer](sl-bgapi-functions#sl-bgapi-obtain-message-buffer).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void *|[in]|buffer|The buffer to release|

##### sl_bgapi_check_command_sensitivity

`sl_status_t sl_bgapi_check_command_sensitivity(uint32_t command_header, bool *is_sensitive)`

**Description:** Check if the specified command is marked as sensitive.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|command_header|The header of the command to check|
|bool *|[out]|is_sensitive|Set to true if the command is considered sensitive, otherwise set to false|

This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format. If the NCP/CPC transport supports encryption, it can use this function to determine if the specified command is considered as sensitive and should be encrypted. If the execution of a sensitive command is attempted over an unencrypted transport, the NCP/CPC component can choose to reject the command.

**Returns**

- SL_STATUS_OK if the sensitivity of the command was successfully determined, otherwise an error code

##### sl_bgapi_execute_binary_command

`sl_status_t sl_bgapi_execute_binary_command(const void *command_buf, size_t command_buf_size, void *response_buf, size_t response_buf_size)`

**Description:** Execute a BGAPI command in binary format.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const void *|[in]|command_buf|Pointer to the full BGAPI command message including the header and the command-specific payload|
|size_t|[in]|command_buf_size|The size of the command buffer. This is used to verify that the command header is valid and the full command message is available.|
|void *|[out]|response_buf|Pointer to the response buffer to fill. It is acceptable to point to the same buffer as the command buffer in `command_buf`.|
|size_t|[in]|response_buf_size|The size of the response buffer|

This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format. This function automatically performs any locking or inter-process communication required to execute the command. The function returns when the command has been executed.

If the caller does not need the command buffer after executing the command, it is acceptable to point the response buffer `response_buf` to the same memory location as the command buffer `command_buf`. In this case the response overwrites the command buffer. Provided that the response buffer is large enough, this function guarantees that the response buffer is always filled with a valid response message. If command execution fails, the response buffer is filled with a generic error response.

**Returns**

- SL_STATUS_OK if the command was executed, otherwise an error code. Note that SL_STATUS_OK does not mean that the command was successful, only that it was executed.

##### sl_bgapi_lock

`SL_BGAPI_DEPRECATED sl_status_t sl_bgapi_lock(void)`

**Description:** Lock the BGAPI for exclusive access.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Deprecated** and replaced by [sl_bgapi_execute_binary_command](sl-bgapi-functions#sl-bgapi-execute-binary-command). The replacement provides a more flexible and efficient way to execute BGAPI commands in their binary format. The new function automatically performs any locking that's needed and enables re-using the command buffer memory for the response.

NOTE: This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format in an application that uses an RTOS. Normal application code that issues BGAPI commands by calling API functions defined by protocol stacks must never call this function directly.

See the documentation of [sl_bgapi_handle_command](sl-bgapi-functions#sl-bgapi-handle-command) for the full sequence that must be followed when processing commands in their binary format.

**Returns**

- SL_STATUS_OK if the lock has been obtained, otherwise an error code

##### sl_bgapi_unlock

`SL_BGAPI_DEPRECATED void sl_bgapi_unlock(void)`

**Description:** Release the lock obtained by [sl_bgapi_lock](sl-bgapi-functions#sl-bgapi-lock).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Deprecated** and replaced by [sl_bgapi_execute_binary_command](sl-bgapi-functions#sl-bgapi-execute-binary-command). The replacement provides a more flexible and efficient way to execute BGAPI commands in their binary format. The new function automatically performs any locking that's needed and enables re-using the command buffer memory for the response.

NOTE: This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format in an application that uses an RTOS. Normal application code that issues BGAPI commands by calling API functions defined by protocol stacks must never call this function directly.

See the documentation of [sl_bgapi_handle_command](sl-bgapi-functions#sl-bgapi-handle-command) for the full sequence that must be followed when processing commands in their binary format. 

##### sl_bgapi_handle_command

`SL_BGAPI_DEPRECATED void sl_bgapi_handle_command(uint32_t hdr, const void *data)`

**Description:** Handle a BGAPI command in binary format.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|hdr|The BGAPI command header|
|const void *|[in]|data|The payload data associated with the command|

**Deprecated** and replaced by [sl_bgapi_execute_binary_command](sl-bgapi-functions#sl-bgapi-execute-binary-command). The replacement provides a more flexible and efficient way to execute BGAPI commands in their binary format. The new function automatically performs any locking that's needed and enables re-using the command buffer memory for the response.

NOTE: This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format. Normal application code that issues BGAPI commands by calling API functions defined by protocol stacks must never call this function directly.

If the application uses an RTOS, the caller must protect the BGAPI handling by obtaining the BGAPI lock with [sl_bgapi_lock](sl-bgapi-functions#sl-bgapi-lock), handle the command with [sl_bgapi_handle_command](sl-bgapi-functions#sl-bgapi-handle-command), read the response from the buffer returned by [sl_bgapi_get_command_response](sl-bgapi-functions#sl-bgapi-get-command-response), and then release the lock with [sl_bgapi_unlock](sl-bgapi-functions#sl-bgapi-unlock). Here's an example of the full sequence that's required:

```c
// Lock BGAPI for exclusive access
sl_status_t status = sl_bgapi_lock();
if (status != SL_STATUS_OK) {
  // Locking will only fail if there are fatal unrecoverable errors with the
  // RTOS primitives, so caller may choose to just assert in case of errors.
}

// Process the command
sl_bgapi_handle_command(hdr, data);

// Read the response
void *rsp = sl_bgapi_get_command_response();
uint32_t rsp_header = *((uint32_t *)rsp);
size_t rsp_len = SL_BGAPI_MSG_LEN(rsp_header) + SL_BGAPI_MSG_HEADER_LEN;
// Send the `rsp_len` bytes of response starting from `rsp`

// Finally unlock the BGAPI to allow other commands to proceed
sl_bgapi_unlock();

```

Empty stub implementations are provided for [sl_bgapi_lock](sl-bgapi-functions#sl-bgapi-lock) and [sl_bgapi_unlock](sl-bgapi-functions#sl-bgapi-unlock), so the same sequence can be used for all NCP/CPC implementations even if an RTOS is not present.

##### sl_bgapi_get_command_response

`SL_BGAPI_DEPRECATED void * sl_bgapi_get_command_response(void)`

**Description:** Get the response of a handled BGAPI command.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Deprecated** and replaced by [sl_bgapi_execute_binary_command](sl-bgapi-functions#sl-bgapi-execute-binary-command). The replacement provides a more flexible and efficient way to execute BGAPI commands in their binary format. The new function automatically performs any locking that's needed and enables re-using the command buffer memory for the response.

NOTE: This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format. Normal application code that issues BGAPI commands by calling API functions defined by protocol stacks must never call this function directly.

See the documentation of [sl_bgapi_handle_command](sl-bgapi-functions#sl-bgapi-handle-command) for the full sequence that must be followed when processing commands in their binary format.

**Returns**

- Pointer to the BGAPI response structure that was filled when the command was executed in [sl_bgapi_handle_command](sl-bgapi-functions#sl-bgapi-handle-command).

##### sl_bgapi_set_error_response

`void sl_bgapi_set_error_response(uint32_t command_hdr, uint16_t result, void *response, size_t response_buf_size)`

**Description:** Set a generic error response to the specified buffer.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|command_hdr|The header of the command that we are responding to. It is possible in certain types of failures that the NCP implementation does not even have the full command header. In these cases it is recommended that the NCP implementation sets the unavailable bytes of the header to value zero to avoid transmitting uninitialized bytes. BGAPI commands are processed one command at a time and the recipient will be able to handle the error response even if it's missing the device ID, the class ID, or the command ID.|
|uint16_t|[in]|result|The value to set to the `result` field of the error response.|
|void *|[out]|response|The response buffer to fill|
|size_t|[in]|response_buf_size|The size of the response buffer. The caller must provide a buffer that has at least [SL_BGAPI_MSG_HEADER_LEN](sl-bgapi-types#sl-bgapi-msg-header-len) + [SL_BGAPI_MSG_ERROR_PAYLOAD_LEN](sl-bgapi-types#sl-bgapi-msg-error-payload-len) bytes available.|

NOTE: This function is provided for NCP/CPC components that need to handle BGAPI commands and responses in their binary format. Normal application code that issues BGAPI commands by calling API functions defined by protocol stacks must never call this function directly.

This function is available for NCP components that have detected fatal errors in command processing (for example have failed to receive a complete command message from the NCP host) and need to generate an error response without going through the normal BGAPI command processing.

### BT Event System Event Masks

API provided by the Bluetooth Mesh stack. 

#### License

**Copyright 2019 Silicon Laboratories Inc. www.silabs.com**

The licensor of this software is Silicon Laboratories Inc. Your use of this software is governed by the terms of Silicon Labs Master Software License Agreement (MSLA) available at www.silabs.com/about-us/legal/master-software-license-agreement. This software is distributed to you in Source Code format and is governed by the sections of the MSLA applicable to Source Code.

Event Mask values used with Event System

When the component `bluetooth_event_system_ipc` is included in the application, the Bluetooth mesh stack events are published using the Event System provided by the `event_system` component. The constants in this group define the event masks used for Bluetooth mesh stack events. 

#### Macros

`#define SL_BTMESH_EVENT_MASK_PUBLIC ((uint32_t) 0x01)`

**Description**: Event mask bit set in all public Bluetooth mesh events.

### Bluetooth Mesh GATT Proxy Client

Bluetooth Mesh GATT Proxy Client. 

Initialize the GATT Proxy client-side functionality. Mesh proxy commands are in the mesh_proxy class. This class allows the linker to drop the GATT Proxy client code if it is not needed. It is enough to initialize this BGAPI class. It contains no commands or events.

### Bluetooth Mesh GATT Proxy Server

Bluetooth Mesh GATT Proxy Server. 

Initialize the GATT Proxy server-side functionality. This class allows the linker to drop the GATT Proxy server code if it is not needed. It is enough to initialize this BGAPI class. It contains no commands or events.

### Bluetooth Mesh Key migration

Bluetooth Mesh Key migration. 

These commands are meant for migration from older releases to 3.2 and later releases. 

#### Functions

##### sl_btmesh_migration_migrate_keys

`sl_status_t sl_btmesh_migration_migrate_keys(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Ugrade keys from pre 3.2 release. Must be executed prior to to node or Provisioner initialization.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_migration_migrate_ddb

`sl_status_t sl_btmesh_migration_migrate_ddb(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Ugrade Device Database from pre 3.2 release. This command must be executed prior to provisioner initialization. Command may not be issued twice.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_migration_migrate_keys_id 0x01600028`

`#define sl_btmesh_cmd_migration_migrate_ddb_id 0x02600028`

`#define sl_btmesh_rsp_migration_migrate_keys_id 0x01600028`

`#define sl_btmesh_rsp_migration_migrate_ddb_id 0x02600028`

### Bluetooth Mesh Private Beacon Server Model

Bluetooth Mesh Private Beacon Server Model. 

This class provides the commands and messages to interface with the Private Beacon Server Model. 

#### Functions

##### sl_btmesh_private_beacon_server_init

`sl_status_t sl_btmesh_private_beacon_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the private beacon server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_private_beacon_server_deinit

`sl_status_t sl_btmesh_private_beacon_server_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the private beacon server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_private_beacon_server_init_id 0x01650028`

`#define sl_btmesh_cmd_private_beacon_server_deinit_id 0x02650028`

`#define sl_btmesh_rsp_private_beacon_server_init_id 0x01650028`

`#define sl_btmesh_rsp_private_beacon_server_deinit_id 0x02650028`

### Bluetooth Mesh Large Composition Data Server Model

Bluetooth Mesh Large Composition Data Server Model. 

This class provides the commands and messages to interface with the Large Composition Data Server model. 

#### Functions

##### sl_btmesh_lcd_server_init

`sl_status_t sl_btmesh_lcd_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the Large Composition Data Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lcd_server_deinit

`sl_status_t sl_btmesh_lcd_server_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the Large Composition Data Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_lcd_server_init_id 0x01670028`

`#define sl_btmesh_cmd_lcd_server_deinit_id 0x02670028`

`#define sl_btmesh_rsp_lcd_server_init_id 0x01670028`

`#define sl_btmesh_rsp_lcd_server_deinit_id 0x02670028`

### Bluetooth Mesh On-demand Private Proxy Server Model

Bluetooth Mesh On-demand Private Proxy Server Model. 

The On-Demand Private Proxy Server model is used to support the configuration of the advertising with Private Network Identity type functionality of a node. Requires the presence of the corresponding Solicitation PDU RPL Configuration Server model, which is initialized with it at the same time (see init command). 

#### Functions

##### sl_btmesh_on_demand_private_proxy_server_init

`sl_status_t sl_btmesh_on_demand_private_proxy_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the On-Demand Private Proxy Server model, and the Solicitation PDU RPL Configuration Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_on_demand_private_proxy_server_deinit

`sl_status_t sl_btmesh_on_demand_private_proxy_server_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the On-Demand Private Proxy Server model, and the Solicitation PDU RPL Configuration Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_on_demand_private_proxy_server_init_id 0x016a0028`

`#define sl_btmesh_cmd_on_demand_private_proxy_server_deinit_id 0x026a0028`

`#define sl_btmesh_rsp_on_demand_private_proxy_server_init_id 0x016a0028`

`#define sl_btmesh_rsp_on_demand_private_proxy_server_deinit_id 0x026a0028`

### Bluetooth Mesh model configuration migration

Bluetooth Mesh model configuration migration. 

These commands are meant for migrating existing model configuration data from older releases to 9.0 and later releases. 

#### Functions

##### sl_btmesh_model_migration_migrate_models

`sl_status_t sl_btmesh_model_migration_migrate_models(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Migrate model configuration data and virtual address data from pre-9.0 release storage format to 9.0 release storage format.

The command expects that DCD page 0 data is stored in persistent storage and contains device composition data that corresponds to the model entries stored on the device. It will create new storage format entries and copy the existing model configurations to the new entries based on the model layout defined on DCD page 0.

After all data is successfully copied to new format the old entries will be removed.

This command must be executed prior to node or Provisioner initialization.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_model_migration_migrate_models_id 0x016e0028`

`#define sl_btmesh_rsp_model_migration_migrate_models_id 0x016e0028`

### Utility Functions

Utility functions for applications on SoC. 

#### Functions

##### sl_btmesh_pop_event

`sl_status_t sl_btmesh_pop_event(sl_btmesh_msg_t *event)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_msg_t](sl-btmesh-common-types#sl-btmesh-msg-t) *|N/A|event|the pointer for storing the new event|

Get the next event that requires processing by user application. Application is not blocked if no event is waiting.

**Returns**

- SL_STATUS_OK if a new event is returned, or SL_STATUS_NOT_FOUND if no event is waiting; other value indicates an error occurred

##### sl_btmesh_event_pending

`bool sl_btmesh_event_pending(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Check whether events are in queue pending for processing. Call [sl_btmesh_pop_event](sl-btmesh-utility-functions#sl-btmesh-pop-event) to process pending events.

**Returns**

- true if event is pending; false otherwise

##### sl_btmesh_event_pending_len

`uint32_t sl_btmesh_event_pending_len(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Check whether events are in queue pending for processing and return the next event length in bytes if events are pending. Call [sl_btmesh_pop_event](sl-btmesh-utility-functions#sl-btmesh-pop-event) to process pending events.

**Returns**

- the next event length if event is pending; 0 otherwise

### BGAPI

#### BGAPI message header format

The BGAPI message header is the first 4 bytes of a BGAPI message. It consists of device and message types, IDs, and data payload length.

##### Byte 1

- **Bits 0 - 2**: Highest 3 bits of the data payload length field
- **Bits 3 - 5**: **Device type**  
  - Bit value **000**: Reserved for future use  
  - Bit value **001**: Reserved for future use  
  - Bit value **010**: Reserved for future use  
  - Bit value **011**: Reserved for future use  
  - Bit value **100**: Bluetooth LE  
  - Bit value **101**: Bluetooth Mesh  
  - Bit value **110**: BGAPI  
  - Bit value **111**: Reserved for future use
- **Bit 6**: **Encryption**  
  - Bit value **0**: The message is not encrypted.  
  - Bit value **1**: The message is encrypted.
- **Bit 7**: **Message type**  
  - Bit value **0**: The message is a command or a response to command.  
  - Bit value **1**: The message is an event.

##### Byte 2

This byte is the lowest 8 bits of the data payload length field.

##### Byte 3

This byte is the BGAPI **class ID**.

##### Byte 4

This byte is the **message ID** of a command, response or event.

A device type, class ID, message type and message ID together construct a unique identifer of a message within the BGAPI protocol.

#### Endianness

BGAPI protocol stores data in little endian.

#### Concurrency

When the application runs in an RTOS, the Bluetooth RTOS adaptation component has a mechanism to synchronize the handling of individual BGAPI commands. Thus, individual BGAPI commands are safe to be called from multiple threads when the Bluetooth RTOS adaptation component is used.

BGAPI commands cannot be called from interrupt context. Calling a command from interrupt context may delay the radio activity. Furthermore, when commands are also called from the main event loop or an RTOS task simultaneously, concurrent BGAPI calls may cause memory issues in the stack.

#### Payload Length Calculation

Use [SL_BGAPI_MSG_LEN](sl-bgapi-types#sl-bgapi-msg-len) to calculate the payload length of a BGAPI message.

#### Decode a BGAPI Message

On an NCP host, a received API message is either a response or an event. As the message is in binary format, users may need to decode the binary to its corresponding named message definition. Following method can be used to decode a message binary received on NCP host:

- Find out the device type from [Byte 1](md-doc-bgapi#md-doc-bgapi-1bgapi-message-header-byte1) of the message header. Go to the BGAPI message summary table according to the device type. The table may be the [BGAPI message summary](md-doc-bgapi#md-doc-bgapi-1bgapi-message-summary) in this document, or a table in another API reference manual. Bluetooth LE and Bluetooth Mesh APIs have separate API reference manuals.
- Find out the message type of the message from bit 7 of the [Byte 1](md-doc-bgapi#md-doc-bgapi-1bgapi-message-header-byte1) in the message header.
- Find out the class ID which is the [Byte 3](md-doc-bgapi#md-doc-bgapi-1bgapi-message-header-byte3) of the message header. Together with the message type, locate either the command or event message group for this class.
- Locate the row in the message group according to the message ID which is the [Byte 4](md-doc-bgapi#md-doc-bgapi-1bgapi-message-header-byte4) of the message header.
- If the row is a command, the decoded message is a response to this command. Go to the command documentation. The 5th and 6th bytes of the binary are the error code returned for the command. Rest data of the binary maps to the [out] parameters of the command in declaration order.
- If the row is an event, go to the event documentation. Data starting from the 5th byte maps to the event data structure fields in declaration order.

#### BGAPI message summary

The following table summarizes the class and message IDs of commands and events in the BGAPI protocol. A response message has the same class and message ID as the command it responds to.

The table also shows the minimum payload length for each message. Messages that have an array parameter can have longer payload length depending on the length of the array.

|Message Name|Class ID|Message ID|Minimum Payload Length|
|---|---|---|---|
|[Mesh Node](sl-btmesh-node)|
|Commands|
|[cmd_node_init](sl-btmesh-node#sl-btmesh-node-init)|0x14|0x00|0|
|[cmd_node_set_exportable_keys](sl-btmesh-node#sl-btmesh-node-set-exportable-keys)|0x14|0x24|0|
|[cmd_node_start_unprov_beaconing](sl-btmesh-node#sl-btmesh-node-start-unprov-beaconing)|0x14|0x01|1|
|[cmd_node_stop_unprov_beaconing](sl-btmesh-node#sl-btmesh-node-stop-unprov-beaconing)|0x14|0x16|0|
|[cmd_node_get_rssi](sl-btmesh-node#sl-btmesh-node-get-rssi)|0x14|0x17|0|
|[cmd_node_send_input_oob_request_response](sl-btmesh-node#sl-btmesh-node-send-input-oob-request-response)|0x14|0x02|1|
|[cmd_node_get_uuid](sl-btmesh-node#sl-btmesh-node-get-uuid)|0x14|0x03|0|
|[cmd_node_set_provisioning_data](sl-btmesh-node#sl-btmesh-node-set-provisioning-data)|0x14|0x04|41|
|[cmd_node_init_oob](sl-btmesh-node#sl-btmesh-node-init-oob)|0x14|0x05|10|
|[cmd_node_set_ivrecovery_mode](sl-btmesh-node#sl-btmesh-node-set-ivrecovery-mode)|0x14|0x06|1|
|[cmd_node_get_ivrecovery_mode](sl-btmesh-node#sl-btmesh-node-get-ivrecovery-mode)|0x14|0x07|0|
|[cmd_node_set_net_relay_delay](sl-btmesh-node#sl-btmesh-node-set-net-relay-delay)|0x14|0x0b|2|
|[cmd_node_get_net_relay_delay](sl-btmesh-node#sl-btmesh-node-get-net-relay-delay)|0x14|0x0c|0|
|[cmd_node_get_ivupdate_state](sl-btmesh-node#sl-btmesh-node-get-ivupdate-state)|0x14|0x0d|0|
|[cmd_node_request_ivupdate](sl-btmesh-node#sl-btmesh-node-request-ivupdate)|0x14|0x0e|0|
|[cmd_node_get_seq_remaining](sl-btmesh-node#sl-btmesh-node-get-seq-remaining)|0x14|0x0f|2|
|[cmd_node_save_replay_protection_list](sl-btmesh-node#sl-btmesh-node-save-replay-protection-list)|0x14|0x10|0|
|[cmd_node_set_uuid](sl-btmesh-node#sl-btmesh-node-set-uuid)|0x14|0x11|16|
|[cmd_node_get_replay_protection_list_status](sl-btmesh-node#sl-btmesh-node-get-replay-protection-list-status)|0x14|0x14|0|
|[cmd_node_get_element_address](sl-btmesh-node#sl-btmesh-node-get-element-address)|0x14|0x12|2|
|[cmd_node_send_static_oob_request_response](sl-btmesh-node#sl-btmesh-node-send-static-oob-request-response)|0x14|0x13|1|
|[cmd_node_reset](sl-btmesh-node#sl-btmesh-node-reset)|0x14|0x15|0|
|[cmd_node_set_beacon_reporting](sl-btmesh-node#sl-btmesh-node-set-beacon-reporting)|0x14|0x18|1|
|[cmd_node_set_iv_update_age](sl-btmesh-node#sl-btmesh-node-set-iv-update-age)|0x14|0x19|4|
|[cmd_node_get_key_count](sl-btmesh-node#sl-btmesh-node-get-key-count)|0x14|0x1a|1|
|[cmd_node_get_key](sl-btmesh-node#sl-btmesh-node-get-key)|0x14|0x1b|6|
|[cmd_node_get_networks](sl-btmesh-node#sl-btmesh-node-get-networks)|0x14|0x1c|0|
|[cmd_node_get_element_seqnum](sl-btmesh-node#sl-btmesh-node-get-element-seqnum)|0x14|0x1d|2|
|[cmd_node_set_model_option](sl-btmesh-node#sl-btmesh-node-set-model-option)|0x14|0x1e|11|
|[cmd_node_get_local_dcd](sl-btmesh-node#sl-btmesh-node-get-local-dcd)|0x14|0x1f|1|
|[cmd_node_power_off](sl-btmesh-node#sl-btmesh-node-power-off)|0x14|0x21|0|
|[cmd_node_set_provisioning_algorithms](sl-btmesh-node#sl-btmesh-node-set-provisioning-algorithms)|0x14|0x25|2|
|[cmd_node_init_provisioning_records](sl-btmesh-node#sl-btmesh-node-init-provisioning-records)|0x14|0x26|0|
|[cmd_node_set_unprov_beaconing_adv_interval](sl-btmesh-node#sl-btmesh-node-set-unprov-beaconing-adv-interval)|0x14|0x28|4|
|[cmd_node_set_proxy_service_adv_interval](sl-btmesh-node#sl-btmesh-node-set-proxy-service-adv-interval)|0x14|0x29|4|
|[cmd_node_set_provisioning_service_adv_interval](sl-btmesh-node#sl-btmesh-node-set-provisioning-service-adv-interval)|0x14|0x30|4|
|[cmd_node_get_local_model_metadata_page](sl-btmesh-node#sl-btmesh-node-get-local-model-metadata-page)|0x14|0x20|1|
|[cmd_node_save_proxy_solicitation_rpl](sl-btmesh-node#sl-btmesh-node-save-proxy-solicitation-rpl)|0x14|0x31|0|
|[cmd_node_get_proxy_solicitation_rpl_status](sl-btmesh-node#sl-btmesh-node-get-proxy-solicitation-rpl-status)|0x14|0x32|0|
|[cmd_node_set_oob_uri](sl-btmesh-node#sl-btmesh-node-set-oob-uri)|0x14|0x33|1|
|[cmd_node_get_oob_uri](sl-btmesh-node#sl-btmesh-node-get-oob-uri)|0x14|0x34|0|
|[cmd_node_test_identity](sl-btmesh-node#sl-btmesh-node-test-identity)|0x14|0x36|5|
|[cmd_node_test_proxy_beacon](sl-btmesh-node#sl-btmesh-node-test-proxy-beacon)|0x14|0x3c|3|
|[cmd_node_set_proxy_service_scan_response](sl-btmesh-node#sl-btmesh-node-set-proxy-service-scan-response)|0x14|0x37|3|
|[cmd_node_clear_proxy_service_scan_response](sl-btmesh-node#sl-btmesh-node-clear-proxy-service-scan-response)|0x14|0x38|2|
|[cmd_node_set_provisioning_service_scan_response](sl-btmesh-node#sl-btmesh-node-set-provisioning-service-scan-response)|0x14|0x39|1|
|[cmd_node_clear_provisioning_service_scan_response](sl-btmesh-node#sl-btmesh-node-clear-provisioning-service-scan-response)|0x14|0x3a|0|
|[cmd_node_compare_dcd](sl-btmesh-node#sl-btmesh-node-compare-dcd)|0x14|0x3b|2|
|Events|
|[evt_node_initialized](sl-btmesh-evt-node-initialized)|0x14|0x00|7|
|[evt_node_provisioned](sl-btmesh-evt-node-provisioned)|0x14|0x01|6|
|[evt_node_config_get](sl-btmesh-evt-node-config-get)|0x14|0x02|4|
|[evt_node_config_set](sl-btmesh-evt-node-config-set)|0x14|0x03|5|
|[evt_node_display_output_oob](sl-btmesh-evt-node-display-output-oob)|0x14|0x04|3|
|[evt_node_input_oob_request](sl-btmesh-evt-node-input-oob-request)|0x14|0x05|2|
|[evt_node_provisioning_started](sl-btmesh-evt-node-provisioning-started)|0x14|0x06|2|
|[evt_node_provisioning_failed](sl-btmesh-evt-node-provisioning-failed)|0x14|0x07|2|
|[evt_node_key_added](sl-btmesh-evt-node-key-added)|0x14|0x08|5|
|[evt_node_model_config_changed](sl-btmesh-evt-node-model-config-changed)|0x14|0x09|7|
|[evt_node_reset](sl-btmesh-evt-node-reset)|0x14|0x0a|0|
|[evt_node_ivrecovery_needed](sl-btmesh-evt-node-ivrecovery-needed)|0x14|0x0b|8|
|[evt_node_changed_ivupdate_state](sl-btmesh-evt-node-changed-ivupdate-state)|0x14|0x0c|5|
|[evt_node_static_oob_request](sl-btmesh-evt-node-static-oob-request)|0x14|0x0d|0|
|[evt_node_key_removed](sl-btmesh-evt-node-key-removed)|0x14|0x0e|5|
|[evt_node_key_updated](sl-btmesh-evt-node-key-updated)|0x14|0x0f|5|
|[evt_node_heartbeat](sl-btmesh-evt-node-heartbeat)|0x14|0x10|5|
|[evt_node_heartbeat_start](sl-btmesh-evt-node-heartbeat-start)|0x14|0x11|8|
|[evt_node_heartbeat_stop](sl-btmesh-evt-node-heartbeat-stop)|0x14|0x12|4|
|[evt_node_beacon_received](sl-btmesh-evt-node-beacon-received)|0x14|0x13|8|
|[evt_node_local_dcd_data](sl-btmesh-evt-node-local-dcd-data)|0x14|0x14|2|
|[evt_node_local_dcd_data_end](sl-btmesh-evt-node-local-dcd-data-end)|0x14|0x15|2|
|[evt_node_local_model_metadata_page](sl-btmesh-evt-node-local-model-metadata-page)|0x14|0x19|2|
|[evt_node_local_model_metadata_page_end](sl-btmesh-evt-node-local-model-metadata-page-end)|0x14|0x1a|2|
|[evt_node_start_received](sl-btmesh-evt-node-start-received)|0x14|0x16|5|
|[evt_node_address_updated](sl-btmesh-evt-node-address-updated)|0x14|0x17|2|
|[evt_node_dcd_updated](sl-btmesh-evt-node-dcd-updated)|0x14|0x18|0|
|[Bluetooth Mesh Stack Provisioner](sl-btmesh-prov)|
|Commands|
|[cmd_prov_init](sl-btmesh-prov#sl-btmesh-prov-init)|0x15|0x00|0|
|[cmd_prov_scan_unprov_beacons](sl-btmesh-prov#sl-btmesh-prov-scan-unprov-beacons)|0x15|0x01|0|
|[cmd_prov_create_provisioning_session](sl-btmesh-prov#sl-btmesh-prov-create-provisioning-session)|0x15|0x41|19|
|[cmd_prov_set_provisioning_suspend_event](sl-btmesh-prov#sl-btmesh-prov-set-provisioning-suspend-event)|0x15|0x42|1|
|[cmd_prov_provision_adv_device](sl-btmesh-prov#sl-btmesh-prov-provision-adv-device)|0x15|0x43|16|
|[cmd_prov_provision_gatt_device](sl-btmesh-prov#sl-btmesh-prov-provision-gatt-device)|0x15|0x44|17|
|[cmd_prov_provision_remote_device](sl-btmesh-prov#sl-btmesh-prov-provision-remote-device)|0x15|0x7f|18|
|[cmd_prov_continue_provisioning](sl-btmesh-prov#sl-btmesh-prov-continue-provisioning)|0x15|0x45|16|
|[cmd_prov_abort_provisioning](sl-btmesh-prov#sl-btmesh-prov-abort-provisioning)|0x15|0x47|17|
|[cmd_prov_set_device_address](sl-btmesh-prov#sl-btmesh-prov-set-device-address)|0x15|0x46|18|
|[cmd_prov_create_network](sl-btmesh-prov#sl-btmesh-prov-create-network)|0x15|0x03|3|
|[cmd_prov_create_appkey](sl-btmesh-prov#sl-btmesh-prov-create-appkey)|0x15|0x07|5|
|[cmd_prov_send_oob_pkey_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-pkey-response)|0x15|0x08|17|
|[cmd_prov_send_oob_auth_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-auth-response)|0x15|0x09|17|
|[cmd_prov_set_oob_requirements](sl-btmesh-prov#sl-btmesh-prov-set-oob-requirements)|0x15|0x0a|24|
|[cmd_prov_start_key_refresh](sl-btmesh-prov#sl-btmesh-prov-start-key-refresh)|0x15|0x0b|4|
|[cmd_prov_get_key_refresh_exclusion](sl-btmesh-prov#sl-btmesh-prov-get-key-refresh-exclusion)|0x15|0x0c|18|
|[cmd_prov_set_key_refresh_exclusion](sl-btmesh-prov#sl-btmesh-prov-set-key-refresh-exclusion)|0x15|0x0d|19|
|[cmd_prov_set_key_refresh_failure](sl-btmesh-prov#sl-btmesh-prov-set-key-refresh-failure)|0x15|0x12|18|
|[cmd_prov_phase_timeout_get](sl-btmesh-prov#sl-btmesh-prov-phase-timeout-get)|0x15|0x10|0|
|[cmd_prov_phase_timeout_set](sl-btmesh-prov#sl-btmesh-prov-phase-timeout-set)|0x15|0x11|4|
|[cmd_prov_get_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry)|0x15|0x16|16|
|[cmd_prov_delete_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-delete-ddb-entry)|0x15|0x17|16|
|[cmd_prov_add_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-add-ddb-entry)|0x15|0x18|37|
|[cmd_prov_list_ddb_entries](sl-btmesh-prov#sl-btmesh-prov-list-ddb-entries)|0x15|0x19|0|
|[cmd_prov_initialize_network](sl-btmesh-prov#sl-btmesh-prov-initialize-network)|0x15|0x37|6|
|[cmd_prov_get_key_refresh_appkey_exclusion](sl-btmesh-prov#sl-btmesh-prov-get-key-refresh-appkey-exclusion)|0x15|0x38|20|
|[cmd_prov_set_key_refresh_appkey_exclusion](sl-btmesh-prov#sl-btmesh-prov-set-key-refresh-appkey-exclusion)|0x15|0x39|21|
|[cmd_prov_stop_scan_unprov_beacons](sl-btmesh-prov#sl-btmesh-prov-stop-scan-unprov-beacons)|0x15|0x3a|0|
|[cmd_prov_update_device_netkey_index](sl-btmesh-prov#sl-btmesh-prov-update-device-netkey-index)|0x15|0x3b|18|
|[cmd_prov_suspend_key_refresh](sl-btmesh-prov#sl-btmesh-prov-suspend-key-refresh)|0x15|0x3c|2|
|[cmd_prov_resume_key_refresh](sl-btmesh-prov#sl-btmesh-prov-resume-key-refresh)|0x15|0x3d|2|
|[cmd_prov_get_key_refresh_phase](sl-btmesh-prov#sl-btmesh-prov-get-key-refresh-phase)|0x15|0x3e|2|
|[cmd_prov_start_key_refresh_from_phase](sl-btmesh-prov#sl-btmesh-prov-start-key-refresh-from-phase)|0x15|0x3f|5|
|[cmd_prov_flush_key_refresh_state](sl-btmesh-prov#sl-btmesh-prov-flush-key-refresh-state)|0x15|0x40|2|
|[cmd_prov_get_provisioning_records_list](sl-btmesh-prov#sl-btmesh-prov-get-provisioning-records-list)|0x15|0x1c|16|
|[cmd_prov_get_provisioning_record_data](sl-btmesh-prov#sl-btmesh-prov-get-provisioning-record-data)|0x15|0x1d|18|
|[cmd_prov_init_provisioning_records](sl-btmesh-prov#sl-btmesh-prov-init-provisioning-records)|0x15|0x1e|0|
|[cmd_prov_get_ddb_entry_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-count)|0x15|0x49|0|
|[cmd_prov_get_ddb_entry_by_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-by-count)|0x15|0x4a|2|
|Events|
|[evt_prov_initialized](sl-btmesh-evt-prov-initialized)|0x15|0x00|7|
|[evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended)|0x15|0x18|17|
|[evt_prov_capabilities](sl-btmesh-evt-prov-capabilities)|0x15|0x17|27|
|[evt_prov_provisioning_failed](sl-btmesh-evt-prov-provisioning-failed)|0x15|0x01|17|
|[evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned)|0x15|0x02|18|
|[evt_prov_unprov_beacon](sl-btmesh-evt-prov-unprov-beacon)|0x15|0x03|31|
|[evt_prov_oob_pkey_request](sl-btmesh-evt-prov-oob-pkey-request)|0x15|0x06|16|
|[evt_prov_oob_auth_request](sl-btmesh-evt-prov-oob-auth-request)|0x15|0x07|19|
|[evt_prov_oob_display_input](sl-btmesh-evt-prov-oob-display-input)|0x15|0x08|19|
|[evt_prov_ddb_list](sl-btmesh-evt-prov-ddb-list)|0x15|0x09|19|
|[evt_prov_uri](sl-btmesh-evt-prov-uri)|0x15|0x0d|5|
|[evt_prov_key_refresh_phase_update](sl-btmesh-evt-prov-key-refresh-phase-update)|0x15|0x14|3|
|[evt_prov_key_refresh_node_update](sl-btmesh-evt-prov-key-refresh-node-update)|0x15|0x15|20|
|[evt_prov_key_refresh_complete](sl-btmesh-evt-prov-key-refresh-complete)|0x15|0x16|4|
|[evt_prov_add_ddb_entry_complete](sl-btmesh-evt-prov-add-ddb-entry-complete)|0x15|0x19|18|
|[evt_prov_delete_ddb_entry_complete](sl-btmesh-evt-prov-delete-ddb-entry-complete)|0x15|0x1a|18|
|[evt_prov_initialization_failed](sl-btmesh-evt-prov-initialization-failed)|0x15|0x1b|2|
|[evt_prov_provisioning_records_list](sl-btmesh-evt-prov-provisioning-records-list)|0x15|0x1c|19|
|[evt_prov_provisioning_record_data](sl-btmesh-evt-prov-provisioning-record-data)|0x15|0x1d|22|
|[evt_prov_start_sent](sl-btmesh-evt-prov-start-sent)|0x15|0x1e|21|
|[Bluetooth Mesh Proxy Connections](sl-btmesh-proxy)|
|Commands|
|[cmd_proxy_connect](sl-btmesh-proxy#sl-btmesh-proxy-connect)|0x18|0x00|1|
|[cmd_proxy_disconnect](sl-btmesh-proxy#sl-btmesh-proxy-disconnect)|0x18|0x01|4|
|[cmd_proxy_set_filter_type](sl-btmesh-proxy#sl-btmesh-proxy-set-filter-type)|0x18|0x02|7|
|[cmd_proxy_allow](sl-btmesh-proxy#sl-btmesh-proxy-allow)|0x18|0x03|8|
|[cmd_proxy_deny](sl-btmesh-proxy#sl-btmesh-proxy-deny)|0x18|0x04|8|
|[cmd_proxy_optimisation_toggle](sl-btmesh-proxy#sl-btmesh-proxy-optimisation-toggle)|0x18|0x05|1|
|[cmd_proxy_send_solicitation](sl-btmesh-proxy#sl-btmesh-proxy-send-solicitation)|0x18|0x06|6|
|Events|
|[evt_proxy_connected](sl-btmesh-evt-proxy-connected)|0x18|0x00|4|
|[evt_proxy_disconnected](sl-btmesh-evt-proxy-disconnected)|0x18|0x01|6|
|[evt_proxy_filter_status](sl-btmesh-evt-proxy-filter-status)|0x18|0x02|7|
|[Bluetooth Mesh Silabs Configuration Client Vendor Model](sl-btmesh-silabs-config-client)|
|Commands|
|[cmd_silabs_config_client_init](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-init)|0x01|0x00|0|
|[cmd_silabs_config_client_set_tx](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-set-tx)|0x01|0x01|9|
|[cmd_silabs_config_client_get_tx](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-get-tx)|0x01|0x02|4|
|[cmd_silabs_config_client_set_model_enable](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-set-model-enable)|0x01|0x03|11|
|[cmd_silabs_config_client_get_model_enable](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-get-model-enable)|0x01|0x04|10|
|[cmd_silabs_config_client_set_network_pdu](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-set-network-pdu)|0x01|0x05|6|
|[cmd_silabs_config_client_get_network_pdu](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-get-network-pdu)|0x01|0x06|4|
|[cmd_silabs_config_client_deinit](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-deinit)|0x01|0x07|0|
|Events|
|[evt_silabs_config_client_tx_status](sl-btmesh-evt-silabs-config-client-tx-status)|0x01|0x01|8|
|[evt_silabs_config_client_model_status](sl-btmesh-evt-silabs-config-client-model-status)|0x01|0x02|10|
|[evt_silabs_config_client_network_pdu_status](sl-btmesh-evt-silabs-config-client-network-pdu-status)|0x01|0x03|5|
|[Bluetooth Mesh Vendor Model](sl-btmesh-vendor-model)|
|Commands|
|[cmd_vendor_model_send](sl-btmesh-vendor-model#sl-btmesh-vendor-model-send)|0x19|0x00|15|
|[cmd_vendor_model_set_publication](sl-btmesh-vendor-model#sl-btmesh-vendor-model-set-publication)|0x19|0x01|9|
|[cmd_vendor_model_clear_publication](sl-btmesh-vendor-model#sl-btmesh-vendor-model-clear-publication)|0x19|0x02|6|
|[cmd_vendor_model_publish](sl-btmesh-vendor-model#sl-btmesh-vendor-model-publish)|0x19|0x03|6|
|[cmd_vendor_model_init](sl-btmesh-vendor-model#sl-btmesh-vendor-model-init)|0x19|0x04|8|
|[cmd_vendor_model_deinit](sl-btmesh-vendor-model#sl-btmesh-vendor-model-deinit)|0x19|0x05|6|
|[cmd_vendor_model_send_tracked](sl-btmesh-vendor-model#sl-btmesh-vendor-model-send-tracked)|0x19|0x06|16|
|[cmd_vendor_model_set_publication_tracked](sl-btmesh-vendor-model#sl-btmesh-vendor-model-set-publication-tracked)|0x19|0x07|10|
|[cmd_vendor_model_set_option](sl-btmesh-vendor-model#sl-btmesh-vendor-model-set-option)|0x19|0x08|5|
|Events|
|[evt_vendor_model_receive](sl-btmesh-evt-vendor-model-receive)|0x19|0x00|18|
|[evt_vendor_model_send_complete](sl-btmesh-evt-vendor-model-send-complete)|0x19|0x01|5|
|[Bluetooth Mesh Health Client Model](sl-btmesh-health-client)|
|Commands|
|[cmd_health_client_init](sl-btmesh-health-client#sl-btmesh-health-client-init)|0x1a|0x07|0|
|[cmd_health_client_deinit](sl-btmesh-health-client#sl-btmesh-health-client-deinit)|0x1a|0x08|0|
|[cmd_health_client_get](sl-btmesh-health-client#sl-btmesh-health-client-get)|0x1a|0x00|8|
|[cmd_health_client_clear](sl-btmesh-health-client#sl-btmesh-health-client-clear)|0x1a|0x01|9|
|[cmd_health_client_test](sl-btmesh-health-client#sl-btmesh-health-client-test)|0x1a|0x02|10|
|[cmd_health_client_get_period](sl-btmesh-health-client#sl-btmesh-health-client-get-period)|0x1a|0x03|6|
|[cmd_health_client_set_period](sl-btmesh-health-client#sl-btmesh-health-client-set-period)|0x1a|0x04|8|
|[cmd_health_client_get_attention](sl-btmesh-health-client#sl-btmesh-health-client-get-attention)|0x1a|0x05|6|
|[cmd_health_client_set_attention](sl-btmesh-health-client#sl-btmesh-health-client-set-attention)|0x1a|0x06|8|
|Events|
|[evt_health_client_server_status](sl-btmesh-evt-health-client-server-status)|0x1a|0x00|13|
|[evt_health_client_server_status_period](sl-btmesh-evt-health-client-server-status-period)|0x1a|0x01|9|
|[evt_health_client_server_status_attention](sl-btmesh-evt-health-client-server-status-attention)|0x1a|0x02|9|
|[Bluetooth Mesh Health Server Model](sl-btmesh-health-server)|
|Commands|
|[cmd_health_server_set_fault](sl-btmesh-health-server#sl-btmesh-health-server-set-fault)|0x1b|0x00|3|
|[cmd_health_server_clear_fault](sl-btmesh-health-server#sl-btmesh-health-server-clear-fault)|0x1b|0x01|3|
|[cmd_health_server_send_test_response](sl-btmesh-health-server#sl-btmesh-health-server-send-test-response)|0x1b|0x02|8|
|Events|
|[evt_health_server_attention](sl-btmesh-evt-health-server-attention)|0x1b|0x00|3|
|[evt_health_server_test_request](sl-btmesh-evt-health-server-test-request)|0x1b|0x01|12|
|[Bluetooth Mesh Generic Client Model](sl-btmesh-generic-client)|
|Commands|
|[cmd_generic_client_get](sl-btmesh-generic-client#sl-btmesh-generic-client-get)|0x1e|0x00|9|
|[cmd_generic_client_set](sl-btmesh-generic-client#sl-btmesh-generic-client-set)|0x1e|0x01|19|
|[cmd_generic_client_publish](sl-btmesh-generic-client#sl-btmesh-generic-client-publish)|0x1e|0x02|15|
|[cmd_generic_client_get_params](sl-btmesh-generic-client#sl-btmesh-generic-client-get-params)|0x1e|0x03|10|
|[cmd_generic_client_init](sl-btmesh-generic-client#sl-btmesh-generic-client-init)|0x1e|0x04|0|
|[cmd_generic_client_init_common](sl-btmesh-generic-client#sl-btmesh-generic-client-init-common)|0x1e|0x05|0|
|[cmd_generic_client_init_on_off](sl-btmesh-generic-client#sl-btmesh-generic-client-init-on-off)|0x1e|0x06|0|
|[cmd_generic_client_init_level](sl-btmesh-generic-client#sl-btmesh-generic-client-init-level)|0x1e|0x07|0|
|[cmd_generic_client_init_default_transition_time](sl-btmesh-generic-client#sl-btmesh-generic-client-init-default-transition-time)|0x1e|0x08|0|
|[cmd_generic_client_init_power_on_off](sl-btmesh-generic-client#sl-btmesh-generic-client-init-power-on-off)|0x1e|0x09|0|
|[cmd_generic_client_init_power_level](sl-btmesh-generic-client#sl-btmesh-generic-client-init-power-level)|0x1e|0x0a|0|
|[cmd_generic_client_init_battery](sl-btmesh-generic-client#sl-btmesh-generic-client-init-battery)|0x1e|0x0b|0|
|[cmd_generic_client_init_location](sl-btmesh-generic-client#sl-btmesh-generic-client-init-location)|0x1e|0x0c|0|
|[cmd_generic_client_init_property](sl-btmesh-generic-client#sl-btmesh-generic-client-init-property)|0x1e|0x0d|0|
|[cmd_generic_client_init_lightness](sl-btmesh-generic-client#sl-btmesh-generic-client-init-lightness)|0x1e|0x0e|0|
|[cmd_generic_client_init_ctl](sl-btmesh-generic-client#sl-btmesh-generic-client-init-ctl)|0x1e|0x0f|0|
|[cmd_generic_client_init_hsl](sl-btmesh-generic-client#sl-btmesh-generic-client-init-hsl)|0x1e|0x10|0|
|Events|
|[evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status)|0x1e|0x00|16|
|[Bluetooth Mesh Generic Server Model](sl-btmesh-generic-server)|
|Commands|
|[cmd_generic_server_respond](sl-btmesh-generic-server#sl-btmesh-generic-server-respond)|0x1f|0x00|16|
|[cmd_generic_server_update](sl-btmesh-generic-server#sl-btmesh-generic-server-update)|0x1f|0x01|10|
|[cmd_generic_server_publish](sl-btmesh-generic-server#sl-btmesh-generic-server-publish)|0x1f|0x02|5|
|[cmd_generic_server_init](sl-btmesh-generic-server#sl-btmesh-generic-server-init)|0x1f|0x04|0|
|[cmd_generic_server_init_common](sl-btmesh-generic-server#sl-btmesh-generic-server-init-common)|0x1f|0x05|0|
|[cmd_generic_server_init_on_off](sl-btmesh-generic-server#sl-btmesh-generic-server-init-on-off)|0x1f|0x06|0|
|[cmd_generic_server_init_level](sl-btmesh-generic-server#sl-btmesh-generic-server-init-level)|0x1f|0x07|0|
|[cmd_generic_server_init_default_transition_time](sl-btmesh-generic-server#sl-btmesh-generic-server-init-default-transition-time)|0x1f|0x08|0|
|[cmd_generic_server_init_power_on_off](sl-btmesh-generic-server#sl-btmesh-generic-server-init-power-on-off)|0x1f|0x09|0|
|[cmd_generic_server_init_power_level](sl-btmesh-generic-server#sl-btmesh-generic-server-init-power-level)|0x1f|0x0a|0|
|[cmd_generic_server_init_battery](sl-btmesh-generic-server#sl-btmesh-generic-server-init-battery)|0x1f|0x0b|0|
|[cmd_generic_server_init_location](sl-btmesh-generic-server#sl-btmesh-generic-server-init-location)|0x1f|0x0c|0|
|[cmd_generic_server_init_property](sl-btmesh-generic-server#sl-btmesh-generic-server-init-property)|0x1f|0x0d|0|
|[cmd_generic_server_init_lightness](sl-btmesh-generic-server#sl-btmesh-generic-server-init-lightness)|0x1f|0x0e|0|
|[cmd_generic_server_init_ctl](sl-btmesh-generic-server#sl-btmesh-generic-server-init-ctl)|0x1f|0x0f|0|
|[cmd_generic_server_init_hsl](sl-btmesh-generic-server#sl-btmesh-generic-server-init-hsl)|0x1f|0x10|0|
|[cmd_generic_server_get_cached_state](sl-btmesh-generic-server#sl-btmesh-generic-server-get-cached-state)|0x1f|0x11|5|
|Events|
|[evt_generic_server_client_request](sl-btmesh-evt-generic-server-client-request)|0x1f|0x00|20|
|[evt_generic_server_state_changed](sl-btmesh-evt-generic-server-state-changed)|0x1f|0x01|10|
|[evt_generic_server_state_recall](sl-btmesh-evt-generic-server-state-recall)|0x1f|0x02|10|
|[Bluetooth Mesh Test Utilities](sl-btmesh-test)|
|Commands|
|[cmd_test_get_nettx](sl-btmesh-test#sl-btmesh-test-get-nettx)|0x22|0x00|0|
|[cmd_test_set_nettx](sl-btmesh-test#sl-btmesh-test-set-nettx)|0x22|0x01|2|
|[cmd_test_get_relay](sl-btmesh-test#sl-btmesh-test-get-relay)|0x22|0x02|0|
|[cmd_test_set_relay](sl-btmesh-test#sl-btmesh-test-set-relay)|0x22|0x03|3|
|[cmd_test_set_ivupdate_test_mode](sl-btmesh-test#sl-btmesh-test-set-ivupdate-test-mode)|0x22|0x05|1|
|[cmd_test_get_ivupdate_test_mode](sl-btmesh-test#sl-btmesh-test-get-ivupdate-test-mode)|0x22|0x06|0|
|[cmd_test_set_ivupdate_state](sl-btmesh-test#sl-btmesh-test-set-ivupdate-state)|0x22|0x08|1|
|[cmd_test_send_beacons](sl-btmesh-test#sl-btmesh-test-send-beacons)|0x22|0x09|0|
|[cmd_test_bind_local_model_app](sl-btmesh-test#sl-btmesh-test-bind-local-model-app)|0x22|0x0a|8|
|[cmd_test_unbind_local_model_app](sl-btmesh-test#sl-btmesh-test-unbind-local-model-app)|0x22|0x0b|8|
|[cmd_test_add_local_model_sub](sl-btmesh-test#sl-btmesh-test-add-local-model-sub)|0x22|0x0c|8|
|[cmd_test_remove_local_model_sub](sl-btmesh-test#sl-btmesh-test-remove-local-model-sub)|0x22|0x0d|8|
|[cmd_test_add_local_model_sub_va](sl-btmesh-test#sl-btmesh-test-add-local-model-sub-va)|0x22|0x0e|7|
|[cmd_test_remove_local_model_sub_va](sl-btmesh-test#sl-btmesh-test-remove-local-model-sub-va)|0x22|0x0f|7|
|[cmd_test_get_local_model_sub](sl-btmesh-test#sl-btmesh-test-get-local-model-sub)|0x22|0x10|6|
|[cmd_test_set_local_model_pub](sl-btmesh-test#sl-btmesh-test-set-local-model-pub)|0x22|0x11|14|
|[cmd_test_set_local_model_pub_va](sl-btmesh-test#sl-btmesh-test-set-local-model-pub-va)|0x22|0x12|13|
|[cmd_test_get_local_model_pub](sl-btmesh-test#sl-btmesh-test-get-local-model-pub)|0x22|0x13|6|
|[cmd_test_set_local_heartbeat_subscription](sl-btmesh-test#sl-btmesh-test-set-local-heartbeat-subscription)|0x22|0x14|5|
|[cmd_test_get_local_heartbeat_subscription](sl-btmesh-test#sl-btmesh-test-get-local-heartbeat-subscription)|0x22|0x15|0|
|[cmd_test_get_local_heartbeat_publication](sl-btmesh-test#sl-btmesh-test-get-local-heartbeat-publication)|0x22|0x16|0|
|[cmd_test_set_local_heartbeat_publication](sl-btmesh-test#sl-btmesh-test-set-local-heartbeat-publication)|0x22|0x17|9|
|[cmd_test_add_local_key](sl-btmesh-test#sl-btmesh-test-add-local-key)|0x22|0x1a|21|
|[cmd_test_remove_local_key](sl-btmesh-test#sl-btmesh-test-remove-local-key)|0x22|0x1b|3|
|[cmd_test_update_local_key](sl-btmesh-test#sl-btmesh-test-update-local-key)|0x22|0x1c|19|
|[cmd_test_set_adv_bearer_state](sl-btmesh-test#sl-btmesh-test-set-adv-bearer-state)|0x22|0x1f|1|
|[cmd_test_prov_get_device_key](sl-btmesh-test#sl-btmesh-test-prov-get-device-key)|0x22|0x23|2|
|[cmd_test_prov_prepare_key_refresh](sl-btmesh-test#sl-btmesh-test-prov-prepare-key-refresh)|0x22|0x24|17|
|[cmd_test_cancel_segmented_tx](sl-btmesh-test#sl-btmesh-test-cancel-segmented-tx)|0x22|0x25|4|
|[cmd_test_set_iv_index](sl-btmesh-test#sl-btmesh-test-set-iv-index)|0x22|0x26|4|
|[cmd_test_set_element_seqnum](sl-btmesh-test#sl-btmesh-test-set-element-seqnum)|0x22|0x27|6|
|[cmd_test_get_local_model_app_bindings](sl-btmesh-test#sl-btmesh-test-get-local-model-app-bindings)|0x22|0x29|6|
|[cmd_test_get_replay_protection_list_entry](sl-btmesh-test#sl-btmesh-test-get-replay-protection-list-entry)|0x22|0x2a|2|
|[cmd_test_clear_replay_protection_list_entry](sl-btmesh-test#sl-btmesh-test-clear-replay-protection-list-entry)|0x22|0x2b|2|
|[cmd_test_set_replay_protection_list_diagnostics](sl-btmesh-test#sl-btmesh-test-set-replay-protection-list-diagnostics)|0x22|0x2c|1|
|[cmd_test_get_default_ttl](sl-btmesh-test#sl-btmesh-test-get-default-ttl)|0x22|0x2e|0|
|[cmd_test_set_default_ttl](sl-btmesh-test#sl-btmesh-test-set-default-ttl)|0x22|0x2f|1|
|[cmd_test_get_gatt_proxy](sl-btmesh-test#sl-btmesh-test-get-gatt-proxy)|0x22|0x30|0|
|[cmd_test_set_gatt_proxy](sl-btmesh-test#sl-btmesh-test-set-gatt-proxy)|0x22|0x31|1|
|[cmd_test_get_identity](sl-btmesh-test#sl-btmesh-test-get-identity)|0x22|0x32|2|
|[cmd_test_set_identity](sl-btmesh-test#sl-btmesh-test-set-identity)|0x22|0x33|3|
|[cmd_test_get_friend](sl-btmesh-test#sl-btmesh-test-get-friend)|0x22|0x34|0|
|[cmd_test_set_friend](sl-btmesh-test#sl-btmesh-test-set-friend)|0x22|0x35|1|
|[cmd_test_get_beacon](sl-btmesh-test#sl-btmesh-test-get-beacon)|0x22|0x36|0|
|[cmd_test_set_beacon](sl-btmesh-test#sl-btmesh-test-set-beacon)|0x22|0x37|1|
|[cmd_test_get_private_identity](sl-btmesh-test#sl-btmesh-test-get-private-identity)|0x22|0x38|2|
|[cmd_test_set_private_identity](sl-btmesh-test#sl-btmesh-test-set-private-identity)|0x22|0x39|3|
|[cmd_test_set_adv_provisioning_bearer_timing](sl-btmesh-test#sl-btmesh-test-set-adv-provisioning-bearer-timing)|0x22|0x3a|4|
|[cmd_test_update_keyrefresh_phase](sl-btmesh-test#sl-btmesh-test-update-keyrefresh-phase)|0x22|0x3b|2|
|[cmd_test_send_private_beacons](sl-btmesh-test#sl-btmesh-test-send-private-beacons)|0x22|0x3c|0|
|[cmd_test_set_adv_params](sl-btmesh-test#sl-btmesh-test-set-adv-params)|0x22|0x3d|6|
|[cmd_test_set_scan_params](sl-btmesh-test#sl-btmesh-test-set-scan-params)|0x22|0x3e|4|
|[cmd_test_adv_use_random_address](sl-btmesh-test#sl-btmesh-test-adv-use-random-address)|0x22|0x3f|1|
|Events|
|[evt_test_local_heartbeat_subscription_complete](sl-btmesh-evt-test-local-heartbeat-subscription-complete)|0x22|0x00|4|
|[evt_test_replay_protection_list_entry_set](sl-btmesh-evt-test-replay-protection-list-entry-set)|0x22|0x01|3|
|[evt_test_replay_protection_list_entry_cleared](sl-btmesh-evt-test-replay-protection-list-entry-cleared)|0x22|0x02|2|
|[evt_test_replay_protection_list_saved](sl-btmesh-evt-test-replay-protection-list-saved)|0x22|0x03|6|
|[evt_test_replay_protection_list_full](sl-btmesh-evt-test-replay-protection-list-full)|0x22|0x04|0|
|[Bluetooth Mesh Low Power Node API](sl-btmesh-lpn)|
|Commands|
|[cmd_lpn_init](sl-btmesh-lpn#sl-btmesh-lpn-init)|0x23|0x00|0|
|[cmd_lpn_deinit](sl-btmesh-lpn#sl-btmesh-lpn-deinit)|0x23|0x01|0|
|[cmd_lpn_establish_friendship](sl-btmesh-lpn#sl-btmesh-lpn-establish-friendship)|0x23|0x03|2|
|[cmd_lpn_poll](sl-btmesh-lpn#sl-btmesh-lpn-poll)|0x23|0x04|2|
|[cmd_lpn_terminate_friendship](sl-btmesh-lpn#sl-btmesh-lpn-terminate-friendship)|0x23|0x05|2|
|[cmd_lpn_config](sl-btmesh-lpn#sl-btmesh-lpn-config)|0x23|0x06|5|
|Events|
|[evt_lpn_friendship_established](sl-btmesh-evt-lpn-friendship-established)|0x23|0x00|4|
|[evt_lpn_friendship_failed](sl-btmesh-evt-lpn-friendship-failed)|0x23|0x01|4|
|[evt_lpn_friendship_terminated](sl-btmesh-evt-lpn-friendship-terminated)|0x23|0x02|4|
|[Bluetooth Mesh Friend Node API](sl-btmesh-friend)|
|Commands|
|[cmd_friend_init](sl-btmesh-friend#sl-btmesh-friend-init)|0x24|0x00|0|
|[cmd_friend_deinit](sl-btmesh-friend#sl-btmesh-friend-deinit)|0x24|0x01|0|
|Events|
|[evt_friend_friendship_established](sl-btmesh-evt-friend-friendship-established)|0x24|0x00|4|
|[evt_friend_friendship_terminated](sl-btmesh-evt-friend-friendship-terminated)|0x24|0x01|6|
|[Bluetooth Mesh GATT Proxy Client](sl-btmesh-proxy-client)|
|Commands|
|[Bluetooth Mesh GATT Proxy Server](sl-btmesh-proxy-server)|
|Commands|
|[Bluetooth Mesh Configuration Client Model](sl-btmesh-config-client)|
|Commands|
|[cmd_config_client_cancel_request](sl-btmesh-config-client#sl-btmesh-config-client-cancel-request)|0x27|0x00|4|
|[cmd_config_client_get_request_status](sl-btmesh-config-client#sl-btmesh-config-client-get-request-status)|0x27|0x01|4|
|[cmd_config_client_get_default_timeout](sl-btmesh-config-client#sl-btmesh-config-client-get-default-timeout)|0x27|0x2e|0|
|[cmd_config_client_set_default_timeout](sl-btmesh-config-client#sl-btmesh-config-client-set-default-timeout)|0x27|0x2f|8|
|[cmd_config_client_add_netkey](sl-btmesh-config-client#sl-btmesh-config-client-add-netkey)|0x27|0x02|6|
|[cmd_config_client_remove_netkey](sl-btmesh-config-client#sl-btmesh-config-client-remove-netkey)|0x27|0x03|6|
|[cmd_config_client_list_netkeys](sl-btmesh-config-client#sl-btmesh-config-client-list-netkeys)|0x27|0x04|4|
|[cmd_config_client_add_appkey](sl-btmesh-config-client#sl-btmesh-config-client-add-appkey)|0x27|0x05|8|
|[cmd_config_client_remove_appkey](sl-btmesh-config-client#sl-btmesh-config-client-remove-appkey)|0x27|0x06|8|
|[cmd_config_client_list_appkeys](sl-btmesh-config-client#sl-btmesh-config-client-list-appkeys)|0x27|0x07|6|
|[cmd_config_client_bind_model](sl-btmesh-config-client#sl-btmesh-config-client-bind-model)|0x27|0x08|11|
|[cmd_config_client_unbind_model](sl-btmesh-config-client#sl-btmesh-config-client-unbind-model)|0x27|0x09|11|
|[cmd_config_client_list_bindings](sl-btmesh-config-client#sl-btmesh-config-client-list-bindings)|0x27|0x0a|9|
|[cmd_config_client_get_model_pub](sl-btmesh-config-client#sl-btmesh-config-client-get-model-pub)|0x27|0x0b|9|
|[cmd_config_client_set_model_pub](sl-btmesh-config-client#sl-btmesh-config-client-set-model-pub)|0x27|0x0c|22|
|[cmd_config_client_set_model_pub_va](sl-btmesh-config-client#sl-btmesh-config-client-set-model-pub-va)|0x27|0x0d|36|
|[cmd_config_client_add_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-add-model-sub)|0x27|0x0e|11|
|[cmd_config_client_add_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-add-model-sub-va)|0x27|0x0f|25|
|[cmd_config_client_remove_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-remove-model-sub)|0x27|0x10|11|
|[cmd_config_client_remove_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-remove-model-sub-va)|0x27|0x11|25|
|[cmd_config_client_set_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-set-model-sub)|0x27|0x12|11|
|[cmd_config_client_set_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-set-model-sub-va)|0x27|0x13|25|
|[cmd_config_client_clear_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-clear-model-sub)|0x27|0x14|9|
|[cmd_config_client_list_subs](sl-btmesh-config-client#sl-btmesh-config-client-list-subs)|0x27|0x15|9|
|[cmd_config_client_get_heartbeat_pub](sl-btmesh-config-client#sl-btmesh-config-client-get-heartbeat-pub)|0x27|0x16|4|
|[cmd_config_client_set_heartbeat_pub](sl-btmesh-config-client#sl-btmesh-config-client-set-heartbeat-pub)|0x27|0x17|13|
|[cmd_config_client_get_heartbeat_sub](sl-btmesh-config-client#sl-btmesh-config-client-get-heartbeat-sub)|0x27|0x19|4|
|[cmd_config_client_set_heartbeat_sub](sl-btmesh-config-client#sl-btmesh-config-client-set-heartbeat-sub)|0x27|0x1a|9|
|[cmd_config_client_get_beacon](sl-btmesh-config-client#sl-btmesh-config-client-get-beacon)|0x27|0x1b|4|
|[cmd_config_client_set_beacon](sl-btmesh-config-client#sl-btmesh-config-client-set-beacon)|0x27|0x1c|5|
|[cmd_config_client_get_default_ttl](sl-btmesh-config-client#sl-btmesh-config-client-get-default-ttl)|0x27|0x1d|4|
|[cmd_config_client_set_default_ttl](sl-btmesh-config-client#sl-btmesh-config-client-set-default-ttl)|0x27|0x1e|5|
|[cmd_config_client_get_gatt_proxy](sl-btmesh-config-client#sl-btmesh-config-client-get-gatt-proxy)|0x27|0x1f|4|
|[cmd_config_client_set_gatt_proxy](sl-btmesh-config-client#sl-btmesh-config-client-set-gatt-proxy)|0x27|0x20|5|
|[cmd_config_client_get_relay](sl-btmesh-config-client#sl-btmesh-config-client-get-relay)|0x27|0x21|4|
|[cmd_config_client_set_relay](sl-btmesh-config-client#sl-btmesh-config-client-set-relay)|0x27|0x22|8|
|[cmd_config_client_get_network_transmit](sl-btmesh-config-client#sl-btmesh-config-client-get-network-transmit)|0x27|0x23|4|
|[cmd_config_client_set_network_transmit](sl-btmesh-config-client#sl-btmesh-config-client-set-network-transmit)|0x27|0x24|7|
|[cmd_config_client_get_identity](sl-btmesh-config-client#sl-btmesh-config-client-get-identity)|0x27|0x25|6|
|[cmd_config_client_set_identity](sl-btmesh-config-client#sl-btmesh-config-client-set-identity)|0x27|0x26|7|
|[cmd_config_client_get_friend](sl-btmesh-config-client#sl-btmesh-config-client-get-friend)|0x27|0x27|4|
|[cmd_config_client_set_friend](sl-btmesh-config-client#sl-btmesh-config-client-set-friend)|0x27|0x28|5|
|[cmd_config_client_get_key_refresh_phase](sl-btmesh-config-client#sl-btmesh-config-client-get-key-refresh-phase)|0x27|0x29|6|
|[cmd_config_client_get_lpn_polltimeout](sl-btmesh-config-client#sl-btmesh-config-client-get-lpn-polltimeout)|0x27|0x2b|6|
|[cmd_config_client_get_dcd](sl-btmesh-config-client#sl-btmesh-config-client-get-dcd)|0x27|0x2c|5|
|[cmd_config_client_reset_node](sl-btmesh-config-client#sl-btmesh-config-client-reset-node)|0x27|0x2d|4|
|[cmd_config_client_set_request_timeout_for_node](sl-btmesh-config-client#sl-btmesh-config-client-set-request-timeout-for-node)|0x27|0x30|4|
|[cmd_config_client_prepare_key_refresh](sl-btmesh-config-client#sl-btmesh-config-client-prepare-key-refresh)|0x27|0x31|17|
|Events|
|[evt_config_client_request_modified](sl-btmesh-evt-config-client-request-modified)|0x27|0x00|4|
|[evt_config_client_netkey_status](sl-btmesh-evt-config-client-netkey-status)|0x27|0x01|6|
|[evt_config_client_netkey_list](sl-btmesh-evt-config-client-netkey-list)|0x27|0x02|5|
|[evt_config_client_netkey_list_end](sl-btmesh-evt-config-client-netkey-list-end)|0x27|0x03|6|
|[evt_config_client_appkey_status](sl-btmesh-evt-config-client-appkey-status)|0x27|0x04|6|
|[evt_config_client_appkey_list](sl-btmesh-evt-config-client-appkey-list)|0x27|0x05|5|
|[evt_config_client_appkey_list_end](sl-btmesh-evt-config-client-appkey-list-end)|0x27|0x06|6|
|[evt_config_client_binding_status](sl-btmesh-evt-config-client-binding-status)|0x27|0x07|6|
|[evt_config_client_bindings_list](sl-btmesh-evt-config-client-bindings-list)|0x27|0x08|5|
|[evt_config_client_bindings_list_end](sl-btmesh-evt-config-client-bindings-list-end)|0x27|0x09|6|
|[evt_config_client_model_pub_status](sl-btmesh-evt-config-client-model-pub-status)|0x27|0x0a|19|
|[evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)|0x27|0x0b|6|
|[evt_config_client_subs_list](sl-btmesh-evt-config-client-subs-list)|0x27|0x0c|5|
|[evt_config_client_subs_list_end](sl-btmesh-evt-config-client-subs-list-end)|0x27|0x0d|6|
|[evt_config_client_heartbeat_pub_status](sl-btmesh-evt-config-client-heartbeat-pub-status)|0x27|0x0e|15|
|[evt_config_client_heartbeat_sub_status](sl-btmesh-evt-config-client-heartbeat-sub-status)|0x27|0x0f|14|
|[evt_config_client_beacon_status](sl-btmesh-evt-config-client-beacon-status)|0x27|0x10|7|
|[evt_config_client_default_ttl_status](sl-btmesh-evt-config-client-default-ttl-status)|0x27|0x11|7|
|[evt_config_client_gatt_proxy_status](sl-btmesh-evt-config-client-gatt-proxy-status)|0x27|0x12|7|
|[evt_config_client_relay_status](sl-btmesh-evt-config-client-relay-status)|0x27|0x13|10|
|[evt_config_client_network_transmit_status](sl-btmesh-evt-config-client-network-transmit-status)|0x27|0x14|9|
|[evt_config_client_identity_status](sl-btmesh-evt-config-client-identity-status)|0x27|0x15|7|
|[evt_config_client_friend_status](sl-btmesh-evt-config-client-friend-status)|0x27|0x16|7|
|[evt_config_client_key_refresh_phase_status](sl-btmesh-evt-config-client-key-refresh-phase-status)|0x27|0x17|9|
|[evt_config_client_lpn_polltimeout_status](sl-btmesh-evt-config-client-lpn-polltimeout-status)|0x27|0x18|10|
|[evt_config_client_dcd_data](sl-btmesh-evt-config-client-dcd-data)|0x27|0x19|6|
|[evt_config_client_dcd_data_end](sl-btmesh-evt-config-client-dcd-data-end)|0x27|0x1a|6|
|[evt_config_client_reset_status](sl-btmesh-evt-config-client-reset-status)|0x27|0x1b|6|
|[evt_config_client_obo_ack_received](sl-btmesh-evt-config-client-obo-ack-received)|0x27|0x1c|4|
|[Bluetooth Mesh BLOB Transfer Client Model](sl-btmesh-mbt-client)|
|Commands|
|[cmd_mbt_client_init](sl-btmesh-mbt-client#sl-btmesh-mbt-client-init)|0x28|0x09|8|
|[cmd_mbt_client_deinit](sl-btmesh-mbt-client#sl-btmesh-mbt-client-deinit)|0x28|0x07|2|
|[cmd_mbt_client_setup](sl-btmesh-mbt-client#sl-btmesh-mbt-client-setup)|0x28|0x00|41|
|[cmd_mbt_client_query_information](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-information)|0x28|0x01|2|
|[cmd_mbt_client_get_server_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-get-server-status)|0x28|0x0d|4|
|[cmd_mbt_client_add_server](sl-btmesh-mbt-client#sl-btmesh-mbt-client-add-server)|0x28|0x0e|4|
|[cmd_mbt_client_configure_throttle](sl-btmesh-mbt-client#sl-btmesh-mbt-client-configure-throttle)|0x28|0x0f|5|
|[cmd_mbt_client_start_transfer](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-transfer)|0x28|0x02|4|
|[cmd_mbt_client_start_block](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-block)|0x28|0x03|4|
|[cmd_mbt_client_send_chunk_request_rsp](sl-btmesh-mbt-client#sl-btmesh-mbt-client-send-chunk-request-rsp)|0x28|0x04|3|
|[cmd_mbt_client_query_block_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-block-status)|0x28|0x05|2|
|[cmd_mbt_client_get_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-get-status)|0x28|0x06|2|
|[cmd_mbt_client_get_transfer_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-get-transfer-status)|0x28|0x0a|23|
|[cmd_mbt_client_cancel_transfer](sl-btmesh-mbt-client#sl-btmesh-mbt-client-cancel-transfer)|0x28|0x0b|2|
|[cmd_mbt_client_abort](sl-btmesh-mbt-client#sl-btmesh-mbt-client-abort)|0x28|0x0c|2|
|Events|
|[evt_mbt_client_server_information_status](sl-btmesh-evt-mbt-client-server-information-status)|0x28|0x00|10|
|[evt_mbt_client_query_information_complete](sl-btmesh-evt-mbt-client-query-information-complete)|0x28|0x04|10|
|[evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status)|0x28|0x01|20|
|[evt_mbt_client_start_transfer_complete](sl-btmesh-evt-mbt-client-start-transfer-complete)|0x28|0x05|2|
|[evt_mbt_client_server_block_status](sl-btmesh-evt-mbt-client-server-block-status)|0x28|0x03|6|
|[evt_mbt_client_start_block_complete](sl-btmesh-evt-mbt-client-start-block-complete)|0x28|0x06|8|
|[evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request)|0x28|0x07|8|
|[evt_mbt_client_server_partial_block_report](sl-btmesh-evt-mbt-client-server-partial-block-report)|0x28|0x0c|5|
|[evt_mbt_client_send_chunks_complete](sl-btmesh-evt-mbt-client-send-chunks-complete)|0x28|0x08|2|
|[evt_mbt_client_query_block_status_complete](sl-btmesh-evt-mbt-client-query-block-status-complete)|0x28|0x09|4|
|[evt_mbt_client_tx_complete](sl-btmesh-evt-mbt-client-tx-complete)|0x28|0x0a|2|
|[evt_mbt_client_server_failed](sl-btmesh-evt-mbt-client-server-failed)|0x28|0x0b|6|
|[evt_mbt_client_transfer_complete](sl-btmesh-evt-mbt-client-transfer-complete)|0x28|0x0d|2|
|[Bluetooth Mesh BLOB Transfer Server Model](sl-btmesh-mbt-server)|
|Commands|
|[cmd_mbt_server_init](sl-btmesh-mbt-server#sl-btmesh-mbt-server-init)|0x29|0x02|19|
|[cmd_mbt_server_deinit](sl-btmesh-mbt-server#sl-btmesh-mbt-server-deinit)|0x29|0x09|2|
|[cmd_mbt_server_start](sl-btmesh-mbt-server#sl-btmesh-mbt-server-start)|0x29|0x00|13|
|[cmd_mbt_server_get_transfer_status](sl-btmesh-mbt-server#sl-btmesh-mbt-server-get-transfer-status)|0x29|0x01|2|
|[cmd_mbt_server_transfer_complete](sl-btmesh-mbt-server#sl-btmesh-mbt-server-transfer-complete)|0x29|0x03|2|
|[cmd_mbt_server_abort](sl-btmesh-mbt-server#sl-btmesh-mbt-server-abort)|0x29|0x04|2|
|[cmd_mbt_server_set_pull_mode_parameters](sl-btmesh-mbt-server#sl-btmesh-mbt-server-set-pull-mode-parameters)|0x29|0x05|6|
|[cmd_mbt_server_transfer_start_rsp](sl-btmesh-mbt-server#sl-btmesh-mbt-server-transfer-start-rsp)|0x29|0x06|3|
|[cmd_mbt_server_enable_block_start_req](sl-btmesh-mbt-server#sl-btmesh-mbt-server-enable-block-start-req)|0x29|0x07|2|
|[cmd_mbt_server_block_start_rsp](sl-btmesh-mbt-server#sl-btmesh-mbt-server-block-start-rsp)|0x29|0x08|3|
|Events|
|[evt_mbt_server_state_changed](sl-btmesh-evt-mbt-server-state-changed)|0x29|0x06|23|
|[evt_mbt_server_transfer_start_req](sl-btmesh-evt-mbt-server-transfer-start-req)|0x29|0x00|18|
|[evt_mbt_server_block_start](sl-btmesh-evt-mbt-server-block-start)|0x29|0x01|18|
|[evt_mbt_server_chunk](sl-btmesh-evt-mbt-server-chunk)|0x29|0x03|15|
|[evt_mbt_server_block_complete](sl-btmesh-evt-mbt-server-block-complete)|0x29|0x04|16|
|[evt_mbt_server_transfer_cancel](sl-btmesh-evt-mbt-server-transfer-cancel)|0x29|0x07|12|
|[evt_mbt_server_partial_block_report_tx_complete](sl-btmesh-evt-mbt-server-partial-block-report-tx-complete)|0x29|0x08|5|
|[Bluetooth Mesh Sensor Server Model](sl-btmesh-sensor-server)|
|Commands|
|[cmd_sensor_server_init](sl-btmesh-sensor-server#sl-btmesh-sensor-server-init)|0x47|0x00|3|
|[cmd_sensor_server_deinit](sl-btmesh-sensor-server#sl-btmesh-sensor-server-deinit)|0x47|0x01|2|
|[cmd_sensor_server_send_descriptor_status](sl-btmesh-sensor-server#sl-btmesh-sensor-server-send-descriptor-status)|0x47|0x02|8|
|[cmd_sensor_server_send_status](sl-btmesh-sensor-server#sl-btmesh-sensor-server-send-status)|0x47|0x03|8|
|[cmd_sensor_server_send_column_status](sl-btmesh-sensor-server#sl-btmesh-sensor-server-send-column-status)|0x47|0x04|10|
|[cmd_sensor_server_send_series_status](sl-btmesh-sensor-server#sl-btmesh-sensor-server-send-series-status)|0x47|0x05|10|
|Events|
|[evt_sensor_server_get_request](sl-btmesh-evt-sensor-server-get-request)|0x47|0x01|11|
|[evt_sensor_server_get_column_request](sl-btmesh-evt-sensor-server-get-column-request)|0x47|0x02|12|
|[evt_sensor_server_get_series_request](sl-btmesh-evt-sensor-server-get-series-request)|0x47|0x03|12|
|[evt_sensor_server_publish](sl-btmesh-evt-sensor-server-publish)|0x47|0x04|6|
|[Bluetooth Mesh Sensor Setup Server Model](sl-btmesh-sensor-setup-server)|
|Commands|
|[cmd_sensor_setup_server_send_cadence_status](sl-btmesh-sensor-setup-server#sl-btmesh-sensor-setup-server-send-cadence-status)|0x48|0x00|10|
|[cmd_sensor_setup_server_send_settings_status](sl-btmesh-sensor-setup-server#sl-btmesh-sensor-setup-server-send-settings-status)|0x48|0x01|10|
|[cmd_sensor_setup_server_send_setting_status](sl-btmesh-sensor-setup-server#sl-btmesh-sensor-setup-server-send-setting-status)|0x48|0x02|12|
|Events|
|[evt_sensor_setup_server_get_cadence_request](sl-btmesh-evt-sensor-setup-server-get-cadence-request)|0x48|0x00|11|
|[evt_sensor_setup_server_set_cadence_request](sl-btmesh-evt-sensor-setup-server-set-cadence-request)|0x48|0x01|14|
|[evt_sensor_setup_server_get_settings_request](sl-btmesh-evt-sensor-setup-server-get-settings-request)|0x48|0x02|11|
|[evt_sensor_setup_server_get_setting_request](sl-btmesh-evt-sensor-setup-server-get-setting-request)|0x48|0x03|13|
|[evt_sensor_setup_server_set_setting_request](sl-btmesh-evt-sensor-setup-server-set-setting-request)|0x48|0x04|14|
|[evt_sensor_setup_server_publish](sl-btmesh-evt-sensor-setup-server-publish)|0x48|0x05|6|
|[Bluetooth Mesh Sensor Client Model](sl-btmesh-sensor-client)|
|Commands|
|[cmd_sensor_client_init](sl-btmesh-sensor-client#sl-btmesh-sensor-client-init)|0x49|0x00|0|
|[cmd_sensor_client_deinit](sl-btmesh-sensor-client#sl-btmesh-sensor-client-deinit)|0x49|0x01|0|
|[cmd_sensor_client_get_descriptor](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-descriptor)|0x49|0x02|9|
|[cmd_sensor_client_get](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get)|0x49|0x03|9|
|[cmd_sensor_client_get_column](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-column)|0x49|0x04|10|
|[cmd_sensor_client_get_series](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-series)|0x49|0x05|10|
|[cmd_sensor_client_get_cadence](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-cadence)|0x49|0x06|9|
|[cmd_sensor_client_set_cadence](sl-btmesh-sensor-client#sl-btmesh-sensor-client-set-cadence)|0x49|0x07|10|
|[cmd_sensor_client_get_settings](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-settings)|0x49|0x08|9|
|[cmd_sensor_client_get_setting](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-setting)|0x49|0x09|11|
|[cmd_sensor_client_set_setting](sl-btmesh-sensor-client#sl-btmesh-sensor-client-set-setting)|0x49|0x0a|12|
|Events|
|[evt_sensor_client_descriptor_status](sl-btmesh-evt-sensor-client-descriptor-status)|0x49|0x00|10|
|[evt_sensor_client_cadence_status](sl-btmesh-evt-sensor-client-cadence-status)|0x49|0x01|12|
|[evt_sensor_client_settings_status](sl-btmesh-evt-sensor-client-settings-status)|0x49|0x02|12|
|[evt_sensor_client_setting_status](sl-btmesh-evt-sensor-client-setting-status)|0x49|0x03|14|
|[evt_sensor_client_status](sl-btmesh-evt-sensor-client-status)|0x49|0x04|10|
|[evt_sensor_client_column_status](sl-btmesh-evt-sensor-client-column-status)|0x49|0x05|12|
|[evt_sensor_client_series_status](sl-btmesh-evt-sensor-client-series-status)|0x49|0x06|12|
|[evt_sensor_client_publish](sl-btmesh-evt-sensor-client-publish)|0x49|0x07|6|
|[Bluetooth Mesh Firmware Update Client Model](sl-btmesh-fw-update-client)|
|Commands|
|[cmd_fw_update_client_init](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-init)|0x4a|0x00|2|
|[cmd_fw_update_client_deinit](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-deinit)|0x4a|0x01|2|
|[cmd_fw_update_client_get_info](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-get-info)|0x4a|0x08|25|
|[cmd_fw_update_client_get_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-get-update)|0x4a|0x09|23|
|[cmd_fw_update_client_start_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-start-update)|0x4a|0x0a|36|
|[cmd_fw_update_client_cancel_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-cancel-update)|0x4a|0x0b|23|
|[cmd_fw_update_client_apply_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-apply-update)|0x4a|0x0c|23|
|[cmd_fw_update_client_check_metadata](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-check-metadata)|0x4a|0x0d|25|
|Events|
|[evt_fw_update_client_info_status_current_fwid](sl-btmesh-evt-fw-update-client-info-status-current-fwid)|0x4a|0x00|7|
|[evt_fw_update_client_info_status_update_uri](sl-btmesh-evt-fw-update-client-info-status-update-uri)|0x4a|0x01|7|
|[evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status)|0x4a|0x02|19|
|[evt_fw_update_client_metadata_status](sl-btmesh-evt-fw-update-client-metadata-status)|0x4a|0x0a|7|
|[Bluetooth Mesh Light Control Client Model](sl-btmesh-lc-client)|
|Commands|
|[cmd_lc_client_init](sl-btmesh-lc-client#sl-btmesh-lc-client-init)|0x4c|0x00|2|
|[cmd_lc_client_get_mode](sl-btmesh-lc-client#sl-btmesh-lc-client-get-mode)|0x4c|0x01|6|
|[cmd_lc_client_set_mode](sl-btmesh-lc-client#sl-btmesh-lc-client-set-mode)|0x4c|0x02|8|
|[cmd_lc_client_get_om](sl-btmesh-lc-client#sl-btmesh-lc-client-get-om)|0x4c|0x04|6|
|[cmd_lc_client_set_om](sl-btmesh-lc-client#sl-btmesh-lc-client-set-om)|0x4c|0x05|8|
|[cmd_lc_client_get_light_onoff](sl-btmesh-lc-client#sl-btmesh-lc-client-get-light-onoff)|0x4c|0x07|6|
|[cmd_lc_client_set_light_onoff](sl-btmesh-lc-client#sl-btmesh-lc-client-set-light-onoff)|0x4c|0x08|15|
|[cmd_lc_client_get_property](sl-btmesh-lc-client#sl-btmesh-lc-client-get-property)|0x4c|0x09|8|
|[cmd_lc_client_set_property](sl-btmesh-lc-client#sl-btmesh-lc-client-set-property)|0x4c|0x0a|10|
|Events|
|[evt_lc_client_mode_status](sl-btmesh-evt-lc-client-mode-status)|0x4c|0x00|9|
|[evt_lc_client_om_status](sl-btmesh-evt-lc-client-om-status)|0x4c|0x01|9|
|[evt_lc_client_light_onoff_status](sl-btmesh-evt-lc-client-light-onoff-status)|0x4c|0x02|14|
|[evt_lc_client_property_status](sl-btmesh-evt-lc-client-property-status)|0x4c|0x03|11|
|[Bluetooth Mesh Light Control Server Model](sl-btmesh-lc-server)|
|Commands|
|[cmd_lc_server_init](sl-btmesh-lc-server#sl-btmesh-lc-server-init)|0x4d|0x00|2|
|[cmd_lc_server_deinit](sl-btmesh-lc-server#sl-btmesh-lc-server-deinit)|0x4d|0x01|2|
|[cmd_lc_server_update_mode](sl-btmesh-lc-server#sl-btmesh-lc-server-update-mode)|0x4d|0x02|3|
|[cmd_lc_server_update_om](sl-btmesh-lc-server#sl-btmesh-lc-server-update-om)|0x4d|0x03|3|
|[cmd_lc_server_update_light_onoff](sl-btmesh-lc-server#sl-btmesh-lc-server-update-light-onoff)|0x4d|0x04|7|
|[cmd_lc_server_init_all_properties](sl-btmesh-lc-server#sl-btmesh-lc-server-init-all-properties)|0x4d|0x05|2|
|[cmd_lc_server_set_publish_mask](sl-btmesh-lc-server#sl-btmesh-lc-server-set-publish-mask)|0x4d|0x06|5|
|[cmd_lc_server_set_regulator_interval](sl-btmesh-lc-server#sl-btmesh-lc-server-set-regulator-interval)|0x4d|0x07|3|
|[cmd_lc_server_set_event_mask](sl-btmesh-lc-server#sl-btmesh-lc-server-set-event-mask)|0x4d|0x08|5|
|[cmd_lc_server_get_lc_state](sl-btmesh-lc-server#sl-btmesh-lc-server-get-lc-state)|0x4d|0x09|2|
|[cmd_lc_server_set_regulator_mode](sl-btmesh-lc-server#sl-btmesh-lc-server-set-regulator-mode)|0x4d|0x0a|3|
|[cmd_lc_server_set_sensor_timeout](sl-btmesh-lc-server#sl-btmesh-lc-server-set-sensor-timeout)|0x4d|0x0b|6|
|Events|
|[evt_lc_server_mode_updated](sl-btmesh-evt-lc-server-mode-updated)|0x4d|0x00|10|
|[evt_lc_server_om_updated](sl-btmesh-evt-lc-server-om-updated)|0x4d|0x01|9|
|[evt_lc_server_light_onoff_updated](sl-btmesh-evt-lc-server-light-onoff-updated)|0x4d|0x02|13|
|[evt_lc_server_occupancy_updated](sl-btmesh-evt-lc-server-occupancy-updated)|0x4d|0x03|9|
|[evt_lc_server_ambient_lux_level_updated](sl-btmesh-evt-lc-server-ambient-lux-level-updated)|0x4d|0x04|12|
|[evt_lc_server_linear_output_updated](sl-btmesh-evt-lc-server-linear-output-updated)|0x4d|0x05|4|
|[evt_lc_server_state_updated](sl-btmesh-evt-lc-server-state-updated)|0x4d|0x06|7|
|[evt_lc_server_regulator_debug_info](sl-btmesh-evt-lc-server-regulator-debug-info)|0x4d|0x07|6|
|[Bluetooth Mesh Light Control Setup Server Model](sl-btmesh-lc-setup-server)|
|Commands|
|[cmd_lc_setup_server_update_property](sl-btmesh-lc-setup-server#sl-btmesh-lc-setup-server-update-property)|0x4e|0x00|5|
|Events|
|[evt_lc_setup_server_set_property](sl-btmesh-evt-lc-setup-server-set-property)|0x4e|0x00|11|
|[Bluetooth Mesh Scene Client Model](sl-btmesh-scene-client)|
|Commands|
|[cmd_scene_client_init](sl-btmesh-scene-client#sl-btmesh-scene-client-init)|0x4f|0x00|2|
|[cmd_scene_client_get](sl-btmesh-scene-client#sl-btmesh-scene-client-get)|0x4f|0x01|6|
|[cmd_scene_client_get_register](sl-btmesh-scene-client#sl-btmesh-scene-client-get-register)|0x4f|0x02|6|
|[cmd_scene_client_recall](sl-btmesh-scene-client#sl-btmesh-scene-client-recall)|0x4f|0x03|16|
|[cmd_scene_client_store](sl-btmesh-scene-client#sl-btmesh-scene-client-store)|0x4f|0x04|9|
|[cmd_scene_client_delete](sl-btmesh-scene-client#sl-btmesh-scene-client-delete)|0x4f|0x05|9|
|[cmd_scene_client_deinit](sl-btmesh-scene-client#sl-btmesh-scene-client-deinit)|0x4f|0x06|2|
|Events|
|[evt_scene_client_status](sl-btmesh-evt-scene-client-status)|0x4f|0x00|17|
|[evt_scene_client_register_status](sl-btmesh-evt-scene-client-register-status)|0x4f|0x01|12|
|[Bluetooth Mesh Scene Server Model](sl-btmesh-scene-server)|
|Commands|
|[cmd_scene_server_init](sl-btmesh-scene-server#sl-btmesh-scene-server-init)|0x50|0x00|2|
|[cmd_scene_server_deinit](sl-btmesh-scene-server#sl-btmesh-scene-server-deinit)|0x50|0x01|2|
|[cmd_scene_server_reset_register](sl-btmesh-scene-server#sl-btmesh-scene-server-reset-register)|0x50|0x02|2|
|[cmd_scene_server_enable_compact_recall_events](sl-btmesh-scene-server#sl-btmesh-scene-server-enable-compact-recall-events)|0x50|0x03|0|
|Events|
|[evt_scene_server_get](sl-btmesh-evt-scene-server-get)|0x50|0x01|8|
|[evt_scene_server_register_get](sl-btmesh-evt-scene-server-register-get)|0x50|0x02|8|
|[evt_scene_server_recall](sl-btmesh-evt-scene-server-recall)|0x50|0x03|14|
|[evt_scene_server_publish](sl-btmesh-evt-scene-server-publish)|0x50|0x04|6|
|[evt_scene_server_compact_recall](sl-btmesh-evt-scene-server-compact-recall)|0x50|0x05|1|
|[Bluetooth Mesh Scene Setup Server Model](sl-btmesh-scene-setup-server)|
|Commands|
|[cmd_scene_setup_server_init](sl-btmesh-scene-setup-server#sl-btmesh-scene-setup-server-init)|0x51|0x00|2|
|[cmd_scene_setup_server_deinit](sl-btmesh-scene-setup-server#sl-btmesh-scene-setup-server-deinit)|0x51|0x01|2|
|Events|
|[evt_scene_setup_server_store](sl-btmesh-evt-scene-setup-server-store)|0x51|0x00|10|
|[evt_scene_setup_server_delete](sl-btmesh-evt-scene-setup-server-delete)|0x51|0x01|10|
|[evt_scene_setup_server_publish](sl-btmesh-evt-scene-setup-server-publish)|0x51|0x02|6|
|[Bluetooth Mesh Scheduler Client Model](sl-btmesh-scheduler-client)|
|Commands|
|[cmd_scheduler_client_init](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-init)|0x54|0x00|2|
|[cmd_scheduler_client_deinit](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-deinit)|0x54|0x01|2|
|[cmd_scheduler_client_get](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-get)|0x54|0x02|6|
|[cmd_scheduler_client_get_action](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-get-action)|0x54|0x03|7|
|[cmd_scheduler_client_set_action](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-set-action)|0x54|0x04|23|
|Events|
|[evt_scheduler_client_status](sl-btmesh-evt-scheduler-client-status)|0x54|0x00|10|
|[evt_scheduler_client_action_status](sl-btmesh-evt-scheduler-client-action-status)|0x54|0x01|24|
|[Bluetooth Mesh Scheduler Server Model](sl-btmesh-scheduler-server)|
|Commands|
|[cmd_scheduler_server_init](sl-btmesh-scheduler-server#sl-btmesh-scheduler-server-init)|0x55|0x00|2|
|[cmd_scheduler_server_deinit](sl-btmesh-scheduler-server#sl-btmesh-scheduler-server-deinit)|0x55|0x01|2|
|[cmd_scheduler_server_get](sl-btmesh-scheduler-server#sl-btmesh-scheduler-server-get)|0x55|0x02|2|
|[cmd_scheduler_server_get_action](sl-btmesh-scheduler-server#sl-btmesh-scheduler-server-get-action)|0x55|0x03|3|
|[cmd_scheduler_server_set_action](sl-btmesh-scheduler-server#sl-btmesh-scheduler-server-set-action)|0x55|0x04|18|
|Events|
|[evt_scheduler_server_action_changed](sl-btmesh-evt-scheduler-server-action-changed)|0x55|0x01|18|
|[evt_scheduler_server_scene_changed](sl-btmesh-evt-scheduler-server-scene-changed)|0x55|0x02|8|
|[evt_scheduler_server_action_triggered](sl-btmesh-evt-scheduler-server-action-triggered)|0x55|0x03|10|
|[Bluetooth Mesh Firmware Update Server Model](sl-btmesh-fw-update-server)|
|Commands|
|[cmd_fw_update_server_init](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-init)|0x57|0x00|4|
|[cmd_fw_update_server_deinit](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-deinit)|0x57|0x01|2|
|[cmd_fw_update_server_check_fw_metadata_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-check-fw-metadata-rsp)|0x57|0x02|5|
|[cmd_fw_update_server_update_start_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-start-rsp)|0x57|0x03|4|
|[cmd_fw_update_server_verify_fw_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-verify-fw-rsp)|0x57|0x04|3|
|[cmd_fw_update_server_distributor_self_update_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-distributor-self-update-rsp)|0x57|0x05|4|
|Events|
|[evt_fw_update_server_check_fw_metadata_req](sl-btmesh-evt-fw-update-server-check-fw-metadata-req)|0x57|0x00|6|
|[evt_fw_update_server_update_start_req](sl-btmesh-evt-fw-update-server-update-start-req)|0x57|0x03|14|
|[evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req)|0x57|0x04|2|
|[evt_fw_update_server_apply](sl-btmesh-evt-fw-update-server-apply)|0x57|0x05|4|
|[evt_fw_update_server_update_cancelled](sl-btmesh-evt-fw-update-server-update-cancelled)|0x57|0x06|4|
|[evt_fw_update_server_distributor_self_update_req](sl-btmesh-evt-fw-update-server-distributor-self-update-req)|0x57|0x07|7|
|[Bluetooth Mesh Time Server Model](sl-btmesh-time-server)|
|Commands|
|[cmd_time_server_init](sl-btmesh-time-server#sl-btmesh-time-server-init)|0x52|0x00|2|
|[cmd_time_server_deinit](sl-btmesh-time-server#sl-btmesh-time-server-deinit)|0x52|0x01|2|
|[cmd_time_server_get_time](sl-btmesh-time-server#sl-btmesh-time-server-get-time)|0x52|0x02|2|
|[cmd_time_server_set_time](sl-btmesh-time-server#sl-btmesh-time-server-set-time)|0x52|0x03|19|
|[cmd_time_server_get_time_zone_offset_new](sl-btmesh-time-server#sl-btmesh-time-server-get-time-zone-offset-new)|0x52|0x04|2|
|[cmd_time_server_set_time_zone_offset_new](sl-btmesh-time-server#sl-btmesh-time-server-set-time-zone-offset-new)|0x52|0x05|12|
|[cmd_time_server_get_tai_utc_delta_new](sl-btmesh-time-server#sl-btmesh-time-server-get-tai-utc-delta-new)|0x52|0x06|2|
|[cmd_time_server_set_tai_utc_delta_new](sl-btmesh-time-server#sl-btmesh-time-server-set-tai-utc-delta-new)|0x52|0x07|14|
|[cmd_time_server_get_time_role](sl-btmesh-time-server#sl-btmesh-time-server-get-time-role)|0x52|0x08|2|
|[cmd_time_server_set_time_role](sl-btmesh-time-server#sl-btmesh-time-server-set-time-role)|0x52|0x09|3|
|[cmd_time_server_get_datetime](sl-btmesh-time-server#sl-btmesh-time-server-get-datetime)|0x52|0x0a|2|
|[cmd_time_server_publish](sl-btmesh-time-server#sl-btmesh-time-server-publish)|0x52|0x0b|2|
|[cmd_time_server_status](sl-btmesh-time-server#sl-btmesh-time-server-status)|0x52|0x0c|6|
|Events|
|[evt_time_server_time_updated](sl-btmesh-evt-time-server-time-updated)|0x52|0x00|19|
|[evt_time_server_time_zone_offset_updated](sl-btmesh-evt-time-server-time-zone-offset-updated)|0x52|0x01|14|
|[evt_time_server_tai_utc_delta_updated](sl-btmesh-evt-time-server-tai-utc-delta-updated)|0x52|0x02|18|
|[evt_time_server_time_role_updated](sl-btmesh-evt-time-server-time-role-updated)|0x52|0x03|3|
|[Bluetooth Mesh Time Client Model](sl-btmesh-time-client)|
|Commands|
|[cmd_time_client_init](sl-btmesh-time-client#sl-btmesh-time-client-init)|0x53|0x00|2|
|[cmd_time_client_deinit](sl-btmesh-time-client#sl-btmesh-time-client-deinit)|0x53|0x01|2|
|[cmd_time_client_get_time](sl-btmesh-time-client#sl-btmesh-time-client-get-time)|0x53|0x02|6|
|[cmd_time_client_set_time](sl-btmesh-time-client#sl-btmesh-time-client-set-time)|0x53|0x03|23|
|[cmd_time_client_get_time_zone](sl-btmesh-time-client#sl-btmesh-time-client-get-time-zone)|0x53|0x04|6|
|[cmd_time_client_set_time_zone](sl-btmesh-time-client#sl-btmesh-time-client-set-time-zone)|0x53|0x05|16|
|[cmd_time_client_get_tai_utc_delta](sl-btmesh-time-client#sl-btmesh-time-client-get-tai-utc-delta)|0x53|0x06|6|
|[cmd_time_client_set_tai_utc_delta](sl-btmesh-time-client#sl-btmesh-time-client-set-tai-utc-delta)|0x53|0x07|18|
|[cmd_time_client_get_time_role](sl-btmesh-time-client#sl-btmesh-time-client-get-time-role)|0x53|0x08|6|
|[cmd_time_client_set_time_role](sl-btmesh-time-client#sl-btmesh-time-client-set-time-role)|0x53|0x09|7|
|Events|
|[evt_time_client_time_status](sl-btmesh-evt-time-client-time-status)|0x53|0x00|25|
|[evt_time_client_time_zone_status](sl-btmesh-evt-time-client-time-zone-status)|0x53|0x01|20|
|[evt_time_client_tai_utc_delta_status](sl-btmesh-evt-time-client-tai-utc-delta-status)|0x53|0x02|24|
|[evt_time_client_time_role_status](sl-btmesh-evt-time-client-time-role-status)|0x53|0x03|9|
|[Bluetooth Mesh Firmware Distribution Server Model](sl-btmesh-fw-dist-server)|
|Commands|
|[cmd_fw_dist_server_init](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-init)|0x58|0x00|17|
|[cmd_fw_dist_server_deinit](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-deinit)|0x58|0x01|2|
|[cmd_fw_dist_server_upload_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-upload-start-rsp)|0x58|0x02|3|
|[cmd_fw_dist_server_execute_distribution_step](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-execute-distribution-step)|0x58|0x03|2|
|[cmd_fw_dist_server_upload_oob_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-upload-oob-start-rsp)|0x58|0x08|4|
|[cmd_fw_dist_server_set_upload_oob_metadata](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-metadata)|0x58|0x09|3|
|[cmd_fw_dist_server_set_upload_oob_image_size](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-image-size)|0x58|0x0a|6|
|[cmd_fw_dist_server_set_upload_oob_progress](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-progress)|0x58|0x0b|4|
|[cmd_fw_dist_server_get_node_status_by_index](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-get-node-status-by-index)|0x58|0x0c|4|
|[cmd_fw_dist_server_get_node_status_by_address](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-get-node-status-by-address)|0x58|0x0d|4|
|[cmd_fw_dist_server_delete_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-delete-rsp)|0x58|0x0e|5|
|[cmd_fw_dist_server_dist_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-start-rsp)|0x58|0x13|4|
|[cmd_fw_dist_server_set_multicast_threshold](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-multicast-threshold)|0x58|0x14|4|
|[cmd_fw_dist_server_delete_all_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-delete-all-rsp)|0x58|0x0f|4|
|[cmd_fw_dist_server_resume_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-resume-rsp)|0x58|0x10|4|
|[cmd_fw_dist_server_configure_throttle](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-configure-throttle)|0x58|0x15|5|
|Events|
|[evt_fw_dist_server_nodes_added](sl-btmesh-evt-fw-dist-server-nodes-added)|0x58|0x00|9|
|[evt_fw_dist_server_nodes_deleted](sl-btmesh-evt-fw-dist-server-nodes-deleted)|0x58|0x01|4|
|[evt_fw_dist_server_dist_start_req](sl-btmesh-evt-fw-dist-server-dist-start-req)|0x58|0x02|29|
|[evt_fw_dist_server_dist_cancel](sl-btmesh-evt-fw-dist-server-dist-cancel)|0x58|0x03|4|
|[evt_fw_dist_server_dist_cancel_complete](sl-btmesh-evt-fw-dist-server-dist-cancel-complete)|0x58|0x04|4|
|[evt_fw_dist_server_upload_start_metadata](sl-btmesh-evt-fw-dist-server-upload-start-metadata)|0x58|0x05|5|
|[evt_fw_dist_server_upload_start_req](sl-btmesh-evt-fw-dist-server-upload-start-req)|0x58|0x06|17|
|[evt_fw_dist_server_upload_cancel](sl-btmesh-evt-fw-dist-server-upload-cancel)|0x58|0x08|4|
|[evt_fw_dist_server_dist_state_changed](sl-btmesh-evt-fw-dist-server-dist-state-changed)|0x58|0x0b|5|
|[evt_fw_dist_server_node_failed](sl-btmesh-evt-fw-dist-server-node-failed)|0x58|0x0c|9|
|[evt_fw_dist_server_upload_complete_metadata](sl-btmesh-evt-fw-dist-server-upload-complete-metadata)|0x58|0x0d|5|
|[evt_fw_dist_server_upload_complete](sl-btmesh-evt-fw-dist-server-upload-complete)|0x58|0x0e|17|
|[evt_fw_dist_server_upload_failed](sl-btmesh-evt-fw-dist-server-upload-failed)|0x58|0x0f|17|
|[evt_fw_dist_server_upload_oob_start_uri](sl-btmesh-evt-fw-dist-server-upload-oob-start-uri)|0x58|0x10|5|
|[evt_fw_dist_server_upload_oob_start_req](sl-btmesh-evt-fw-dist-server-upload-oob-start-req)|0x58|0x11|5|
|[evt_fw_dist_server_fw_delete_req](sl-btmesh-evt-fw-dist-server-fw-delete-req)|0x58|0x12|5|
|[evt_fw_dist_server_fw_delete_all_req](sl-btmesh-evt-fw-dist-server-fw-delete-all-req)|0x58|0x13|4|
|[evt_fw_dist_server_dist_suspend](sl-btmesh-evt-fw-dist-server-dist-suspend)|0x58|0x15|4|
|[evt_fw_dist_server_resume_req](sl-btmesh-evt-fw-dist-server-resume-req)|0x58|0x16|18|
|[Bluetooth Mesh Firmware Distribution Client Model](sl-btmesh-fw-dist-client)|
|Commands|
|[cmd_fw_dist_client_init](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-init)|0x59|0x00|2|
|[cmd_fw_dist_client_deinit](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-deinit)|0x59|0x01|2|
|[cmd_fw_dist_client_setup](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-setup)|0x59|0x02|5|
|[cmd_fw_dist_client_setup_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-setup-upload)|0x59|0x03|20|
|[cmd_fw_dist_client_set_upload_metadata](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-set-upload-metadata)|0x59|0x04|3|
|[cmd_fw_dist_client_get_receivers](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-receivers)|0x59|0x0e|8|
|[cmd_fw_dist_client_get](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get)|0x59|0x0d|4|
|[cmd_fw_dist_client_start_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-distribution)|0x59|0x0f|31|
|[cmd_fw_dist_client_cancel_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-cancel-distribution)|0x59|0x10|4|
|[cmd_fw_dist_client_apply_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-apply-distribution)|0x59|0x11|4|
|[cmd_fw_dist_client_suspend_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-suspend-distribution)|0x59|0x12|4|
|[cmd_fw_dist_client_add_receivers](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-add-receivers)|0x59|0x13|5|
|[cmd_fw_dist_client_delete_all_receivers](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-delete-all-receivers)|0x59|0x14|4|
|[cmd_fw_dist_client_get_capabilities](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-capabilities)|0x59|0x15|4|
|[cmd_fw_dist_client_get_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-upload)|0x59|0x16|4|
|[cmd_fw_dist_client_start_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-upload)|0x59|0x17|2|
|[cmd_fw_dist_client_cancel_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-cancel-upload)|0x59|0x19|4|
|[cmd_fw_dist_client_get_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw)|0x59|0x1a|5|
|[cmd_fw_dist_client_get_fw_by_index](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw-by-index)|0x59|0x1b|6|
|[cmd_fw_dist_client_delete_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-delete-fw)|0x59|0x1c|5|
|[cmd_fw_dist_client_delete_all_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-delete-all-fw)|0x59|0x1d|4|
|[cmd_fw_dist_client_prepare_oob_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-prepare-oob-upload)|0x59|0x1e|3|
|[cmd_fw_dist_client_start_oob_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-oob-upload)|0x59|0x1f|8|
|[cmd_fw_dist_client_suspend_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-suspend-upload)|0x59|0x20|2|
|[cmd_fw_dist_client_resume_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-resume-upload)|0x59|0x21|2|
|Events|
|[evt_fw_dist_client_receivers_status](sl-btmesh-evt-fw-dist-client-receivers-status)|0x59|0x03|7|
|[evt_fw_dist_client_receivers_list](sl-btmesh-evt-fw-dist-client-receivers-list)|0x59|0x04|15|
|[evt_fw_dist_client_receivers_list_end](sl-btmesh-evt-fw-dist-client-receivers-list-end)|0x59|0x05|10|
|[evt_fw_dist_client_capabilities_status](sl-btmesh-evt-fw-dist-client-capabilities-status)|0x59|0x06|22|
|[evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)|0x59|0x07|17|
|[evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status)|0x59|0x08|9|
|[evt_fw_dist_client_fw_status](sl-btmesh-evt-fw-dist-client-fw-status)|0x59|0x09|10|
|[evt_fw_dist_client_upload_complete](sl-btmesh-evt-fw-dist-client-upload-complete)|0x59|0x0a|17|
|[evt_fw_dist_client_upload_failed](sl-btmesh-evt-fw-dist-client-upload-failed)|0x59|0x0b|20|
|[Bluetooth Mesh Remote Provisioning Client Model](sl-btmesh-remote-provisioning-client)|
|Commands|
|[cmd_remote_provisioning_client_init](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-init)|0x30|0x00|0|
|[cmd_remote_provisioning_client_get_scan_capabilities](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-get-scan-capabilities)|0x30|0x01|6|
|[cmd_remote_provisioning_client_start_scan](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-start-scan)|0x30|0x02|25|
|[cmd_remote_provisioning_client_get_scan_status](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-get-scan-status)|0x30|0x03|6|
|[cmd_remote_provisioning_client_stop_scan](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-stop-scan)|0x30|0x04|6|
|[cmd_remote_provisioning_client_start_extended_scan](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-start-extended-scan)|0x30|0x05|25|
|[cmd_remote_provisioning_client_open_link](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-open-link)|0x30|0x06|24|
|[cmd_remote_provisioning_client_get_link_status](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-get-link-status)|0x30|0x07|6|
|[cmd_remote_provisioning_client_close_link](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-close-link)|0x30|0x08|7|
|Events|
|[evt_remote_provisioning_client_scan_capabilities](sl-btmesh-evt-remote-provisioning-client-scan-capabilities)|0x30|0x00|6|
|[evt_remote_provisioning_client_scan_status](sl-btmesh-evt-remote-provisioning-client-scan-status)|0x30|0x01|8|
|[evt_remote_provisioning_client_scan_report](sl-btmesh-evt-remote-provisioning-client-scan-report)|0x30|0x02|25|
|[evt_remote_provisioning_client_extended_scan_report](sl-btmesh-evt-remote-provisioning-client-extended-scan-report)|0x30|0x03|24|
|[evt_remote_provisioning_client_link_status](sl-btmesh-evt-remote-provisioning-client-link-status)|0x30|0x05|6|
|[evt_remote_provisioning_client_link_report](sl-btmesh-evt-remote-provisioning-client-link-report)|0x30|0x06|5|
|[Bluetooth Mesh Remote Provisioning Server Model](sl-btmesh-remote-provisioning-server)|
|Commands|
|[cmd_remote_provisioning_server_init](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-init)|0x31|0x00|0|
|[cmd_remote_provisioning_server_open_link](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-open-link)|0x31|0x01|1|
|[cmd_remote_provisioning_server_set_default_bearer](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-set-default-bearer)|0x31|0x02|1|
|Events|
|[evt_remote_provisioning_server_link_open_request](sl-btmesh-evt-remote-provisioning-server-link-open-request)|0x31|0x00|7|
|[evt_remote_provisioning_server_link_close_request](sl-btmesh-evt-remote-provisioning-server-link-close-request)|0x31|0x01|1|
|[Bluetooth Mesh Standalone Updater](sl-btmesh-fw-standalone-updater)|
|Commands|
|[cmd_fw_standalone_updater_init](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-init)|0x5a|0x00|4|
|[cmd_fw_standalone_updater_deinit](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-deinit)|0x5a|0x01|2|
|[cmd_fw_standalone_updater_setup](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-setup)|0x5a|0x02|15|
|[cmd_fw_standalone_updater_set_metadata](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-set-metadata)|0x5a|0x03|3|
|[cmd_fw_standalone_updater_set_multicast_threshold](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-set-multicast-threshold)|0x5a|0x04|4|
|[cmd_fw_standalone_updater_add_receiver](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-add-receiver)|0x5a|0x05|5|
|[cmd_fw_standalone_updater_delete_all_receivers](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-delete-all-receivers)|0x5a|0x06|2|
|[cmd_fw_standalone_updater_start](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-start)|0x5a|0x07|26|
|[cmd_fw_standalone_updater_execute_distribution_step](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-execute-distribution-step)|0x5a|0x08|2|
|[cmd_fw_standalone_updater_apply](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-apply)|0x5a|0x09|2|
|[cmd_fw_standalone_updater_get_state](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-get-state)|0x5a|0x0a|2|
|[cmd_fw_standalone_updater_get_node_status_by_index](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-get-node-status-by-index)|0x5a|0x0b|4|
|[cmd_fw_standalone_updater_get_node_status_by_address](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-get-node-status-by-address)|0x5a|0x0c|4|
|[cmd_fw_standalone_updater_cancel](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-cancel)|0x5a|0x0d|2|
|[cmd_fw_standalone_updater_configure_throttle](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-configure-throttle)|0x5a|0x0e|5|
|Events|
|[evt_fw_standalone_updater_dist_state_changed](sl-btmesh-evt-fw-standalone-updater-dist-state-changed)|0x5a|0x00|5|
|[evt_fw_standalone_updater_node_failed](sl-btmesh-evt-fw-standalone-updater-node-failed)|0x5a|0x01|9|
|[Bluetooth Mesh Key migration](sl-btmesh-migration)|
|Commands|
|[cmd_migration_migrate_keys](sl-btmesh-migration#sl-btmesh-migration-migrate-keys)|0x60|0x01|0|
|[cmd_migration_migrate_ddb](sl-btmesh-migration#sl-btmesh-migration-migrate-ddb)|0x60|0x02|0|
|[NCP firmware list cache](sl-btmesh-ncp-fw-list)|
|Commands|
|[cmd_ncp_fw_list_init](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-init)|0x61|0x00|2|
|[cmd_ncp_fw_list_deinit](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-deinit)|0x61|0x01|2|
|[cmd_ncp_fw_list_get_fw_info_by_index](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-get-fw-info-by-index)|0x61|0x02|4|
|[cmd_ncp_fw_list_get_fw_metadata_by_index](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-get-fw-metadata-by-index)|0x61|0x03|4|
|[cmd_ncp_fw_list_add_fw](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-add-fw)|0x61|0x04|15|
|[cmd_ncp_fw_list_set_fw_metadata](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-set-fw-metadata)|0x61|0x05|5|
|Events|
|[evt_ncp_fw_list_fw_deleted](sl-btmesh-evt-ncp-fw-list-fw-deleted)|0x61|0x08|5|
|[evt_ncp_fw_list_fw_all_deleted](sl-btmesh-evt-ncp-fw-list-fw-all-deleted)|0x61|0x09|4|
|[evt_ncp_fw_list_fw_added](sl-btmesh-evt-ncp-fw-list-fw-added)|0x61|0x0a|15|
|[Bluetooth Mesh SAR Configuration Client Model](sl-btmesh-sar-config-client)|
|Commands|
|[cmd_sar_config_client_init](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-init)|0x62|0x01|0|
|[cmd_sar_config_client_deinit](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-deinit)|0x62|0x02|0|
|[cmd_sar_config_client_get_sar_transmitter](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-get-sar-transmitter)|0x62|0x03|4|
|[cmd_sar_config_client_set_sar_transmitter](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-set-sar-transmitter)|0x62|0x04|14|
|[cmd_sar_config_client_get_sar_receiver](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-get-sar-receiver)|0x62|0x05|4|
|[cmd_sar_config_client_set_sar_receiver](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-set-sar-receiver)|0x62|0x06|12|
|Events|
|[evt_sar_config_client_sar_transmitter_status](sl-btmesh-evt-sar-config-client-sar-transmitter-status)|0x62|0x01|16|
|[evt_sar_config_client_sar_receiver_status](sl-btmesh-evt-sar-config-client-sar-receiver-status)|0x62|0x02|14|
|[Bluetooth Mesh SAR Configuration Server Model](sl-btmesh-sar-config-server)|
|Commands|
|[cmd_sar_config_server_init](sl-btmesh-sar-config-server#sl-btmesh-sar-config-server-init)|0x63|0x01|0|
|[cmd_sar_config_server_deinit](sl-btmesh-sar-config-server#sl-btmesh-sar-config-server-deinit)|0x63|0x02|0|
|[cmd_sar_config_server_get_sar_transmitter](sl-btmesh-sar-config-server#sl-btmesh-sar-config-server-get-sar-transmitter)|0x63|0x03|0|
|[cmd_sar_config_server_set_sar_transmitter](sl-btmesh-sar-config-server#sl-btmesh-sar-config-server-set-sar-transmitter)|0x63|0x04|10|
|[cmd_sar_config_server_get_sar_receiver](sl-btmesh-sar-config-server#sl-btmesh-sar-config-server-get-sar-receiver)|0x63|0x05|0|
|[cmd_sar_config_server_set_sar_receiver](sl-btmesh-sar-config-server#sl-btmesh-sar-config-server-set-sar-receiver)|0x63|0x06|8|
|Events|
|[evt_sar_config_server_sar_transmitter_set](sl-btmesh-evt-sar-config-server-sar-transmitter-set)|0x63|0x01|10|
|[evt_sar_config_server_sar_receiver_set](sl-btmesh-evt-sar-config-server-sar-receiver-set)|0x63|0x02|8|
|[Bluetooth Mesh Private Beacon Client Model](sl-btmesh-private-beacon-client)|
|Commands|
|[cmd_private_beacon_client_init](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-init)|0x64|0x01|0|
|[cmd_private_beacon_client_deinit](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-deinit)|0x64|0x02|0|
|[cmd_private_beacon_client_get_beacon](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-get-beacon)|0x64|0x03|4|
|[cmd_private_beacon_client_set_beacon](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-beacon)|0x64|0x04|7|
|[cmd_private_beacon_client_get_gatt_proxy](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-get-gatt-proxy)|0x64|0x05|4|
|[cmd_private_beacon_client_set_gatt_proxy](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-gatt-proxy)|0x64|0x06|5|
|[cmd_private_beacon_client_get_identity](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-get-identity)|0x64|0x07|6|
|[cmd_private_beacon_client_set_identity](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-identity)|0x64|0x08|7|
|Events|
|[evt_private_beacon_client_beacon_status](sl-btmesh-evt-private-beacon-client-beacon-status)|0x64|0x01|8|
|[evt_private_beacon_client_gatt_proxy_status](sl-btmesh-evt-private-beacon-client-gatt-proxy-status)|0x64|0x02|7|
|[evt_private_beacon_client_identity_status](sl-btmesh-evt-private-beacon-client-identity-status)|0x64|0x03|10|
|[Bluetooth Mesh Private Beacon Server Model](sl-btmesh-private-beacon-server)|
|Commands|
|[cmd_private_beacon_server_init](sl-btmesh-private-beacon-server#sl-btmesh-private-beacon-server-init)|0x65|0x01|0|
|[cmd_private_beacon_server_deinit](sl-btmesh-private-beacon-server#sl-btmesh-private-beacon-server-deinit)|0x65|0x02|0|
|[Bluetooth Mesh Large Composition Data Client Model](sl-btmesh-lcd-client)|
|Commands|
|[cmd_lcd_client_init](sl-btmesh-lcd-client#sl-btmesh-lcd-client-init)|0x66|0x01|0|
|[cmd_lcd_client_deinit](sl-btmesh-lcd-client#sl-btmesh-lcd-client-deinit)|0x66|0x02|0|
|[cmd_lcd_client_get_composition_data](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-composition-data)|0x66|0x03|7|
|[cmd_lcd_client_get_metadata](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-metadata)|0x66|0x04|7|
|Events|
|[evt_lcd_client_data_header](sl-btmesh-evt-lcd-client-data-header)|0x66|0x01|9|
|[evt_lcd_client_data](sl-btmesh-evt-lcd-client-data)|0x66|0x02|5|
|[evt_lcd_client_data_end](sl-btmesh-evt-lcd-client-data-end)|0x66|0x03|6|
|[Bluetooth Mesh Large Composition Data Server Model](sl-btmesh-lcd-server)|
|Commands|
|[cmd_lcd_server_init](sl-btmesh-lcd-server#sl-btmesh-lcd-server-init)|0x67|0x01|0|
|[cmd_lcd_server_deinit](sl-btmesh-lcd-server#sl-btmesh-lcd-server-deinit)|0x67|0x02|0|
|[Bluetooth Mesh On-demand Private Proxy Client Model](sl-btmesh-on-demand-private-proxy-client)|
|Commands|
|[cmd_on_demand_private_proxy_client_init](sl-btmesh-on-demand-private-proxy-client#sl-btmesh-on-demand-private-proxy-client-init)|0x68|0x01|0|
|[cmd_on_demand_private_proxy_client_deinit](sl-btmesh-on-demand-private-proxy-client#sl-btmesh-on-demand-private-proxy-client-deinit)|0x68|0x02|0|
|[cmd_on_demand_private_proxy_client_get_on_demand_private_gatt_proxy](sl-btmesh-on-demand-private-proxy-client#sl-btmesh-on-demand-private-proxy-client-get-on-demand-private-gatt-proxy)|0x68|0x03|4|
|[cmd_on_demand_private_proxy_client_set_on_demand_private_gatt_proxy](sl-btmesh-on-demand-private-proxy-client#sl-btmesh-on-demand-private-proxy-client-set-on-demand-private-gatt-proxy)|0x68|0x04|5|
|Events|
|[evt_on_demand_private_proxy_client_private_gatt_proxy_status](sl-btmesh-evt-on-demand-private-proxy-client-private-gatt-proxy-status)|0x68|0x01|7|
|[Bluetooth Mesh Solicitation PDU RPL Config Client Model](sl-btmesh-solicitation-config-client)|
|Commands|
|[cmd_solicitation_config_client_init](sl-btmesh-solicitation-config-client#sl-btmesh-solicitation-config-client-init)|0x69|0x01|0|
|[cmd_solicitation_config_client_deinit](sl-btmesh-solicitation-config-client#sl-btmesh-solicitation-config-client-deinit)|0x69|0x02|0|
|[cmd_solicitation_config_client_clear_items](sl-btmesh-solicitation-config-client#sl-btmesh-solicitation-config-client-clear-items)|0x69|0x03|9|
|Events|
|[evt_solicitation_config_client_items_status](sl-btmesh-evt-solicitation-config-client-items-status)|0x69|0x01|10|
|[Bluetooth Mesh On-demand Private Proxy Server Model](sl-btmesh-on-demand-private-proxy-server)|
|Commands|
|[cmd_on_demand_private_proxy_server_init](sl-btmesh-on-demand-private-proxy-server#sl-btmesh-on-demand-private-proxy-server-init)|0x6a|0x01|0|
|[cmd_on_demand_private_proxy_server_deinit](sl-btmesh-on-demand-private-proxy-server#sl-btmesh-on-demand-private-proxy-server-deinit)|0x6a|0x02|0|
|[Bluetooth Mesh Silabs Configuration Server Vendor Model](sl-btmesh-silabs-config-server)|
|Commands|
|[cmd_silabs_config_server_init](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-init)|0x6b|0x00|0|
|[cmd_silabs_config_server_deinit](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-deinit)|0x6b|0x01|0|
|[cmd_silabs_config_server_set_tx](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-set-tx)|0x6b|0x02|5|
|[cmd_silabs_config_server_get_tx](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-get-tx)|0x6b|0x03|0|
|[cmd_silabs_config_server_set_model_enable](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-set-model-enable)|0x6b|0x04|7|
|[cmd_silabs_config_server_get_model_enable](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-get-model-enable)|0x6b|0x05|5|
|[cmd_silabs_config_server_set_network_pdu](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-set-network-pdu)|0x6b|0x06|2|
|[cmd_silabs_config_server_get_network_pdu](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-get-network-pdu)|0x6b|0x07|0|
|Events|
|[evt_silabs_config_server_tx_changed](sl-btmesh-evt-silabs-config-server-tx-changed)|0x6b|0x00|5|
|[evt_silabs_config_server_model_option_changed](sl-btmesh-evt-silabs-config-server-model-option-changed)|0x6b|0x01|7|
|[evt_silabs_config_server_network_pdu_changed](sl-btmesh-evt-silabs-config-server-network-pdu-changed)|0x6b|0x02|2|
|[Bluetooth Mesh Diagnostic Utilities](sl-btmesh-diagnostic)|
|Commands|
|[cmd_diagnostic_init](sl-btmesh-diagnostic#sl-btmesh-diagnostic-init)|0x6c|0x00|0|
|[cmd_diagnostic_deinit](sl-btmesh-diagnostic#sl-btmesh-diagnostic-deinit)|0x6c|0x01|0|
|[cmd_diagnostic_enable_relay](sl-btmesh-diagnostic#sl-btmesh-diagnostic-enable-relay)|0x6c|0x02|0|
|[cmd_diagnostic_disable_relay](sl-btmesh-diagnostic#sl-btmesh-diagnostic-disable-relay)|0x6c|0x03|0|
|[cmd_diagnostic_get_relay](sl-btmesh-diagnostic#sl-btmesh-diagnostic-get-relay)|0x6c|0x04|0|
|[cmd_diagnostic_get_statistics](sl-btmesh-diagnostic#sl-btmesh-diagnostic-get-statistics)|0x6c|0x05|8|
|[cmd_diagnostic_clear_statistics](sl-btmesh-diagnostic#sl-btmesh-diagnostic-clear-statistics)|0x6c|0x06|0|
|[cmd_diagnostic_enable_friend](sl-btmesh-diagnostic#sl-btmesh-diagnostic-enable-friend)|0x6c|0x07|0|
|[cmd_diagnostic_disable_friend](sl-btmesh-diagnostic#sl-btmesh-diagnostic-disable-friend)|0x6c|0x08|0|
|[cmd_diagnostic_get_friend](sl-btmesh-diagnostic#sl-btmesh-diagnostic-get-friend)|0x6c|0x09|0|
|Events|
|[evt_diagnostic_relay](sl-btmesh-evt-diagnostic-relay)|0x6c|0x00|6|
|[evt_diagnostic_friend_queue](sl-btmesh-evt-diagnostic-friend-queue)|0x6c|0x01|16|
|[evt_diagnostic_friend_relay](sl-btmesh-evt-diagnostic-friend-relay)|0x6c|0x02|16|
|[evt_diagnostic_friend_remove](sl-btmesh-evt-diagnostic-friend-remove)|0x6c|0x03|17|
|[Bluetooth Mesh model configuration migration](sl-btmesh-model-migration)|
|Commands|
|[cmd_model_migration_migrate_models](sl-btmesh-model-migration#sl-btmesh-model-migration-migrate-models)|0x6e|0x01|0|

### Overview

 This document contains the full API reference for the Silicon Labs Bluetooth Mesh Software.

The Blue Gecko family of the Silicon Labs' Bluetooth chipsets deliver a high performance, low energy and easy-to-use Bluetooth solution integrated into a small form factor package.

The ultra-low power operating modes and fast wake-up times of the Silicon Labs' energy friendly 32-bit MCUs, combined with the low transmit and receive power consumption of the Bluetooth radio, result in a solution optimized for battery powered applications.

#### API Payload

The parameters of a Bluetooth Mesh API command, response, or event are passed between the application and firmware in a payload. For example, a parameter of uint32_t type uses 4 bytes of the payload space. A byte array parameter uses one byte to describe the length of the array. Data in the array is copied into the remaining free payload space.

#### API Payload Size

The maximum API payload size is 256 bytes for both NCP and SoC modes. When an application calls a command, the API library checks the payload length and returns error code SL_STATUS_COMMAND_TOO_LONG (0x49) if the payload of input parameters will cause an overflow. Error code SL_STATUS_WOULD_OVERFLOW (0x1d) is returned if the given size of an output parameter is too small for response data.

#### Decode API Binary Data

For decoding a message in binary format, see [Decode a BGAPI Message](md-doc-bgapi#md-doc-bgapi-1decode-bgapi-message).

#### Deprecations

Deprecated commands, enumerations, and events are documented in this API reference manual. It is highly recommended to migrate to the replacements as early as possible. A deprecated command may not support new features although it remains functional on current Bluetooth Mesh stack. Deprecated items will be removed in some future release.

### BGAPI Types

Common types in BGAPI protocol. 

#### Modules

[uint8array](uint8array)

[byte_array_s](byte-array-s)

[bd_addr](bd-addr)

[uuid_128](uuid-128)

[aes_key_128](aes-key-128)

[sl_bt_uuid_16_t](sl-bt-uuid-16-t)

[sl_bt_uuid_64_t](sl-bt-uuid-64-t)

#### Typedefs

##### byte_array

`typedef struct byte_array_s byte_array`

#### Macros

`#define SL_BT_TYPE_UINT8ARRARY `

`#define SL_BT_TYPE_BYTE_ARRARY `

`#define SL_BT_TYPE_BDADDR `

`#define SL_BT_TYPE_UUID128 `

`#define SL_BT_TYPE_AES_KEY128 `

`#define SL_BT_TYPE_UUID16 `

`#define SL_BT_TYPE_UUID64 `

`#define SL_BGAPI_MSG_HEADER_LEN (4)`

**Description**: The length of a BGAPI message header which is 4 bytes.

`#define SL_BGAPI_MSG_ERROR_PAYLOAD_LEN (2)`

**Description**: The length of the BGAPI message payload of a generic error response.

`#define SL_BGAPI_MSG_TYPE (HDR)`

**Description**: Get the message type of a BGAPI message.

`#define SL_BGAPI_MSG_DEVICE_TYPE (HDR)`

**Description**: Get the device type of a BGAPI message.

`#define SL_BGAPI_MSG_ID (HDR)`

**Description**: Get the identifier of a BGAPI message including device type, class ID, message type and message ID.

`#define SL_BGAPI_HEADER_MAX_PAYLOAD_LEN (0x7FF)`

**Description**: The maximum value the BGAPI header payload length field can store.

`#define SL_BGAPI_MSG_LEN (HDR)`

**Description**: Get the data payload length in a BGAPI message.

`#define SL_BGAPI_BIT_ENCRYPTED (1 << 6)`

**Description**: The bit indicating whether data of a BGAPI message is encrypted.

`#define SL_BGAPI_MSG_ENCRYPTED (HDR)`

**Description**: Check whether data of a BGAPI message is encrypted.

`#define SL_BGAPI_MSG_HEADER_FROM_ID_AND_LEN (evt_id, payload_len)`

**Description**: Construct a BGAPI message header from an event ID and payload length.

Variable-length uint8_t array. Maximum length: 255. 

##### Public Attributes

###### len

```
uint8_t uint8array::len
```

**Details:** Number of bytes stored in `data`

###### data

```
uint8_t uint8array::data[]
```

**Details:** Data bytes

Variable-length uint8_t array. Maximum length: 65535. 

##### Public Attributes

###### len

```
uint16_t byte_array_s::len
```

**Details:** Number of bytes stored in `data`

###### data

```
uint8_t byte_array_s::data[]
```

**Details:** Data bytes

Bluetooth address. 

##### Public Attributes

###### addr

```
uint8_t bd_addr::addr[6]
```

**Description:** Bluetooth address in reverse byte order.

128-bit UUID 

##### Public Attributes

###### data

```
uint8_t uuid_128::data[16]
```

**Details:** 128-bit UUID

128-bit AES key 

##### Public Attributes

###### data

```
uint8_t aes_key_128::data[16]
```

**Details:** 128-bit AES key

16-bit UUID 

##### Public Attributes

###### data

```
uint8_t sl_bt_uuid_16_t::data[2]
```

**Details:** 16-bit UUID

64-bit UUID 

##### Public Attributes

###### data

```
uint8_t sl_bt_uuid_64_t::data[8]
```

**Details:** 64-bit UUID

### Mesh Node

Mesh Node. 

Bluetooth mesh stack API for unprovisioned devices and provisioned nodes.

**Initialization:**

- [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) : Initialize node
- [sl_btmesh_node_init_oob](sl-btmesh-node#sl-btmesh-node-init-oob) : Initialize node with out-of-band authentication
- [sl_btmesh_evt_node_initialized](sl-btmesh-evt-node-initialized) : Node initialized

**Provisioning a node:**

- [sl_btmesh_node_get_uuid](sl-btmesh-node#sl-btmesh-node-get-uuid) : Get device UUID
- [sl_btmesh_node_start_unprov_beaconing](sl-btmesh-node#sl-btmesh-node-start-unprov-beaconing) : Start unprovisioned device beaconing
- [sl_btmesh_node_stop_unprov_beaconing](sl-btmesh-node#sl-btmesh-node-stop-unprov-beaconing) : Stop unprovisioned device beaconing
- [sl_btmesh_evt_node_provisioning_started](sl-btmesh-evt-node-provisioning-started) : Provisioning process has started
- [sl_btmesh_evt_node_input_oob_request](sl-btmesh-evt-node-input-oob-request) : Request to input out-of-band authentication data
- [sl_btmesh_node_send_input_oob_request_response](sl-btmesh-node#sl-btmesh-node-send-input-oob-request-response) : Respond to input out-of-band authentication request
- [sl_btmesh_evt_node_display_output_oob](sl-btmesh-evt-node-display-output-oob) : Request to display output out-of-band authentication data
- [sl_btmesh_evt_node_static_oob_request](sl-btmesh-evt-node-static-oob-request) : Request for static out-of-band authentication data
- [sl_btmesh_node_send_static_oob_request_response](sl-btmesh-node#sl-btmesh-node-send-static-oob-request-response) : Respond to static out-of-band authentication request
- [sl_btmesh_evt_node_provisioned](sl-btmesh-evt-node-provisioned) : Node has been provisioned
- [sl_btmesh_evt_node_provisioning_failed](sl-btmesh-evt-node-provisioning-failed) : Provisioning process has failed
- [sl_btmesh_node_set_provisioning_data](sl-btmesh-node#sl-btmesh-node-set-provisioning-data) : Pre-provision a device

**Node Configuration:**

- [sl_btmesh_evt_node_key_added](sl-btmesh-evt-node-key-added) : A cryptographic key has been added to the node
- [sl_btmesh_evt_node_config_get](sl-btmesh-evt-node-config-get) : Node-wide configuration has been queried
- [sl_btmesh_evt_node_config_set](sl-btmesh-evt-node-config-set) : Node-wide configuration has been modified
- [sl_btmesh_evt_node_model_config_changed](sl-btmesh-evt-node-model-config-changed) : Model configuration has been modified
- [sl_btmesh_node_reset](sl-btmesh-node#sl-btmesh-node-reset) : Factory reset mesh node

**Note on Bluetooth mesh addresses**

Bluetooth mesh address space is divided into sections containing ranges of addresses of various types. Different address types are used in different contexts. Some requests accept only certain address types.

The address types are as follows:

- **0x0000 Unassigned address:** represents an address that has not been set
- **0x0001..0x7fff Unicast addresses** are allocated by the Provisioner to provisioned nodes. Each element of a node has its own unicast address.
- **0x8000..0xbfff Virtual addresses** are 16-bit shorthand for 128-bit label UUIDs which are pre-allocated to specific purposes in relevant Bluetooth SIG specifications. Virtual addresses can typically be used in the same context as group addresses. Some commands require specifying the full label UUID instead of the virtual address shorthand.
- **0xc000..0xffef Group addresses** are allocated by the Provisioner for multicast communication.
- **0xfff0..0xffff Fixed group addresses** are allocated in the Mesh specification for multicast communication in a particular context. They can be used in the same context as regular group addresses. The following addresses are currently defined:  
  - 0xfffc All-proxies broadcast address  
  - 0xfffd All-friends broadcast address  
  - 0xfffe All-relays broadcast address  
  - 0xffff All-nodes broadcast address

#### Modules

[Message Flags](sl-btmesh-node-message-flags)

[sl_btmesh_evt_node_initialized](sl-btmesh-evt-node-initialized)

[sl_btmesh_evt_node_provisioned](sl-btmesh-evt-node-provisioned)

[sl_btmesh_evt_node_config_get](sl-btmesh-evt-node-config-get)

[sl_btmesh_evt_node_config_set](sl-btmesh-evt-node-config-set)

[sl_btmesh_evt_node_display_output_oob](sl-btmesh-evt-node-display-output-oob)

[sl_btmesh_evt_node_input_oob_request](sl-btmesh-evt-node-input-oob-request)

[sl_btmesh_evt_node_provisioning_started](sl-btmesh-evt-node-provisioning-started)

[sl_btmesh_evt_node_provisioning_failed](sl-btmesh-evt-node-provisioning-failed)

[sl_btmesh_evt_node_key_added](sl-btmesh-evt-node-key-added)

[sl_btmesh_evt_node_model_config_changed](sl-btmesh-evt-node-model-config-changed)

[sl_btmesh_evt_node_reset](sl-btmesh-evt-node-reset)

[sl_btmesh_evt_node_ivrecovery_needed](sl-btmesh-evt-node-ivrecovery-needed)

[sl_btmesh_evt_node_changed_ivupdate_state](sl-btmesh-evt-node-changed-ivupdate-state)

[sl_btmesh_evt_node_static_oob_request](sl-btmesh-evt-node-static-oob-request)

[sl_btmesh_evt_node_key_removed](sl-btmesh-evt-node-key-removed)

[sl_btmesh_evt_node_key_updated](sl-btmesh-evt-node-key-updated)

[sl_btmesh_evt_node_heartbeat](sl-btmesh-evt-node-heartbeat)

[sl_btmesh_evt_node_heartbeat_start](sl-btmesh-evt-node-heartbeat-start)

[sl_btmesh_evt_node_heartbeat_stop](sl-btmesh-evt-node-heartbeat-stop)

[sl_btmesh_evt_node_beacon_received](sl-btmesh-evt-node-beacon-received)

[sl_btmesh_evt_node_local_dcd_data](sl-btmesh-evt-node-local-dcd-data)

[sl_btmesh_evt_node_local_dcd_data_end](sl-btmesh-evt-node-local-dcd-data-end)

[sl_btmesh_evt_node_local_model_metadata_page](sl-btmesh-evt-node-local-model-metadata-page)

[sl_btmesh_evt_node_local_model_metadata_page_end](sl-btmesh-evt-node-local-model-metadata-page-end)

[sl_btmesh_evt_node_start_received](sl-btmesh-evt-node-start-received)

[sl_btmesh_evt_node_address_updated](sl-btmesh-evt-node-address-updated)

[sl_btmesh_evt_node_dcd_updated](sl-btmesh-evt-node-dcd-updated)

#### Enumerations

##### sl_btmesh_node_algorithm_flag_t

```
enum sl_btmesh_node_algorithm_flag_t {
    sl_btmesh_node_algorithm_flag_ecdh_p256_cmac_aes128_aes_ccm = 0x1
    sl_btmesh_node_algorithm_flag_ecdh_p256_hmac_sha256_aes_ccm = 0x2
}
```

**Description:**

Flags for allowed provisioning algorithms during provisioning, which use a bitmap so that multiple algorithms can be supported.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_algorithm_flag_ecdh_p256_cmac_aes128_aes_ccm|(0x1) ECDH based provisioning, authenticated using AES-CMAC, and protected with AES-CCM|
|sl_btmesh_node_algorithm_flag_ecdh_p256_hmac_sha256_aes_ccm|(0x2) ECDH based provisioning, authenticated using HMAC-SHA-256, and protected with AES-CCM|

##### sl_btmesh_node_auth_method_flag_t

```
enum sl_btmesh_node_auth_method_flag_t {
    sl_btmesh_node_auth_method_flag_none = 0x1
    sl_btmesh_node_auth_method_flag_static = 0x2
    sl_btmesh_node_auth_method_flag_output = 0x4
    sl_btmesh_node_auth_method_flag_input = 0x8
}
```

**Description:**

Flags for supported OOB authentication methods during provisioning, which use a bitmap so that multiple methods can be supported.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_auth_method_flag_none|(0x1) Authentication without OOB is supported|
|sl_btmesh_node_auth_method_flag_static|(0x2) Static OOB data authentication is supported|
|sl_btmesh_node_auth_method_flag_output|(0x4) Output OOB authentication is supported|
|sl_btmesh_node_auth_method_flag_input|(0x8) Input OOB authentication is supported|

##### sl_btmesh_node_oob_input_action_flag_t

```
enum sl_btmesh_node_oob_input_action_flag_t {
    sl_btmesh_node_oob_input_action_flag_push = 0x1
    sl_btmesh_node_oob_input_action_flag_twist = 0x2
    sl_btmesh_node_oob_input_action_flag_numeric = 0x4
    sl_btmesh_node_oob_input_action_flag_alpha = 0x8
}
```

**Description:**

Flags for supported input OOB actions during provisioning, which use a bitmap so that multiple actions can be supported.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_oob_input_action_flag_push|(0x1) Push a button on the device.|
|sl_btmesh_node_oob_input_action_flag_twist|(0x2) Twist a dial on the device.|
|sl_btmesh_node_oob_input_action_flag_numeric|(0x4) Input a numeric authentication code.|
|sl_btmesh_node_oob_input_action_flag_alpha|(0x8) Input an alphanumeric authentication code.|

##### sl_btmesh_node_oob_input_action_t

```
enum sl_btmesh_node_oob_input_action_t {
    sl_btmesh_node_oob_input_action_push = 0x0
    sl_btmesh_node_oob_input_action_twist = 0x1
    sl_btmesh_node_oob_input_action_numeric = 0x2
    sl_btmesh_node_oob_input_action_alpha = 0x3
}
```

**Description:**

Indicate the input OOB action selected by the Provisioner during provisioning of the device.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_oob_input_action_push|(0x0) Push a button on the device.|
|sl_btmesh_node_oob_input_action_twist|(0x1) Twist a dial on the device.|
|sl_btmesh_node_oob_input_action_numeric|(0x2) Input a numeric authentication code.|
|sl_btmesh_node_oob_input_action_alpha|(0x3) Input an alphanumeric authentication code.|

##### sl_btmesh_node_oob_output_action_flag_t

```
enum sl_btmesh_node_oob_output_action_flag_t {
    sl_btmesh_node_oob_output_action_flag_blink = 0x1
    sl_btmesh_node_oob_output_action_flag_beep = 0x2
    sl_btmesh_node_oob_output_action_flag_vibrate = 0x4
    sl_btmesh_node_oob_output_action_flag_numeric = 0x8
    sl_btmesh_node_oob_output_action_flag_alpha = 0x10
}
```

**Description:**

Flags for supported output OOB actions during provisioning, which use a bitmap so that multiple actions can be supported.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_oob_output_action_flag_blink|(0x1) Blink a light.|
|sl_btmesh_node_oob_output_action_flag_beep|(0x2) Emit a sound.|
|sl_btmesh_node_oob_output_action_flag_vibrate|(0x4) Vibrate the device.|
|sl_btmesh_node_oob_output_action_flag_numeric|(0x8) Output a numeric authentication code.|
|sl_btmesh_node_oob_output_action_flag_alpha|(0x10) Output an alphanumeric authentication code.|

##### sl_btmesh_node_oob_output_action_t

```
enum sl_btmesh_node_oob_output_action_t {
    sl_btmesh_node_oob_output_action_blink = 0x0
    sl_btmesh_node_oob_output_action_beep = 0x1
    sl_btmesh_node_oob_output_action_vibrate = 0x2
    sl_btmesh_node_oob_output_action_numeric = 0x3
    sl_btmesh_node_oob_output_action_alpha = 0x4
}
```

**Description:**

Indicate the output OOB action selected by the Provisioner during provisioning of the device.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_oob_output_action_blink|(0x0) Blink a light.|
|sl_btmesh_node_oob_output_action_beep|(0x1) Emit a sound.|
|sl_btmesh_node_oob_output_action_vibrate|(0x2) Vibrate the device.|
|sl_btmesh_node_oob_output_action_numeric|(0x3) Output a numeric authentication code.|
|sl_btmesh_node_oob_output_action_alpha|(0x4) Output an alphanumeric authentication code.|

##### sl_btmesh_node_key_type_t

```
enum sl_btmesh_node_key_type_t {
    sl_btmesh_node_key_type_net = 0x0
    sl_btmesh_node_key_type_app = 0x1
}
```

**Description:**

Specify the type of a key in key manipulation commands.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_key_type_net|(0x0) Network key|
|sl_btmesh_node_key_type_app|(0x1) Application key|

##### sl_btmesh_node_config_state_t

```
enum sl_btmesh_node_config_state_t {
    sl_btmesh_node_dcd = 0x8008
    sl_btmesh_node_beacon = 0x8009
    sl_btmesh_node_default_ttl = 0x800c
    sl_btmesh_node_friendship = 0x800f
    sl_btmesh_node_gatt_proxy = 0x8012
    sl_btmesh_node_key_refresh = 0x8015
    sl_btmesh_node_relay = 0x8023
    sl_btmesh_node_identity = 0x8042
    sl_btmesh_node_nettx = 0x8024
}
```

**Description:**

Specify the state to which a Configuration Client/Server command/event applies.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_dcd|(0x8008) Device Composition Data|
|sl_btmesh_node_beacon|(0x8009) Status of broadcasting Secure Network Beacons|
|sl_btmesh_node_default_ttl|(0x800c) Default Time-To-Live for messages|
|sl_btmesh_node_friendship|(0x800f) Friend status|
|sl_btmesh_node_gatt_proxy|(0x8012) GATT proxy status|
|sl_btmesh_node_key_refresh|(0x8015) Key refresh status|
|sl_btmesh_node_relay|(0x8023) Relay status|
|sl_btmesh_node_identity|(0x8042) Identity status|
|sl_btmesh_node_nettx|(0x8024) Network transmit status|

##### sl_btmesh_node_dcd_comparison_t

```
enum sl_btmesh_node_dcd_comparison_t {
    sl_btmesh_node_composition_changed = 0x1
    sl_btmesh_node_cid_changed = 0x2
    sl_btmesh_node_pid_changed = 0x4
    sl_btmesh_node_vid_changed = 0x8
    sl_btmesh_node_crpl_changed = 0x10
    sl_btmesh_node_features_changed = 0x20
    sl_btmesh_node_element_loc_changed = 0x40
    sl_btmesh_node_sig_model_added = 0x80
    sl_btmesh_node_sig_model_removed = 0x100
    sl_btmesh_node_vendor_model_added = 0x200
    sl_btmesh_node_vendor_model_removed = 0x400
    sl_btmesh_node_element_added = 0x800
    sl_btmesh_node_element_removed = 0x1000
}
```

**Description:**

Indicates the type of differences found between a given composition data page content and the current one. Available details are page-specific.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_node_composition_changed|(0x1) Page content differs in any way.|
|sl_btmesh_node_cid_changed|(0x2) Company Identifier changed|
|sl_btmesh_node_pid_changed|(0x4) Product Identifier changed|
|sl_btmesh_node_vid_changed|(0x8) Version Identifier changed|
|sl_btmesh_node_crpl_changed|(0x10) Replay Protection List size changed|
|sl_btmesh_node_features_changed|(0x20) Features changed (Relay, Proxy, Friend or Low Power|
|sl_btmesh_node_element_loc_changed|(0x40) Element location changed for some element|
|sl_btmesh_node_sig_model_added|(0x80) SIG model entry added|
|sl_btmesh_node_sig_model_removed|(0x100) SIG model entry removed|
|sl_btmesh_node_vendor_model_added|(0x200) Vendor model added|
|sl_btmesh_node_vendor_model_removed|(0x400) Vendor model removed|
|sl_btmesh_node_element_added|(0x800) Element added|
|sl_btmesh_node_element_removed|(0x1000) Element removed|

#### Functions

##### sl_btmesh_node_init

`sl_status_t sl_btmesh_node_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the Bluetooth mesh stack in Node role. When initialization is complete, a [sl_btmesh_evt_node_initialized](sl-btmesh-evt-node-initialized) event will be generated.

This command must be issued before any other Bluetooth Mesh commands, except for [sl_btmesh_node_set_uuid](sl-btmesh-node#sl-btmesh-node-set-uuid) command.

Note that you may initialize a device either in the Provisioner or the Node role, but not both.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_node_initialized](sl-btmesh-evt-node-initialized)

##### sl_btmesh_node_set_exportable_keys

`sl_status_t sl_btmesh_node_set_exportable_keys(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Set the node in mode that allows exporting encryption keys. By default on devices with PSA/ITS support the keys on normal node cannot be exported. This command must called before either [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) or [sl_btmesh_node_init_oob](sl-btmesh-node#sl-btmesh-node-init-oob). **On everey boot device boots to node role unless this command is issued before node initialization**

This command is to be used if device is originally in a node role and at later stage switches to a provisioner role.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_node_start_unprov_beaconing

`sl_status_t sl_btmesh_node_start_unprov_beaconing(uint8_t bearer)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|bearer|Bit mask for which bearer to use. Values are as follows:<br/><br/>- **1 (bit 0):** PB-ADV<br/>- **2 (bit 1):** PB-GATT<br/><br/>Other bits are reserved and must not be used.|

Start sending Unprovisioned Device Beacons.

This command makes an unprovisioned device available for provisioning. The device will start sending periodic unprovisioned device beacons containing device UUID. It will also start listening for incoming Provisioner connection attempts on the specified bearers (PB-ADV, PB-GATT, or both). For PB-GATT, the device will also begin advertising its provisioning GATT service.

At the beginning of a provisioning process, a [sl_btmesh_evt_node_provisioning_started](sl-btmesh-evt-node-provisioning-started) event will be generated. When the device receives provisioning data from the Provisioner, a [sl_btmesh_evt_node_provisioned](sl-btmesh-evt-node-provisioned) event will be generated. If provisioning fails with an error, a [sl_btmesh_evt_node_provisioning_failed](sl-btmesh-evt-node-provisioning-failed) event will be generated.

After it is provisioned, addresses are allocated for the node elements and a network key is deployed to the node, making the node ready for further configuration by the Provisioner. Note that, at this point, the node is not yet fully ready to communicate with other nodes on the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_node_provisioning_started](sl-btmesh-evt-node-provisioning-started)
- [sl_btmesh_evt_node_provisioned](sl-btmesh-evt-node-provisioned)
- [sl_btmesh_evt_node_provisioning_failed](sl-btmesh-evt-node-provisioning-failed)

##### sl_btmesh_node_stop_unprov_beaconing

`sl_status_t sl_btmesh_node_stop_unprov_beaconing(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Stop sending Unprovisioned Device Beacons.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_rssi

`sl_status_t sl_btmesh_node_get_rssi(int8_t *rssi)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int8_t *|[out]|rssi|Latest RSSI value. Units: dBm. Ignore this parameter if the command fails.|

Get the latest RSSI value of a provisioned Bluetooth device.

The value indicates the best signal strength received from any node within the network. The value is cleared after calling this function meaning the next call will fail if no new RSSI value is received.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_send_input_oob_request_response

`sl_status_t sl_btmesh_node_send_input_oob_request_response(size_t data_len, const uint8_t *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|data_len|Length of data in `data`|
|const uint8_t *|[in]|data|Raw 16-byte or 32-byte array containing the input authentication data. The length of the data depends on the chosen provisioning algorithm; see the [sl_btmesh_evt_node_start_received](sl-btmesh-evt-node-start-received) event for details on how the stack indicates the Provisioner's choice of provisioning algorithm to the application.<br/><br/>Note that the raw data given to the stack must be encoded in the manner described in the Mesh Protocol 1.1 specifcation Section 5.4.2.4. Whether the data should be treated as Numeric or Alphanumeric depends on the selected input action.|

Provide the stack with the input out-of-band authentication data which the Provisioner is displaying.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_uuid

`sl_status_t sl_btmesh_node_get_uuid(uuid_128 *uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128) *|[out]|uuid|The 16-byte UUID of the device|

Get the device UUID.

Every mesh device has a 128-bit UUID identifying the device. It is used primarily during provisioning, because it is broadcast in Unprovisioned Device Beacons to indicate that the device is ready to be provisioned.

This command is used for debugging purposes. During provisioning, the stack automatically uses the UUID of the device, which does not need to be explicitly specified when [sl_btmesh_node_start_unprov_beaconing](sl-btmesh-node#sl-btmesh-node-start-unprov-beaconing) is started.

If get uuid is used before [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init), the uuid will be read from the nvme if it was manually set by [sl_btmesh_node_set_uuid](sl-btmesh-node#sl-btmesh-node-set-uuid). If get uuid is used without a prior [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) or [sl_btmesh_node_set_uuid](sl-btmesh-node#sl-btmesh-node-set-uuid), SL_STATUS_BT_MESH_DOES_NOT_EXIST will be returned.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_provisioning_data

`sl_status_t sl_btmesh_node_set_provisioning_data(aes_key_128 device_key, aes_key_128 network_key, uint16_t netkey_index, uint32_t iv_index, uint16_t address, uint8_t kr_in_progress)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[aes_key_128](aes-key-128)|[in]|device_key|Device Key for this Device, shared by the Provisioner|
|[aes_key_128](aes-key-128)|[in]|network_key|Network key that the Provisioner has selected for this device|
|uint16_t|[in]|netkey_index|Index of the Network Key the Provisioner has selected for this device|
|uint32_t|[in]|iv_index|Current IV Index used in the network|
|uint16_t|[in]|address|Address the Provisioner has allocated for this device's primary element|
|uint8_t|[in]|kr_in_progress|Set to 1 if key refresh is currently in progress, otherwise 0.|

Provision devices completely out-of-band. Populate the Provisioner's device database with the corresponding values to make the device reachable and configurable in the Provisioner's network.

See also the Provisioner command for [sl_btmesh_prov_add_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-add-ddb-entry) to Provisioner's device database.

**NOTE** : The device must be reset after this command has been issued.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_init_oob

`sl_status_t sl_btmesh_node_init_oob(uint8_t public_key, uint8_t auth_methods, uint16_t output_actions, uint8_t output_size, uint16_t input_actions, uint8_t input_size, uint16_t oob_location)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|public_key|If non-zero, use the ECC key stored in the persistent store during provisioning instead of an ephemeral key.|
|uint8_t|[in]|auth_methods|Enum [sl_btmesh_node_auth_method_flag_t](sl-btmesh-node#sl-btmesh-node-auth-method-flag-t). Allowed OOB authentication methods. The value is a bitmap so that multiple methods can be supported.|
|uint16_t|[in]|output_actions|Enum [sl_btmesh_node_oob_output_action_flag_t](sl-btmesh-node#sl-btmesh-node-oob-output-action-flag-t). Allowed OOB Output Action types|
|uint8_t|[in]|output_size|Maximum Output OOB size Valid values range from 0 (feature not supported) to 8.|
|uint16_t|[in]|input_actions|Enum [sl_btmesh_node_oob_input_action_flag_t](sl-btmesh-node#sl-btmesh-node-oob-input-action-flag-t). Allowed OOB Input Action types|
|uint8_t|[in]|input_size|Maximum Input OOB size. Valid values range from 0 (feature not supported) to 8.|
|uint16_t|[in]|oob_location|Defines the OOB data location bitmask. See [OOB Capabilities](sl-btmesh-prov-oob-capabilities).|

Initialize the Bluetooth mesh stack in the Node role. When initialization is complete, a [sl_btmesh_evt_node_initialized](sl-btmesh-evt-node-initialized) event is generated.

This command is the same as the [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) command except for parameters defining whether OOB authentication data stored on the device can be used during provisioning.

This command must be issued before any other Bluetooth mesh commands, except for [sl_btmesh_node_set_uuid](sl-btmesh-node#sl-btmesh-node-set-uuid) command.

Note that you may initialize a device either in the Provisioner or the Node role, but not both.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_node_initialized](sl-btmesh-evt-node-initialized)

##### sl_btmesh_node_set_ivrecovery_mode

`sl_status_t sl_btmesh_node_set_ivrecovery_mode(uint8_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|mode|Zero to disable; non-zero to enable|

Enable/disable the IV index recovery mode.

If the node has not been in communication with the network for a long time (e.g., because it was turned off), it may have missed IV index updates and isn't able to communicate with other nodes. In this case, enable the IV index recovery mode.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_ivrecovery_mode

`sl_status_t sl_btmesh_node_get_ivrecovery_mode(uint8_t *mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|mode|If non-zero, IV recovery is enabled.|

Get the current IV index recovery mode state. See [sl_btmesh_node_set_ivrecovery_mode](sl-btmesh-node#sl-btmesh-node-set-ivrecovery-mode) for details.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_net_relay_delay

`sl_status_t sl_btmesh_node_set_net_relay_delay(uint8_t min_ms, uint8_t max_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|min_ms|Minimum interval, in milliseconds|
|uint8_t|[in]|max_ms|Maximum interval, in milliseconds, which must be equal to or greater than the minimum.|

Set the network relay delay interval.

This parameter determines the time a relay waits until it relays a network PDU. The value used is a random number within the specified interval.

Note that this value affects the first instance of the relayed network PDU. If relay retransmissions are enabled, the interval between retransmissions is defined by the relay state, set by the Provisioner of the network or by [sl_btmesh_test_set_relay](sl-btmesh-test#sl-btmesh-test-set-relay) test command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_net_relay_delay

`sl_status_t sl_btmesh_node_get_net_relay_delay(uint8_t *min_ms, uint8_t *max_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|min_ms|Minimum interval, in milliseconds|
|uint8_t *|[out]|max_ms|Maximum interval, in milliseconds|

Get network relay delay interval. See [sl_btmesh_node_set_net_relay_delay](sl-btmesh-node#sl-btmesh-node-set-net-relay-delay) command for details.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_ivupdate_state

`sl_status_t sl_btmesh_node_get_ivupdate_state(uint32_t *iv_index, uint8_t *state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *|[out]|iv_index|Current IV index|
|uint8_t *|[out]|state|Indicates whether the IV index update is ongoing (1) or not (0).|

Get the current IV index update state in the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_request_ivupdate

`sl_status_t sl_btmesh_node_request_ivupdate(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Attempt to request an IV index update in the network.

Each network layer PDU that a node sends has a 24-bit sequence number attached to it. Each node element keeps a sequence number counter, which is incremented for every PDU sent out to the network. Repeating sequence numbers for a given IV index value is not allowed. As a result, if a node determines it is about to exhaust the available sequence numbers in one of its elements, it needs to request an IV index update by issuing this command.

Determining when a node may run out of sequence numbers has to be done at the application level because the stack can't determine how often the application plans to transmit to the network, i.e., how long the remaining sequence numbers might last.

See also the [sl_btmesh_node_get_seq_remaining](sl-btmesh-node#sl-btmesh-node-get-seq-remaining) command.

Note that the call may fail for various reasons, for example if an IV index update is already ongoing, or if not enough time has passed since the previous IV index update.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_seq_remaining

`sl_status_t sl_btmesh_node_get_seq_remaining(uint16_t elem_index, uint32_t *count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of queried element|
|uint32_t *|[out]|count|Remaining sequence number count|

Get the number of sequence numbers remaining on an element (before sequence numbers are exhausted). Note that every node element keeps a separate sequence number counter.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_save_replay_protection_list

`sl_status_t sl_btmesh_node_save_replay_protection_list(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Save the current replay protection list to the persistent store.

The replay protection list keeps track of the packet sequence numbers from different sources received by the node. The node will not process messages associated with already used sequence numbers and is therefore protected from replay attacks using previously recorded messages.

The replay protection list is kept in RAM during runtime. It needs to be saved to the persistent store periodically and always before the device powers off. Because the stack is not aware when this will happen, the application has to call this method while the node is getting ready to power down but is still running.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_uuid

`sl_status_t sl_btmesh_node_set_uuid(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID to set|

Write device UUID into the persistent store. This command must be called before initializing the Bluetooth mesh stack (before [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) or [sl_btmesh_node_init_oob](sl-btmesh-node#sl-btmesh-node-init-oob)), otherwise the change will not take effect before a reboot.

Ensure that the UUID conforms to the format defined in [RFC 4122](https://tools.ietf.org/html/rfc4122)

Note that UUID must not be changed when the device is provisioned to a network.

Furthermore, ensure that the UUID remains constant if a device has received a firmware update, which requires reprovisioning of the device after the update has been applied (e.g., new elements are added by the update).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_replay_protection_list_status

`sl_status_t sl_btmesh_node_get_replay_protection_list_status(uint16_t *total_entries, uint16_t *unsaved_entries)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|total_entries|Total number of entries in use|
|uint16_t *|[out]|unsaved_entries|Number of unsaved entries|

Get the status of the replay protection list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_element_address

`sl_status_t sl_btmesh_node_get_element_address(uint16_t elem_index, uint16_t *address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t *|[out]|address|The address of the element. Returns 0x0000 if the address is not configured or if an error occurs.|

Get the unicast address configured to an element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_send_static_oob_request_response

`sl_status_t sl_btmesh_node_send_static_oob_request_response(size_t data_len, const uint8_t *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|data_len|Length of data in `data`|
|const uint8_t *|[in]|data|Raw 16-byte or 32-byte array containing the static authentication data. The length of the data depends on the chosen provisioning algorithm; see the [sl_btmesh_evt_node_start_received](sl-btmesh-evt-node-start-received) event for details on how the stack indicates the Provisioner's choice of provisioning algorithm to the application.<br/><br/>Note that the raw data given to the stack must be encoded in the manner described in the Mesh Protocol 1.1 specifcation Section 5.4.2.4. The data type for static OOB authentication data is Binary.|

Provide the stack with static out-of-band authentication data, which the stack requested.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_reset

`sl_status_t sl_btmesh_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Factory reset of the mesh node.

To complete procedure, the application should do its own cleanup duties and reset the hardware.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_beacon_reporting

`sl_status_t sl_btmesh_node_set_beacon_reporting(uint8_t report)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|report|Turn reporting on (nonzero) or off (zero).|

Set secure network beaconing on or off. When on, every received secure network beacon will generate a [sl_btmesh_evt_node_beacon_received](sl-btmesh-evt-node-beacon-received) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_iv_update_age

`sl_status_t sl_btmesh_node_set_iv_update_age(uint32_t age_sec)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|age_sec|Seconds since last IV update. Values from 0 to 345600 (96h)|

Set the time since the last IV update. After the reboot, the node doesn't know the time since the last IV update and assumes that it happened at the time of the reboot.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_key_count

`sl_status_t sl_btmesh_node_get_key_count(uint8_t type, uint32_t *count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|type|Enum [sl_btmesh_node_key_type_t](sl-btmesh-node#sl-btmesh-node-key-type-t). 0 for network key, 1 for application key|
|uint32_t *|[out]|count|Number of keys of the given type on the device|

Get the total number of keys in node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_key

`sl_status_t sl_btmesh_node_get_key(uint8_t type, uint32_t index, uint8_t current, uint16_t *id, uint16_t *netkey_index, aes_key_128 *key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|type|Enum [sl_btmesh_node_key_type_t](sl-btmesh-node#sl-btmesh-node-key-type-t). 0 for network key, 1 for application key|
|uint32_t|[in]|index|Key position, ranging from zero to key count minus one|
|uint8_t|[in]|current|1: Current key, 0: Old key|
|uint16_t *|[out]|id|Mesh key index of the key|
|uint16_t *|[out]|netkey_index|For application keys, the network key index of the network key this key is bound to. Ignore for other key types.|
|[aes_key_128](aes-key-128) *|[out]|key|Key data, 16 bytes|

Get a key by position. Only current key data exits in normal mode. Old key data can be queried only during the key refresh.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_networks

`SL_BGAPI_DEPRECATED sl_status_t sl_btmesh_node_get_networks(size_t max_networks_size, size_t *networks_len, uint8_t *networks)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|max_networks_size|Size of output buffer passed in `networks`|
|size_t *|[out]|networks_len|On return, set to the length of output data written to `networks`|
|uint8_t *|[out]|networks|List of network IDs. Each ID is two bytes in little-endian format|

Get a list of networks supported by the node. This is a deprecated function. Please use [sl_btmesh_node_get_key_count](sl-btmesh-node#sl-btmesh-node-get-key-count) and [sl_btmesh_node_get_key](sl-btmesh-node#sl-btmesh-node-get-key) instead.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_element_seqnum

`sl_status_t sl_btmesh_node_get_element_seqnum(uint16_t elem_index, uint32_t *seqnum)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint32_t *|[out]|seqnum|Current sequence number of the element Ignore the value if the result code indicates an error (for example, when the element index is out of bounds).|

Get the current sequence number of an element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_model_option

`sl_status_t sl_btmesh_node_set_model_option(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t option, uint32_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|uint8_t|[in]|option|Option to set. The following options are defined:<br/><br/>- **0x80** Generic level delta behavior. Used only with generic level models.<br/>- **0xa0** Light models range status behavior. Used only with Lightness, Ctl and Hsl models. Note that state codes are different for states with status|
|uint32_t|[in]|value|Value for the option.<br/><br/>The following values are defined for generic level delta behavior option:<br/><br/>- **0x0** Generic level delta behavior: pass raw delta request data to application<br/>- **0x1** Generic level delta behavior: pass processed delta request data to application (default)<br/><br/>The following values are defined for for Lightness, Ctl and Hsl range status message behavior option:<br/><br/>- **0x0** Range Status behavior: pass status messages without status field(default)<br/>- **0x1** Range Status behavior: pass status messagages with status field|

Set a model-specific option.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_local_dcd

`sl_status_t sl_btmesh_node_get_local_dcd(uint8_t page)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|page|Composition data page to query|

Get the local Device Composition Data.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_node_local_dcd_data](sl-btmesh-evt-node-local-dcd-data)
- [sl_btmesh_evt_node_local_dcd_data_end](sl-btmesh-evt-node-local-dcd-data-end)

##### sl_btmesh_node_power_off

`sl_status_t sl_btmesh_node_power_off(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Power off the mesh node. To be called prior power off to allow the device to save its own state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_adv_phy

`sl_status_t sl_btmesh_node_set_adv_phy(uint8_t phy)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|N/A|phy||

##### sl_btmesh_node_get_adv_phy

`sl_status_t sl_btmesh_node_get_adv_phy(uint8_t *phy)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|N/A|phy||

##### sl_btmesh_node_set_provisioning_algorithms

`sl_status_t sl_btmesh_node_set_provisioning_algorithms(uint16_t algorithms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|algorithms|Enum [sl_btmesh_node_algorithm_flag_t](sl-btmesh-node#sl-btmesh-node-algorithm-flag-t). Allowed provisioning algorithms bitmask; zero represents a special value to allow any available algorithm.|

Set the set of allowed provisioning algorithms. The application can use this command to limit the algorithms used in provisioning, even if the stack would contain support for multiple algorithms. This command has to be issued before initializing the stack with [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) or [sl_btmesh_node_init_oob](sl-btmesh-node#sl-btmesh-node-init-oob).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_init_provisioning_records

`sl_status_t sl_btmesh_node_init_provisioning_records(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize provisioning record retrieval functionality on the device. This must be called before device is provisioned, if provisioning records are to be used.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_unprov_beaconing_adv_interval

`sl_status_t sl_btmesh_node_set_unprov_beaconing_adv_interval(uint16_t adv_interval_min, uint16_t adv_interval_max)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|adv_interval_min|Minimum advertisement interval. Value is in units of 0.625 ms. Range: 0x20 to 0xFFFF. Time range: 20 ms to 40.96 s|
|uint16_t|[in]|adv_interval_max|Maximum advertisement interval. Value is in units of 0.625 ms. Must be equal to or greater than the minimum interval. Range: 0x20 to 0xFFFF. Time range: 20 ms to 40.96 s|

Set Unprovisioned Device Beaconing advertisement interval timing parameters both with and without URI.

This command sets the timing parameters of Unprovisioned Device Beaconing advertisement interval with and without URI. This setting will take effect next time the Unprovisioned Device Beaconing advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_proxy_service_adv_interval

`sl_status_t sl_btmesh_node_set_proxy_service_adv_interval(uint16_t adv_interval_min, uint16_t adv_interval_max)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|adv_interval_min|Minimum advertisement interval. Value is in units of 0.625 ms. Range: 0x20 to 0xFFFF. Time range: 20 ms to 40.96 s|
|uint16_t|[in]|adv_interval_max|Maximum advertisement interval. Value is in units of 0.625 ms. Must be equal to or greater than the minimum interval. Range: 0x20 to 0xFFFF. Time range: 20 ms to 40.96 s|

Set Mesh Proxy Service advertisement interval timing parameters.

This command sets the timing parameters of Mesh Proxy Service advertisement interval. This setting will take effect next time the Mesh Proxy Service advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_provisioning_service_adv_interval

`sl_status_t sl_btmesh_node_set_provisioning_service_adv_interval(uint16_t adv_interval_min, uint16_t adv_interval_max)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|adv_interval_min|Minimum advertisement interval. Value is in units of 0.625 ms. Range: 0x20 to 0xFFFF. Time range: 20 ms to 40.96 s|
|uint16_t|[in]|adv_interval_max|Maximum advertisement interval. Value is in units of 0.625 ms. Must be equal to or greater than the minimum interval. Range: 0x20 to 0xFFFF. Time range: 20 ms to 40.96 s|

Set Mesh Provisioning Service advertisement interval timing parameters.

This command sets the timing parameters of Mesh Provisioning Service advertisement interval. This setting will take effect next time the Mesh Provisioning Service advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_local_model_metadata_page

`sl_status_t sl_btmesh_node_get_local_model_metadata_page(uint8_t page)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|page|Model metadata page to query|

Get the local Mesh Model Metadata.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_node_local_model_metadata_page](sl-btmesh-evt-node-local-model-metadata-page)
- [sl_btmesh_evt_node_local_model_metadata_page_end](sl-btmesh-evt-node-local-model-metadata-page-end)

##### sl_btmesh_node_save_proxy_solicitation_rpl

`sl_status_t sl_btmesh_node_save_proxy_solicitation_rpl(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Save the current Private GATT Proxy Solicitation Replay Protection List to persistent storage.

Solicitation PDU RPL is in use only if the node supports On Demand Private Proxy Server.

The replay protection list keeps track of the Solicitation PDU sequence numbers from different sources received by the node. The node will not process messages associtated with already used sequence numbers and is therefore protected from replay attacks using previously recorded messages.

The replay protection list is kept is RAM during runtime. It needs to be saved to persistent storage periodally and always before the device powers off. Because the stack is not aware when this will happen, the application has to call this method while the node is getting ready to power down but is still running.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_proxy_solicitation_rpl_status

`sl_status_t sl_btmesh_node_get_proxy_solicitation_rpl_status(uint16_t *total_entries, uint16_t *unsaved_entries)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|total_entries|Total number of entries in use|
|uint16_t *|[out]|unsaved_entries|Number of unsaved entries|

Get the status of the Solicitation Replay Protection List.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_oob_uri

`sl_status_t sl_btmesh_node_set_oob_uri(size_t uri_len, const uint8_t *uri)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|uri_len|Length of data in `uri`|
|const uint8_t *|[in]|uri|Base URI for OOB public key retrieval|

Set OOB URI.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_get_oob_uri

`sl_status_t sl_btmesh_node_get_oob_uri(size_t max_uri_size, size_t *uri_len, uint8_t *uri)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|max_uri_size|Size of output buffer passed in `uri`|
|size_t *|[out]|uri_len|On return, set to the length of output data written to `uri`|
|uint8_t *|[out]|uri|Base URI for OOB public key retrieval|

Get the OOB URI.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_proxy_service_uuid

`sl_status_t sl_btmesh_node_set_proxy_service_uuid(uint16_t uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|uuid||

##### sl_btmesh_node_test_identity

`sl_status_t sl_btmesh_node_test_identity(uint16_t address, uint16_t netkey_index, size_t data_len, const uint8_t *data, uint8_t *match)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Mesh address of the node, if this is 0 then testing for network identity. If valid a node address is give then testing for node identity.|
|uint16_t|[in]|netkey_index|Network key index of the node.|
|size_t|[in]|data_len|Length of data in `data`|
|const uint8_t *|[in]|data|Contents of the network identity beacon.|
|uint8_t *|[out]|match|- 0: Network/Node Identity record did not match<br/><br/>- 1: Network/Node Identity record did match|

Tets if receiver network identity beacon matches mesh network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_test_proxy_beacon

`sl_status_t sl_btmesh_node_test_proxy_beacon(uint16_t address, size_t data_len, const uint8_t *data, uint8_t *match, uint8_t *private_proxy, uint16_t *netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Mesh address of the node, if this is 0 then testing only for network identity. Otherwise for both node and network identity.|
|size_t|[in]|data_len|Length of data in `data`|
|const uint8_t *|[in]|data|Contents of the network identity beacon.|
|uint8_t *|[out]|match|- 0: Network/Node Identity did not match<br/><br/>- 1: Network Identity did match<br/>- 2: Node Identity did match|
|uint8_t *|[out]|private_proxy|- 0: Proxy Service is not private<br/><br/>- 1: Proxy Service is private|
|uint16_t *|[out]|netkey_index|Network key index of the node.|

Tets if receiver network/node identity beacon matches mesh network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_proxy_service_scan_response

`sl_status_t sl_btmesh_node_set_proxy_service_scan_response(uint16_t netkey_index, size_t scan_response_data_len, const uint8_t *scan_response_data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key associated with the proxy service advertisement. The caller may set scan response data separately for each network key, so that data encrypted and/or authenticated with the network key can be used as a scan response, if desired.|
|size_t|[in]|scan_response_data_len|Length of data in `scan_response_data`|
|const uint8_t *|[in]|scan_response_data|Binary scan response data encoded as AD types as defined in the Core specification. Data must fit into a SCAN_RSP PDU. It is up to the caller to ensure that valid data is given.|

Set Mesh Proxy Service scan response data.

This command sets the scan response data for a Mesh Proxy Service advertisement. The Mesh Proxy Service advertisement is a connectable and scannable advertisement, meaning that a client can issue a scan request and receive a scan response that carries additional data relevant to the service. This setting will take effect next time the Mesh Proxy Service advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_clear_proxy_service_scan_response

`sl_status_t sl_btmesh_node_clear_proxy_service_scan_response(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key associated with the proxy service advertisement. The caller may set scan response data separately for each network key, so that data encrypted and/or authenticated with the network key can be used as a scan response, if desired.|

Clear Mesh Proxy Service scan response data.

This command clears the scan response data for a Mesh Proxy Service advertisement. This setting will take effect next time the Mesh Proxy Service advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_set_provisioning_service_scan_response

`sl_status_t sl_btmesh_node_set_provisioning_service_scan_response(size_t scan_response_data_len, const uint8_t *scan_response_data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|size_t|[in]|scan_response_data_len|Length of data in `scan_response_data`|
|const uint8_t *|[in]|scan_response_data|Binary scan response data encoded as AD types as defined in the Core specification. Data must fit into a SCAN_RSP PDU. It is up to the caller to ensure that valid data is given.|

Set Mesh Provisioning Service scan response data.

This command sets the scan response data for a Mesh Provisioning Service advertisement. The Mesh Provisioning Service advertisement is a connectable and scannable advertisement, meaning that a client can issue a scan request and receive a scan response that carries additional data relevant to the service. This setting will take effect next time the Mesh Provisioning Service advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_clear_provisioning_service_scan_response

`sl_status_t sl_btmesh_node_clear_provisioning_service_scan_response(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Clear Mesh Provisioning Service scan response data.

This command clears the scan response data for a Mesh Provisioning Service advertisement. This setting will take effect next time the Mesh Provisioning Service advertisement is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_node_compare_dcd

`sl_status_t sl_btmesh_node_compare_dcd(uint8_t page_number, size_t page_data_len, const uint8_t *page_data, uint32_t *diff)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|page_number|Composition Data page number. Valid range: 0-2.|
|size_t|[in]|page_data_len|Length of data in `page_data`|
|const uint8_t *|[in]|page_data|Composition Data page content to be compared|
|uint32_t *|[out]|diff|Enum [sl_btmesh_node_dcd_comparison_t](sl-btmesh-node#sl-btmesh-node-dcd-comparison-t). Bit field indication the types of differences found.|

Compare a composition data page to the currently active one.

This command compares scans the given data and the currently active compositon data page for differences.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_node_init_id 0x00140028`

`#define sl_btmesh_cmd_node_set_exportable_keys_id 0x24140028`

`#define sl_btmesh_cmd_node_start_unprov_beaconing_id 0x01140028`

`#define sl_btmesh_cmd_node_stop_unprov_beaconing_id 0x16140028`

`#define sl_btmesh_cmd_node_get_rssi_id 0x17140028`

`#define sl_btmesh_cmd_node_send_input_oob_request_response_id 0x02140028`

`#define sl_btmesh_cmd_node_get_uuid_id 0x03140028`

`#define sl_btmesh_cmd_node_set_provisioning_data_id 0x04140028`

`#define sl_btmesh_cmd_node_init_oob_id 0x05140028`

`#define sl_btmesh_cmd_node_set_ivrecovery_mode_id 0x06140028`

`#define sl_btmesh_cmd_node_get_ivrecovery_mode_id 0x07140028`

`#define sl_btmesh_cmd_node_set_net_relay_delay_id 0x0b140028`

`#define sl_btmesh_cmd_node_get_net_relay_delay_id 0x0c140028`

`#define sl_btmesh_cmd_node_get_ivupdate_state_id 0x0d140028`

`#define sl_btmesh_cmd_node_request_ivupdate_id 0x0e140028`

`#define sl_btmesh_cmd_node_get_seq_remaining_id 0x0f140028`

`#define sl_btmesh_cmd_node_save_replay_protection_list_id 0x10140028`

`#define sl_btmesh_cmd_node_set_uuid_id 0x11140028`

`#define sl_btmesh_cmd_node_get_replay_protection_list_status_id 0x14140028`

`#define sl_btmesh_cmd_node_get_element_address_id 0x12140028`

`#define sl_btmesh_cmd_node_send_static_oob_request_response_id 0x13140028`

`#define sl_btmesh_cmd_node_reset_id 0x15140028`

`#define sl_btmesh_cmd_node_set_beacon_reporting_id 0x18140028`

`#define sl_btmesh_cmd_node_set_iv_update_age_id 0x19140028`

`#define sl_btmesh_cmd_node_get_key_count_id 0x1a140028`

`#define sl_btmesh_cmd_node_get_key_id 0x1b140028`

`#define sl_btmesh_cmd_node_get_networks_id 0x1c140028`

`#define sl_btmesh_cmd_node_get_element_seqnum_id 0x1d140028`

`#define sl_btmesh_cmd_node_set_model_option_id 0x1e140028`

`#define sl_btmesh_cmd_node_get_local_dcd_id 0x1f140028`

`#define sl_btmesh_cmd_node_power_off_id 0x21140028`

`#define sl_btmesh_cmd_node_set_adv_phy_id 0x22140028`

`#define sl_btmesh_cmd_node_get_adv_phy_id 0x23140028`

`#define sl_btmesh_cmd_node_set_provisioning_algorithms_id 0x25140028`

`#define sl_btmesh_cmd_node_init_provisioning_records_id 0x26140028`

`#define sl_btmesh_cmd_node_set_unprov_beaconing_adv_interval_id 0x28140028`

`#define sl_btmesh_cmd_node_set_proxy_service_adv_interval_id 0x29140028`

`#define sl_btmesh_cmd_node_set_provisioning_service_adv_interval_id 0x30140028`

`#define sl_btmesh_cmd_node_get_local_model_metadata_page_id 0x20140028`

`#define sl_btmesh_cmd_node_save_proxy_solicitation_rpl_id 0x31140028`

`#define sl_btmesh_cmd_node_get_proxy_solicitation_rpl_status_id 0x32140028`

`#define sl_btmesh_cmd_node_set_oob_uri_id 0x33140028`

`#define sl_btmesh_cmd_node_get_oob_uri_id 0x34140028`

`#define sl_btmesh_cmd_node_set_proxy_service_uuid_id 0x35140028`

`#define sl_btmesh_cmd_node_test_identity_id 0x36140028`

`#define sl_btmesh_cmd_node_test_proxy_beacon_id 0x3c140028`

`#define sl_btmesh_cmd_node_set_proxy_service_scan_response_id 0x37140028`

`#define sl_btmesh_cmd_node_clear_proxy_service_scan_response_id 0x38140028`

`#define sl_btmesh_cmd_node_set_provisioning_service_scan_response_id 0x39140028`

`#define sl_btmesh_cmd_node_clear_provisioning_service_scan_response_id 0x3a140028`

`#define sl_btmesh_cmd_node_compare_dcd_id 0x3b140028`

`#define sl_btmesh_rsp_node_init_id 0x00140028`

`#define sl_btmesh_rsp_node_set_exportable_keys_id 0x24140028`

`#define sl_btmesh_rsp_node_start_unprov_beaconing_id 0x01140028`

`#define sl_btmesh_rsp_node_stop_unprov_beaconing_id 0x16140028`

`#define sl_btmesh_rsp_node_get_rssi_id 0x17140028`

`#define sl_btmesh_rsp_node_send_input_oob_request_response_id 0x02140028`

`#define sl_btmesh_rsp_node_get_uuid_id 0x03140028`

`#define sl_btmesh_rsp_node_set_provisioning_data_id 0x04140028`

`#define sl_btmesh_rsp_node_init_oob_id 0x05140028`

`#define sl_btmesh_rsp_node_set_ivrecovery_mode_id 0x06140028`

`#define sl_btmesh_rsp_node_get_ivrecovery_mode_id 0x07140028`

`#define sl_btmesh_rsp_node_set_net_relay_delay_id 0x0b140028`

`#define sl_btmesh_rsp_node_get_net_relay_delay_id 0x0c140028`

`#define sl_btmesh_rsp_node_get_ivupdate_state_id 0x0d140028`

`#define sl_btmesh_rsp_node_request_ivupdate_id 0x0e140028`

`#define sl_btmesh_rsp_node_get_seq_remaining_id 0x0f140028`

`#define sl_btmesh_rsp_node_save_replay_protection_list_id 0x10140028`

`#define sl_btmesh_rsp_node_set_uuid_id 0x11140028`

`#define sl_btmesh_rsp_node_get_replay_protection_list_status_id 0x14140028`

`#define sl_btmesh_rsp_node_get_element_address_id 0x12140028`

`#define sl_btmesh_rsp_node_send_static_oob_request_response_id 0x13140028`

`#define sl_btmesh_rsp_node_reset_id 0x15140028`

`#define sl_btmesh_rsp_node_set_beacon_reporting_id 0x18140028`

`#define sl_btmesh_rsp_node_set_iv_update_age_id 0x19140028`

`#define sl_btmesh_rsp_node_get_key_count_id 0x1a140028`

`#define sl_btmesh_rsp_node_get_key_id 0x1b140028`

`#define sl_btmesh_rsp_node_get_networks_id 0x1c140028`

`#define sl_btmesh_rsp_node_get_element_seqnum_id 0x1d140028`

`#define sl_btmesh_rsp_node_set_model_option_id 0x1e140028`

`#define sl_btmesh_rsp_node_get_local_dcd_id 0x1f140028`

`#define sl_btmesh_rsp_node_power_off_id 0x21140028`

`#define sl_btmesh_rsp_node_set_adv_phy_id 0x22140028`

`#define sl_btmesh_rsp_node_get_adv_phy_id 0x23140028`

`#define sl_btmesh_rsp_node_set_provisioning_algorithms_id 0x25140028`

`#define sl_btmesh_rsp_node_init_provisioning_records_id 0x26140028`

`#define sl_btmesh_rsp_node_set_unprov_beaconing_adv_interval_id 0x28140028`

`#define sl_btmesh_rsp_node_set_proxy_service_adv_interval_id 0x29140028`

`#define sl_btmesh_rsp_node_set_provisioning_service_adv_interval_id 0x30140028`

`#define sl_btmesh_rsp_node_get_local_model_metadata_page_id 0x20140028`

`#define sl_btmesh_rsp_node_save_proxy_solicitation_rpl_id 0x31140028`

`#define sl_btmesh_rsp_node_get_proxy_solicitation_rpl_status_id 0x32140028`

`#define sl_btmesh_rsp_node_set_oob_uri_id 0x33140028`

`#define sl_btmesh_rsp_node_get_oob_uri_id 0x34140028`

`#define sl_btmesh_rsp_node_set_proxy_service_uuid_id 0x35140028`

`#define sl_btmesh_rsp_node_test_identity_id 0x36140028`

`#define sl_btmesh_rsp_node_test_proxy_beacon_id 0x3c140028`

`#define sl_btmesh_rsp_node_set_proxy_service_scan_response_id 0x37140028`

`#define sl_btmesh_rsp_node_clear_proxy_service_scan_response_id 0x38140028`

`#define sl_btmesh_rsp_node_set_provisioning_service_scan_response_id 0x39140028`

`#define sl_btmesh_rsp_node_clear_provisioning_service_scan_response_id 0x3a140028`

`#define sl_btmesh_rsp_node_compare_dcd_id 0x3b140028`

#### Message Flags

##### Macros

`#define SL_BTMESH_NODE_MESSAGE_FLAG_NONE 0x0`

**Description**: Message does not have flags

`#define SL_BTMESH_NODE_MESSAGE_FLAG_REPLY 0x1`

**Description**: Message is an access layer reply to a unicast request

`#define SL_BTMESH_NODE_MESSAGE_FLAG_MULTICAST_REPLY 0x2`

**Description**: Message is an access layer reply to a multicast request

`#define SL_BTMESH_NODE_MESSAGE_FLAG_TTL0 0x4`

**Description**: Message is either received with TTL=0 or is a response to such a message and should be sent out with TTL=0

`#define SL_BTMESH_NODE_MESSAGE_FLAG_SEGTRANS 0x10`

**Description**: Message is segmented in transport layer, can be used to force the use of transport layer segmentation

`#define SL_BTMESH_NODE_MESSAGE_FLAG_FRIENDCRED 0x20`

**Description**: Use friendship credentials instead of normal credentials when sending data; used when publishing with friendship credential flag on in model publish settings

`#define SL_BTMESH_NODE_MESSAGE_FLAG_EXTENDED 0x40`

**Description**: Use extended packet size instead of standard

`#define SL_BTMESH_NODE_MESSAGE_FLAG_LONG_DELAY 0x80`

**Description**: long delay needed in sending two messages in reply that need to be sent in order

#### sl_btmesh_evt_node_reset

Provisioner has instructed the node to reset. 

This event is generated when the Provisioner has ordered the node to be reset. Stack data has already been reset. This event is generated to inform the application that it should do its own cleanup duties and reset the hardware. 

##### Macros

`#define sl_btmesh_evt_node_reset_id 0x0a1400a8`

**Description**: Identifier of the reset event.

#### sl_btmesh_evt_node_static_oob_request

Static out of band authentication data is needed in the provisioning. 

The application on the node should provide the value to the Bluetooth mesh stack using the [sl_btmesh_node_send_static_oob_request_response](sl-btmesh-node#sl-btmesh-node-send-static-oob-request-response) command. 

##### Macros

`#define sl_btmesh_evt_node_static_oob_request_id 0x0d1400a8`

**Description**: Identifier of the static_oob_request event.

#### sl_btmesh_evt_node_dcd_updated

DCD page 128 has been taken in use as Page 0 due to a NPPI procedure. 

Node needs to be restarted. 

##### Macros

`#define sl_btmesh_evt_node_dcd_updated_id 0x181400a8`

**Description**: Identifier of the dcd_updated event.

#### sl_btmesh_evt_node_initialized

Node is initialized and operational. 

##### Modules

[sl_btmesh_evt_node_initialized_s](sl-btmesh-evt-node-initialized-s)

##### Typedefs

###### sl_btmesh_evt_node_initialized_t

`typedef struct sl_btmesh_evt_node_initialized_s sl_btmesh_evt_node_initialized_t`

##### Macros

`#define sl_btmesh_evt_node_initialized_id 0x001400a8`

**Description**: Identifier of the initialized event.

Data structure of the initialized event. 

###### Public Attributes

###### provisioned (heading level 7)

```
uint8_t sl_btmesh_evt_node_initialized_s::provisioned
```

**Details:** 1 if node is provisioned into a network, 0 if unprovisioned.

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_node_initialized_s::address
```

**Details:** Unicast address of the primary element of the node. Ignored if unprovisioned. Secondary elements have been assigned sequential unicast addresses following the primary element address.

###### iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_node_initialized_s::iv_index
```

**Details:** IV index for the first network of the node, ignore if unprovisioned.

#### sl_btmesh_evt_node_provisioned

The node has received provisioning data (address allocation and a network key) from the Provisioner. 

A [sl_btmesh_evt_node_key_added](sl-btmesh-evt-node-key-added) event will follow for the network key.

The node is now ready for further configuration by the Provisioner but is not yet ready for communication with other nodes in the network (it does not have any application keys and its models have not been set up). 

##### Modules

[sl_btmesh_evt_node_provisioned_s](sl-btmesh-evt-node-provisioned-s)

##### Typedefs

###### sl_btmesh_evt_node_provisioned_t

`typedef struct sl_btmesh_evt_node_provisioned_s sl_btmesh_evt_node_provisioned_t`

##### Macros

`#define sl_btmesh_evt_node_provisioned_id 0x011400a8`

**Description**: Identifier of the provisioned event.

Data structure of the provisioned event. 

###### Public Attributes

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_node_provisioned_s::address
```

**Details:** The unicast address that the Provisioner allocated for the primary element of the node. Secondary elements have been assigned sequentially following unicast addresses.

###### iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_node_provisioned_s::iv_index
```

**Details:** Current IV index of the provisioned network

#### sl_btmesh_evt_node_config_get

Informative; Configuration Client requested the current value of a State in the Configuration Server Model. 

##### Modules

[sl_btmesh_evt_node_config_get_s](sl-btmesh-evt-node-config-get-s)

##### Typedefs

###### sl_btmesh_evt_node_config_get_t

`typedef struct sl_btmesh_evt_node_config_get_s sl_btmesh_evt_node_config_get_t`

##### Macros

`#define sl_btmesh_evt_node_config_get_id 0x021400a8`

**Description**: Identifier of the config_get event.

Data structure of the config_get event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_node_config_get_s::netkey_index
```

**Details:** The network key index of the network to which the command applies. 0xffff for node-wide states.

###### id (heading level 7)

```
uint16_t sl_btmesh_evt_node_config_get_s::id
```

**Details:** Enum [sl_btmesh_node_config_state_t](sl-btmesh-node#sl-btmesh-node-config-state-t). Specifies to which State the command applies

#### sl_btmesh_evt_node_config_set

Informative; Configuration Client changes the State in the Configuration Server Model. 

##### Modules

[sl_btmesh_evt_node_config_set_s](sl-btmesh-evt-node-config-set-s)

##### Typedefs

###### sl_btmesh_evt_node_config_set_t

`typedef struct sl_btmesh_evt_node_config_set_s sl_btmesh_evt_node_config_set_t`

##### Macros

`#define sl_btmesh_evt_node_config_set_id 0x031400a8`

**Description**: Identifier of the config_set event.

Data structure of the config_set event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_node_config_set_s::netkey_index
```

**Details:** The network key index of the network to which the command applies. 0xffff for node-wide states.

###### id (heading level 7)

```
uint16_t sl_btmesh_evt_node_config_set_s::id
```

**Details:** Enum [sl_btmesh_node_config_state_t](sl-btmesh-node#sl-btmesh-node-config-state-t). Specifies to which state the command applies

###### value (heading level 7)

```
uint8array sl_btmesh_evt_node_config_set_s::value
```

**Details:** The new value

#### sl_btmesh_evt_node_display_output_oob

Display output OOB data so Provisioner can input it. 

##### Modules

[sl_btmesh_evt_node_display_output_oob_s](sl-btmesh-evt-node-display-output-oob-s)

##### Typedefs

###### sl_btmesh_evt_node_display_output_oob_t

`typedef struct sl_btmesh_evt_node_display_output_oob_s sl_btmesh_evt_node_display_output_oob_t`

##### Macros

`#define sl_btmesh_evt_node_display_output_oob_id 0x041400a8`

**Description**: Identifier of the display_output_oob event.

Data structure of the display_output_oob event. 

###### Public Attributes

###### output_action (heading level 7)

```
uint8_t sl_btmesh_evt_node_display_output_oob_s::output_action
```

**Details:** Enum [sl_btmesh_node_oob_output_action_t](sl-btmesh-node#sl-btmesh-node-oob-output-action-t). Selected output action

###### output_size (heading level 7)

```
uint8_t sl_btmesh_evt_node_display_output_oob_s::output_size
```

**Details:** Size of data to output in characters.

###### data (heading level 7)

```
uint8array sl_btmesh_evt_node_display_output_oob_s::data
```

**Details:** Raw 16-byte or 32-byte array containing the output authentication data. The length of the data depends on the chosen provisioning algorithm; see the [sl_btmesh_evt_node_start_received](sl-btmesh-evt-node-start-received) event for details on how the stack indicates the Provisioner's choice of provisioning algorithm to the application.

Note that the raw data is encoded in the manner described in the Mesh Protocol 1.1 specifcation Section 5.4.2.4, and must be converted to a human-readable format for displaying. Whether the data should be treated as Numeric or Alphanumeric depends on the selected output action.

#### sl_btmesh_evt_node_input_oob_request

The Provisioner is displaying an out of band authentication value. 

The application on the node should provide the value to the Bluetooth mesh stack using the [sl_btmesh_node_send_input_oob_request_response](sl-btmesh-node#sl-btmesh-node-send-input-oob-request-response) command. 

##### Modules

[sl_btmesh_evt_node_input_oob_request_s](sl-btmesh-evt-node-input-oob-request-s)

##### Typedefs

###### sl_btmesh_evt_node_input_oob_request_t

`typedef struct sl_btmesh_evt_node_input_oob_request_s sl_btmesh_evt_node_input_oob_request_t`

##### Macros

`#define sl_btmesh_evt_node_input_oob_request_id 0x051400a8`

**Description**: Identifier of the input_oob_request event.

Data structure of the input_oob_request event. 

###### Public Attributes

###### input_action (heading level 7)

```
uint8_t sl_btmesh_evt_node_input_oob_request_s::input_action
```

**Details:** Enum [sl_btmesh_node_oob_input_action_t](sl-btmesh-node#sl-btmesh-node-oob-input-action-t). Selected input action

###### input_size (heading level 7)

```
uint8_t sl_btmesh_evt_node_input_oob_request_s::input_size
```

**Details:** Size of data in the input in characters.

#### sl_btmesh_evt_node_provisioning_started

Provisioner has started provisioning this node. 

##### Modules

[sl_btmesh_evt_node_provisioning_started_s](sl-btmesh-evt-node-provisioning-started-s)

##### Typedefs

###### sl_btmesh_evt_node_provisioning_started_t

`typedef struct sl_btmesh_evt_node_provisioning_started_s sl_btmesh_evt_node_provisioning_started_t`

##### Macros

`#define sl_btmesh_evt_node_provisioning_started_id 0x061400a8`

**Description**: Identifier of the provisioning_started event.

Data structure of the provisioning_started event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_node_provisioning_started_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

#### sl_btmesh_evt_node_provisioning_failed

Provisioning the node has failed. 

##### Modules

[sl_btmesh_evt_node_provisioning_failed_s](sl-btmesh-evt-node-provisioning-failed-s)

##### Typedefs

###### sl_btmesh_evt_node_provisioning_failed_t

`typedef struct sl_btmesh_evt_node_provisioning_failed_s sl_btmesh_evt_node_provisioning_failed_t`

##### Macros

`#define sl_btmesh_evt_node_provisioning_failed_id 0x071400a8`

**Description**: Identifier of the provisioning_failed event.

Data structure of the provisioning_failed event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_node_provisioning_failed_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

#### sl_btmesh_evt_node_key_added

Received when a Configuration Client has deployed a new network or application key to the node. 

##### Modules

[sl_btmesh_evt_node_key_added_s](sl-btmesh-evt-node-key-added-s)

##### Typedefs

###### sl_btmesh_evt_node_key_added_t

`typedef struct sl_btmesh_evt_node_key_added_s sl_btmesh_evt_node_key_added_t`

##### Macros

`#define sl_btmesh_evt_node_key_added_id 0x081400a8`

**Description**: Identifier of the key_added event.

Data structure of the key_added event. 

###### Public Attributes

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_node_key_added_s::type
```

**Details:** Type of the new key. Values are as follows:

- **0x00:** Network key
- **0x01:** Application key

###### index (heading level 7)

```
uint16_t sl_btmesh_evt_node_key_added_s::index
```

**Details:** Key index of the new key

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_node_key_added_s::netkey_index
```

**Details:** Network key index to which the application key is bound, which is ignored for network keys

#### sl_btmesh_evt_node_model_config_changed

Informative. 

This event notifies that a remote Configuration Client has changed the configuration of a local model. 

##### Modules

[sl_btmesh_evt_node_model_config_changed_s](sl-btmesh-evt-node-model-config-changed-s)

##### Typedefs

###### sl_btmesh_evt_node_model_config_changed_t

`typedef struct sl_btmesh_evt_node_model_config_changed_s sl_btmesh_evt_node_model_config_changed_t`

##### Macros

`#define sl_btmesh_evt_node_model_config_changed_id 0x091400a8`

**Description**: Identifier of the model_config_changed event.

Data structure of the model_config_changed event. 

###### Public Attributes

###### node_config_state (heading level 7)

```
uint8_t sl_btmesh_evt_node_model_config_changed_s::node_config_state
```

**Details:** The configuration state which has changed. Values are as follows:

- **0x00:** Model application key bindings
- **0x01:** Model publication parameters
- **0x02:** Model subscription list

###### element_address (heading level 7)

```
uint16_t sl_btmesh_evt_node_model_config_changed_s::element_address
```

**Details:** Address of the element which contains the model

###### vendor_id (heading level 7)

```
uint16_t sl_btmesh_evt_node_model_config_changed_s::vendor_id
```

**Details:** Vendor ID of the model; value 0xffff is used for Bluetooth SIG models.

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_node_model_config_changed_s::model_id
```

**Details:** Model ID of the model

#### sl_btmesh_evt_node_ivrecovery_needed

Network IV index recovery needed. 

This event is generated when the node detects the network IV index is too far in the future to be automatically updated. See [sl_btmesh_node_set_ivrecovery_mode](sl-btmesh-node#sl-btmesh-node-set-ivrecovery-mode) command. 

##### Modules

[sl_btmesh_evt_node_ivrecovery_needed_s](sl-btmesh-evt-node-ivrecovery-needed-s)

##### Typedefs

###### sl_btmesh_evt_node_ivrecovery_needed_t

`typedef struct sl_btmesh_evt_node_ivrecovery_needed_s sl_btmesh_evt_node_ivrecovery_needed_t`

##### Macros

`#define sl_btmesh_evt_node_ivrecovery_needed_id 0x0b1400a8`

**Description**: Identifier of the ivrecovery_needed event.

Data structure of the ivrecovery_needed event. 

###### Public Attributes

###### node_iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_node_ivrecovery_needed_s::node_iv_index
```

**Details:** Current IV index of the node

###### network_iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_node_ivrecovery_needed_s::network_iv_index
```

**Details:** Received network IV index

#### sl_btmesh_evt_node_changed_ivupdate_state

Network IV index update state has changed. 

##### Modules

[sl_btmesh_evt_node_changed_ivupdate_state_s](sl-btmesh-evt-node-changed-ivupdate-state-s)

##### Typedefs

###### sl_btmesh_evt_node_changed_ivupdate_state_t

`typedef struct sl_btmesh_evt_node_changed_ivupdate_state_s sl_btmesh_evt_node_changed_ivupdate_state_t`

##### Macros

`#define sl_btmesh_evt_node_changed_ivupdate_state_id 0x0c1400a8`

**Description**: Identifier of the changed_ivupdate_state event.

Data structure of the changed_ivupdate_state event. 

###### Public Attributes

###### iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_node_changed_ivupdate_state_s::iv_index
```

**Details:** Current IV index

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_node_changed_ivupdate_state_s::state
```

**Details:** Indicates whether the IV index update is ongoing (1) or not (0).

#### sl_btmesh_evt_node_key_removed

Received when a Configuration Client removes a network or application key from the node. 

##### Modules

[sl_btmesh_evt_node_key_removed_s](sl-btmesh-evt-node-key-removed-s)

##### Typedefs

###### sl_btmesh_evt_node_key_removed_t

`typedef struct sl_btmesh_evt_node_key_removed_s sl_btmesh_evt_node_key_removed_t`

##### Macros

`#define sl_btmesh_evt_node_key_removed_id 0x0e1400a8`

**Description**: Identifier of the key_removed event.

Data structure of the key_removed event. 

###### Public Attributes

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_node_key_removed_s::type
```

**Details:** Type of the removed key. Values are as follows:

- **0x00:** Network key
- **0x01:** Application key

###### index (heading level 7)

```
uint16_t sl_btmesh_evt_node_key_removed_s::index
```

**Details:** Key index of the removed key

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_node_key_removed_s::netkey_index
```

**Details:** Network key index to which the application key is bound, which is ignored for network keys

#### sl_btmesh_evt_node_key_updated

Received when a Configuration Client updates a network or application key of the node. 

##### Modules

[sl_btmesh_evt_node_key_updated_s](sl-btmesh-evt-node-key-updated-s)

##### Typedefs

###### sl_btmesh_evt_node_key_updated_t

`typedef struct sl_btmesh_evt_node_key_updated_s sl_btmesh_evt_node_key_updated_t`

##### Macros

`#define sl_btmesh_evt_node_key_updated_id 0x0f1400a8`

**Description**: Identifier of the key_updated event.

Data structure of the key_updated event. 

###### Public Attributes

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_node_key_updated_s::type
```

**Details:** Type of the updated key. Values are as follows:

- **0x00:** Network key
- **0x01:** Application key

###### index (heading level 7)

```
uint16_t sl_btmesh_evt_node_key_updated_s::index
```

**Details:** Key index of the updated key

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_node_key_updated_s::netkey_index
```

**Details:** Network key index to which the application key is bound. Ignore this value if the event is for network key updates.

#### sl_btmesh_evt_node_heartbeat

Indicates reception of heartbeat message. 

##### Modules

[sl_btmesh_evt_node_heartbeat_s](sl-btmesh-evt-node-heartbeat-s)

##### Typedefs

###### sl_btmesh_evt_node_heartbeat_t

`typedef struct sl_btmesh_evt_node_heartbeat_s sl_btmesh_evt_node_heartbeat_t`

##### Macros

`#define sl_btmesh_evt_node_heartbeat_id 0x101400a8`

**Description**: Identifier of the heartbeat event.

Data structure of the heartbeat event. 

###### Public Attributes

###### src_addr (heading level 7)

```
uint16_t sl_btmesh_evt_node_heartbeat_s::src_addr
```

**Details:** Source address for the heartbeat message

###### dst_addr (heading level 7)

```
uint16_t sl_btmesh_evt_node_heartbeat_s::dst_addr
```

**Details:** Destination address for the heartbeat message

###### hops (heading level 7)

```
uint8_t sl_btmesh_evt_node_heartbeat_s::hops
```

**Details:** Hops traveled by the heartbeat message

#### sl_btmesh_evt_node_heartbeat_start

Indicates start of heartbeat reception. 

##### Modules

[sl_btmesh_evt_node_heartbeat_start_s](sl-btmesh-evt-node-heartbeat-start-s)

##### Typedefs

###### sl_btmesh_evt_node_heartbeat_start_t

`typedef struct sl_btmesh_evt_node_heartbeat_start_s sl_btmesh_evt_node_heartbeat_start_t`

##### Macros

`#define sl_btmesh_evt_node_heartbeat_start_id 0x111400a8`

**Description**: Identifier of the heartbeat_start event.

Data structure of the heartbeat_start event. 

###### Public Attributes

###### src_addr (heading level 7)

```
uint16_t sl_btmesh_evt_node_heartbeat_start_s::src_addr
```

**Details:** Source address for the heartbeat message

###### dst_addr (heading level 7)

```
uint16_t sl_btmesh_evt_node_heartbeat_start_s::dst_addr
```

**Details:** Destination address for the heartbeat message

###### period_sec (heading level 7)

```
uint32_t sl_btmesh_evt_node_heartbeat_start_s::period_sec
```

**Details:** Heartbeat subscription period in seconds.

#### sl_btmesh_evt_node_heartbeat_stop

Indicates end of heartbeat reception. 

##### Modules

[sl_btmesh_evt_node_heartbeat_stop_s](sl-btmesh-evt-node-heartbeat-stop-s)

##### Typedefs

###### sl_btmesh_evt_node_heartbeat_stop_t

`typedef struct sl_btmesh_evt_node_heartbeat_stop_s sl_btmesh_evt_node_heartbeat_stop_t`

##### Macros

`#define sl_btmesh_evt_node_heartbeat_stop_id 0x121400a8`

**Description**: Identifier of the heartbeat_stop event.

Data structure of the heartbeat_stop event. 

###### Public Attributes

###### src_addr (heading level 7)

```
uint16_t sl_btmesh_evt_node_heartbeat_stop_s::src_addr
```

**Details:** Source address for the heartbeat message

###### dst_addr (heading level 7)

```
uint16_t sl_btmesh_evt_node_heartbeat_stop_s::dst_addr
```

**Details:** Destination address for the heartbeat message

#### sl_btmesh_evt_node_beacon_received

Indicates reception of the secure network beacon. 

##### Modules

[sl_btmesh_evt_node_beacon_received_s](sl-btmesh-evt-node-beacon-received-s)

##### Typedefs

###### sl_btmesh_evt_node_beacon_received_t

`typedef struct sl_btmesh_evt_node_beacon_received_s sl_btmesh_evt_node_beacon_received_t`

##### Macros

`#define sl_btmesh_evt_node_beacon_received_id 0x131400a8`

**Description**: Identifier of the beacon_received event.

Data structure of the beacon_received event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_node_beacon_received_s::netkey_index
```

**Details:** Index of the network key used to encrypt the beacon

###### key_refresh (heading level 7)

```
uint8_t sl_btmesh_evt_node_beacon_received_s::key_refresh
```

**Details:** Indicates whether there is an ongoing key refresh.

###### iv_update (heading level 7)

```
uint8_t sl_btmesh_evt_node_beacon_received_s::iv_update
```

**Details:** Indicates whether there is an ongoing IV update.

###### iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_node_beacon_received_s::iv_index
```

**Details:** IV index contained in the beacon.

#### sl_btmesh_evt_node_local_dcd_data

Event reporting queried composition data page contents. 

The contents are requested using the [sl_btmesh_node_get_local_dcd](sl-btmesh-node#sl-btmesh-node-get-local-dcd) command. More than one event may be generated. Page contents are terminated by a [sl_btmesh_evt_node_local_dcd_data_end](sl-btmesh-evt-node-local-dcd-data-end) event. Note that the interpretation of the received data is page-specific. Page 0 contains the element and model layout of the node. 

##### Modules

[sl_btmesh_evt_node_local_dcd_data_s](sl-btmesh-evt-node-local-dcd-data-s)

##### Typedefs

###### sl_btmesh_evt_node_local_dcd_data_t

`typedef struct sl_btmesh_evt_node_local_dcd_data_s sl_btmesh_evt_node_local_dcd_data_t`

##### Macros

`#define sl_btmesh_evt_node_local_dcd_data_id 0x141400a8`

**Description**: Identifier of the local_dcd_data event.

Data structure of the local_dcd_data event. 

###### Public Attributes

###### page (heading level 7)

```
uint8_t sl_btmesh_evt_node_local_dcd_data_s::page
```

**Details:** Composition data page containing data

###### data (heading level 7)

```
uint8array sl_btmesh_evt_node_local_dcd_data_s::data
```

**Details:** Composition data page contents

#### sl_btmesh_evt_node_local_dcd_data_end

Terminating event for node composition data. 

##### Modules

[sl_btmesh_evt_node_local_dcd_data_end_s](sl-btmesh-evt-node-local-dcd-data-end-s)

##### Typedefs

###### sl_btmesh_evt_node_local_dcd_data_end_t

`typedef struct sl_btmesh_evt_node_local_dcd_data_end_s sl_btmesh_evt_node_local_dcd_data_end_t`

##### Macros

`#define sl_btmesh_evt_node_local_dcd_data_end_id 0x151400a8`

**Description**: Identifier of the local_dcd_data_end event.

Data structure of the local_dcd_data_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_node_local_dcd_data_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

#### sl_btmesh_evt_node_local_model_metadata_page

Event reporting queried model metadata page contents. 

The contents are requested using the [sl_btmesh_node_get_local_model_metadata_page](sl-btmesh-node#sl-btmesh-node-get-local-model-metadata-page) command. More than one event may be generated. Page contents are terminated by a [sl_btmesh_evt_node_local_model_metadata_page_end](sl-btmesh-evt-node-local-model-metadata-page-end) event. Note that the interpretation of the received data is page-specific. Page 0 contains the optional model metadata for mesh models, if applicable. 

##### Modules

[sl_btmesh_evt_node_local_model_metadata_page_s](sl-btmesh-evt-node-local-model-metadata-page-s)

##### Typedefs

###### sl_btmesh_evt_node_local_model_metadata_page_t

`typedef struct sl_btmesh_evt_node_local_model_metadata_page_s sl_btmesh_evt_node_local_model_metadata_page_t`

##### Macros

`#define sl_btmesh_evt_node_local_model_metadata_page_id 0x191400a8`

**Description**: Identifier of the local_model_metadata_page event.

Data structure of the local_model_metadata_page event. 

###### Public Attributes

###### page (heading level 7)

```
uint8_t sl_btmesh_evt_node_local_model_metadata_page_s::page
```

**Details:** Model metadata page number

###### data (heading level 7)

```
uint8array sl_btmesh_evt_node_local_model_metadata_page_s::data
```

**Details:** Model metadata page contents

#### sl_btmesh_evt_node_local_model_metadata_page_end

Terminating event for Mesh Model Metadata page. 

##### Modules

[sl_btmesh_evt_node_local_model_metadata_page_end_s](sl-btmesh-evt-node-local-model-metadata-page-end-s)

##### Typedefs

###### sl_btmesh_evt_node_local_model_metadata_page_end_t

`typedef struct sl_btmesh_evt_node_local_model_metadata_page_end_s sl_btmesh_evt_node_local_model_metadata_page_end_t`

##### Macros

`#define sl_btmesh_evt_node_local_model_metadata_page_end_id 0x1a1400a8`

**Description**: Identifier of the local_model_metadata_page_end event.

Data structure of the local_model_metadata_page_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_node_local_model_metadata_page_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

#### sl_btmesh_evt_node_start_received

Provisioning Start PDU received. 

This diagnostic event shows the algorithm, public key, and authentication choices Provisioner made and communicated to the unprovisioned device. 

##### Modules

[sl_btmesh_evt_node_start_received_s](sl-btmesh-evt-node-start-received-s)

##### Typedefs

###### sl_btmesh_evt_node_start_received_t

`typedef struct sl_btmesh_evt_node_start_received_s sl_btmesh_evt_node_start_received_t`

##### Macros

`#define sl_btmesh_evt_node_start_received_id 0x161400a8`

**Description**: Identifier of the start_received event.

Data structure of the start_received event. 

###### Public Attributes

###### algorithm (heading level 7)

```
uint8_t sl_btmesh_evt_node_start_received_s::algorithm
```

**Details:** Selected provisioning algorithm

###### public_key (heading level 7)

```
uint8_t sl_btmesh_evt_node_start_received_s::public_key
```

**Details:** Selected OOB public key

###### authentication_method (heading level 7)

```
uint8_t sl_btmesh_evt_node_start_received_s::authentication_method
```

**Details:** Selected authentication method

###### authentication_action (heading level 7)

```
uint8_t sl_btmesh_evt_node_start_received_s::authentication_action
```

**Details:** Selected authentication action

###### authentication_size (heading level 7)

```
uint8_t sl_btmesh_evt_node_start_received_s::authentication_size
```

**Details:** Selected authentication size

#### sl_btmesh_evt_node_address_updated

Address of the device has changed due to a NPPI procedure. 

##### Modules

[sl_btmesh_evt_node_address_updated_s](sl-btmesh-evt-node-address-updated-s)

##### Typedefs

###### sl_btmesh_evt_node_address_updated_t

`typedef struct sl_btmesh_evt_node_address_updated_s sl_btmesh_evt_node_address_updated_t`

##### Macros

`#define sl_btmesh_evt_node_address_updated_id 0x171400a8`

**Description**: Identifier of the address_updated event.

Data structure of the address_updated event. 

###### Public Attributes

###### new_address (heading level 7)

```
uint16_t sl_btmesh_evt_node_address_updated_s::new_address
```

**Details:** New address taken into use.

### Bluetooth Mesh Stack Provisioner

Bluetooth Mesh Stack Provisioner. 

Bluetooth mesh stack API for the embedded Provisioner

Commands in this class provision nodes in the mesh network and generate security keys for the network.

**Initialization:**

- [sl_btmesh_prov_init](sl-btmesh-prov#sl-btmesh-prov-init)
- [sl_btmesh_prov_init_provisioning_records](sl-btmesh-prov#sl-btmesh-prov-init-provisioning-records)
- [sl_btmesh_evt_prov_initialized](sl-btmesh-evt-prov-initialized)
- [sl_btmesh_evt_prov_initialization_failed](sl-btmesh-evt-prov-initialization-failed)

**Provisioning a node:**

- [sl_btmesh_prov_scan_unprov_beacons](sl-btmesh-prov#sl-btmesh-prov-scan-unprov-beacons) : Scan for unprovisioned device beacons
- [sl_btmesh_prov_stop_scan_unprov_beacons](sl-btmesh-prov#sl-btmesh-prov-stop-scan-unprov-beacons) : Stop scanning for unprovisioned device beacons
- [sl_btmesh_evt_prov_unprov_beacon](sl-btmesh-evt-prov-unprov-beacon) : Unprovisioned device beacon seen
- [sl_btmesh_evt_prov_uri](sl-btmesh-evt-prov-uri) : URI advertisement seen
- [sl_btmesh_prov_create_provisioning_session](sl-btmesh-prov#sl-btmesh-prov-create-provisioning-session) : Create provisioning session
- [sl_btmesh_prov_set_provisioning_suspend_event](sl-btmesh-prov#sl-btmesh-prov-set-provisioning-suspend-event) : Set up control points in the provisioning flow
- [sl_btmesh_prov_set_oob_requirements](sl-btmesh-prov#sl-btmesh-prov-set-oob-requirements) : Set requirements for device OOB capabilties
- [sl_btmesh_prov_provision_adv_device](sl-btmesh-prov#sl-btmesh-prov-provision-adv-device) : Provision a device over PB-ADV
- [sl_btmesh_prov_provision_gatt_device](sl-btmesh-prov#sl-btmesh-prov-provision-gatt-device) : Provision a device over PB-GATT
- [sl_btmesh_prov_provision_remote_device](sl-btmesh-prov#sl-btmesh-prov-provision-remote-device) : Provision a device over PB-Remote
- [sl_btmesh_evt_prov_oob_display_input](sl-btmesh-evt-prov-oob-display-input) : Request to display input out-of-band data to the user to input on the node
- [sl_btmesh_evt_prov_oob_pkey_request](sl-btmesh-evt-prov-oob-pkey-request) : Request for out-of-band public key of a node
- [sl_btmesh_prov_send_oob_pkey_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-pkey-response) : Provide stack with out-of-band public key of a node
- [sl_btmesh_evt_prov_oob_auth_request](sl-btmesh-evt-prov-oob-auth-request) : Request for out-of-band authentication data of a node
- [sl_btmesh_prov_send_oob_auth_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-auth-response) : Provide stack with out-of-band authentication data of a node
- [sl_btmesh_evt_prov_capabilities](sl-btmesh-evt-prov-capabilities) : Device capabilities received
- [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended) : Provisioning flow suspended for controlling of the provisioning behavior
- [sl_btmesh_prov_continue_provisioning](sl-btmesh-prov#sl-btmesh-prov-continue-provisioning) : Continue a suspended provisioning session
- [sl_btmesh_prov_abort_provisioning](sl-btmesh-prov#sl-btmesh-prov-abort-provisioning) : Abort a suspended provisioning session
- [sl_btmesh_prov_set_device_address](sl-btmesh-prov#sl-btmesh-prov-set-device-address) : Explicitly set the device primary address
- [sl_btmesh_prov_get_provisioning_records_list](sl-btmesh-prov#sl-btmesh-prov-get-provisioning-records-list) : Get the list of provisioning record on the device
- [sl_btmesh_evt_prov_provisioning_records_list](sl-btmesh-evt-prov-provisioning-records-list) : List of provisioning records on the device, if any
- [sl_btmesh_prov_get_provisioning_record_data](sl-btmesh-prov#sl-btmesh-prov-get-provisioning-record-data) : Get a fragment of a specific provisioning record's contents
- [sl_btmesh_evt_prov_provisioning_record_data](sl-btmesh-evt-prov-provisioning-record-data) : Provisioning record data fragment
- [sl_btmesh_evt_prov_start_sent](sl-btmesh-evt-prov-start-sent) : Provisioning Start PDU sent
- [sl_btmesh_evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned) : Device Provisioned
- [sl_btmesh_evt_prov_provisioning_failed](sl-btmesh-evt-prov-provisioning-failed) : Provisioning a device failed

Provisiong can be executed either with default behavior and parameters, or with fine-grained control over the provisioning process and explicitly set provisioning parameters. The overall process for provisioning a nearby device is as follows:

- The Provisioner starts to scan for devices to be provisioned by calling [sl_btmesh_prov_scan_unprov_beacons](sl-btmesh-prov#sl-btmesh-prov-scan-unprov-beacons). Devices that are available for provisioning are reported with [sl_btmesh_evt_prov_unprov_beacon](sl-btmesh-evt-prov-unprov-beacon) events that indicate the device UUID and the provisioning bearer the device supports. The scanning stops either by calling [sl_btmesh_prov_stop_scan_unprov_beacons](sl-btmesh-prov#sl-btmesh-prov-stop-scan-unprov-beacons) or by starting to provision a device.
- A provisioning session is created by calling [sl_btmesh_prov_create_provisioning_session](sl-btmesh-prov#sl-btmesh-prov-create-provisioning-session). At this point, the Provisioner must decide which initial network key is provisioned to the device if the provisioning succeeds. This choice only affects the initial access to the network, though. For example, the device could initially be provisioned to a guest network while later the primary network key could be added to the device and the guest network key dropped, to make the device part of the primary network.
- Optionally, if fine-grained control over the provisioning process execution is required, [sl_btmesh_prov_set_provisioning_suspend_event](sl-btmesh-prov#sl-btmesh-prov-set-provisioning-suspend-event) can be called to suspend the provisioning process at the time when a provisioning link is opened, or at the time when a Provisioning Capabilities PDU is received from the device. Whenever a provisioning process is suspended, the Provisioner can make a decision whether to proceed with provisioning or to abort it based on the information received from the device.
- A provisioning link to the device is opened by calling either [sl_btmesh_prov_provision_adv_device](sl-btmesh-prov#sl-btmesh-prov-provision-adv-device) or [sl_btmesh_prov_provision_gatt_device](sl-btmesh-prov#sl-btmesh-prov-provision-gatt-device), depending on which provision bearer is being used. Note that for PB-GATT a LE connection must first be established with the device to be provisioned, or provisioning will fail.
- Optionally, if the provisioning was set to be suspended at the opening of the provisioning link, [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended) event will be generated once the link is formed. At this point, the Provisioner may query the device's provisioning records by calling [sl_btmesh_prov_get_provisioning_records_list](sl-btmesh-prov#sl-btmesh-prov-get-provisioning-records-list) and [sl_btmesh_prov_get_provisioning_record_data](sl-btmesh-prov#sl-btmesh-prov-get-provisioning-record-data); provisioning records may contain information related to the device, such as X.509 certificates stored on the device. Once done examining the provisioning records, the Provisioner must call either [sl_btmesh_prov_continue_provisioning](sl-btmesh-prov#sl-btmesh-prov-continue-provisioning) or [sl_btmesh_prov_abort_provisioning](sl-btmesh-prov#sl-btmesh-prov-abort-provisioning) depending on whether it wants to continue the suspended provisioning process or not.
- Once the provisioning link has been opened and provisioning has been resumed if suspended, the Provisioner will query the device for its capabilities, which are reported as a [sl_btmesh_evt_prov_capabilities](sl-btmesh-evt-prov-capabilities) event.
- Optionally, if the provisioning was set to be suspended at the reception of the Provisioning Capabilities PDU, [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended) event will be generated once the capabilities have been reported. At this point, the Provisioner may examine the received capabilities and make decisions based on the number of elements the device has, the provisioning algorithms it supports, and the out-of-band information it has. The Provisioner may set the primary Mesh address to be assigned to the device by calling [sl_btmesh_prov_set_device_address](sl-btmesh-prov#sl-btmesh-prov-set-device-address) (if not used, the Mesh stack will auto-assign an address); it may set the OOB public key and OOB authentication data requirements it wants to use in provisioning the device by [sl_btmesh_prov_set_oob_requirements](sl-btmesh-prov#sl-btmesh-prov-set-oob-requirements) (if not used, the Mesh stack will automatically choose an authentication method). Then, the Provisioner must again call either [sl_btmesh_prov_continue_provisioning](sl-btmesh-prov#sl-btmesh-prov-continue-provisioning) or [sl_btmesh_prov_abort_provisioning](sl-btmesh-prov#sl-btmesh-prov-abort-provisioning) depending on whether it wants to continue the suspended provisioning process or not.
- Once the device's provisioning capabilities have been received, the Provisioner has made a selection of the provisioning parameters to use, and provisioning has been resumed if suspended, the Provisioner will send a Provisioning Start PDU to the device, and a [sl_btmesh_evt_prov_start_sent](sl-btmesh-evt-prov-start-sent) event that contains the choices made will be generated.
- If the device has an out-of-band public key and the key was chosen to be used in provisioning the device, a [sl_btmesh_evt_prov_oob_pkey_request](sl-btmesh-evt-prov-oob-pkey-request) will be generated when the key is needed. The Provisioner must respond with [sl_btmesh_prov_send_oob_pkey_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-pkey-response) that contains the key data.
- If the device supports output out-of-band authentication or static out-of-band authentication, and either of those was chosen to be used in provisioning the device, a [sl_btmesh_evt_prov_oob_auth_request](sl-btmesh-evt-prov-oob-auth-request) event will be generated when the authentication data is needed. The Provisioner must respond with [sl_btmesh_prov_send_oob_auth_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-auth-response) that contains the authentication data.
- If the device support input out-of-band authentication and it was chosen to be used in provisioning the device, a [sl_btmesh_evt_prov_oob_display_input](sl-btmesh-evt-prov-oob-display-input) event that contains authentication data will be generated. The Provisioner must display the authentication data to the user, so that they may input the data into the device.
- Once the necessary cryptographic exchanges have been completed, the Provisioner will provision the device with the chosen primary unicast address and the chosen initial network key. The process will conclude by the generation of a [sl_btmesh_evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned) event.

**Key Management**

- [sl_btmesh_prov_create_network](sl-btmesh-prov#sl-btmesh-prov-create-network) : Create a new network key on the Provisioner
- [sl_btmesh_prov_create_appkey](sl-btmesh-prov#sl-btmesh-prov-create-appkey) : Create a new application key on the Provisioner
- [sl_btmesh_prov_start_key_refresh](sl-btmesh-prov#sl-btmesh-prov-start-key-refresh) : Start a key refresh procedure
- [sl_btmesh_prov_suspend_key_refresh](sl-btmesh-prov#sl-btmesh-prov-suspend-key-refresh) : Suspend an ongoing key refresh procedure
- [sl_btmesh_prov_resume_key_refresh](sl-btmesh-prov#sl-btmesh-prov-resume-key-refresh) : Resume a suspended key refresh procedure
- [sl_btmesh_prov_get_key_refresh_exclusion](sl-btmesh-prov#sl-btmesh-prov-get-key-refresh-exclusion) : Get node key refresh exclusion status
- [sl_btmesh_prov_set_key_refresh_exclusion](sl-btmesh-prov#sl-btmesh-prov-set-key-refresh-exclusion) : Set node key refresh exclusion status
- [sl_btmesh_prov_get_key_refresh_phase](sl-btmesh-prov#sl-btmesh-prov-get-key-refresh-phase) : Get node key refresh phase
- [sl_btmesh_prov_start_key_refresh_from_phase](sl-btmesh-prov#sl-btmesh-prov-start-key-refresh-from-phase) : Start a key refresh procedure from the given phase

**Device Database**

- [sl_btmesh_prov_add_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-add-ddb-entry) : Add a node to the device database
- [sl_btmesh_prov_delete_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-delete-ddb-entry) : Remove a node from the device database
- [sl_btmesh_prov_get_ddb_entry](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry) : Fetch node data from the device database
- [sl_btmesh_prov_list_ddb_entries](sl-btmesh-prov#sl-btmesh-prov-list-ddb-entries) : Request a list of nodes in the device database
- [sl_btmesh_evt_prov_ddb_list](sl-btmesh-evt-prov-ddb-list) : Device database list result
- [sl_btmesh_prov_update_device_netkey_index](sl-btmesh-prov#sl-btmesh-prov-update-device-netkey-index) : Update default network key index for a device database entry
- [sl_btmesh_prov_get_ddb_entry_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-count) : Get the number of entries in the the device database
- [sl_btmesh_prov_get_ddb_entry_by_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-by-count) : Get the Nth entry from the the device database

These commands are available only if the Provisioner functionality is compiled in the device. Otherwise, a "feature not implemented" error code will be returned for all functions in this class. 

#### Modules

[OOB Capabilities](sl-btmesh-prov-oob-capabilities)

[sl_btmesh_evt_prov_initialized](sl-btmesh-evt-prov-initialized)

[sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended)

[sl_btmesh_evt_prov_capabilities](sl-btmesh-evt-prov-capabilities)

[sl_btmesh_evt_prov_provisioning_failed](sl-btmesh-evt-prov-provisioning-failed)

[sl_btmesh_evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned)

[sl_btmesh_evt_prov_unprov_beacon](sl-btmesh-evt-prov-unprov-beacon)

[sl_btmesh_evt_prov_oob_pkey_request](sl-btmesh-evt-prov-oob-pkey-request)

[sl_btmesh_evt_prov_oob_auth_request](sl-btmesh-evt-prov-oob-auth-request)

[sl_btmesh_evt_prov_oob_display_input](sl-btmesh-evt-prov-oob-display-input)

[sl_btmesh_evt_prov_ddb_list](sl-btmesh-evt-prov-ddb-list)

[sl_btmesh_evt_prov_uri](sl-btmesh-evt-prov-uri)

[sl_btmesh_evt_prov_key_refresh_phase_update](sl-btmesh-evt-prov-key-refresh-phase-update)

[sl_btmesh_evt_prov_key_refresh_node_update](sl-btmesh-evt-prov-key-refresh-node-update)

[sl_btmesh_evt_prov_key_refresh_complete](sl-btmesh-evt-prov-key-refresh-complete)

[sl_btmesh_evt_prov_add_ddb_entry_complete](sl-btmesh-evt-prov-add-ddb-entry-complete)

[sl_btmesh_evt_prov_delete_ddb_entry_complete](sl-btmesh-evt-prov-delete-ddb-entry-complete)

[sl_btmesh_evt_prov_initialization_failed](sl-btmesh-evt-prov-initialization-failed)

[sl_btmesh_evt_prov_provisioning_records_list](sl-btmesh-evt-prov-provisioning-records-list)

[sl_btmesh_evt_prov_provisioning_record_data](sl-btmesh-evt-prov-provisioning-record-data)

[sl_btmesh_evt_prov_start_sent](sl-btmesh-evt-prov-start-sent)

#### Functions

##### sl_btmesh_prov_init

`sl_status_t sl_btmesh_prov_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the Bluetooth mesh stack in the Provisioner role. Note that the result code of this command only indicates that the request to initialize has been accepted for processing. When initialization is completed successfully, a [sl_btmesh_evt_prov_initialized](sl-btmesh-evt-prov-initialized) will be generated. On failed initialization a [sl_btmesh_evt_prov_initialization_failed](sl-btmesh-evt-prov-initialization-failed) event will be generated. Note that the application must wait for an event to be generated before executing further BGAPI commands.

This command must be issued before any other Bluetooth mesh stack commands. Note that the Bluetooth mesh stack can be initialized either in the Provisioner or the Node role, but not both.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_initialized](sl-btmesh-evt-prov-initialized)
- [sl_btmesh_evt_prov_initialization_failed](sl-btmesh-evt-prov-initialization-failed)

##### sl_btmesh_prov_scan_unprov_beacons

`sl_status_t sl_btmesh_prov_scan_unprov_beacons(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Start scanning for unprovisioned device beacons.

Unprovisioned devices send out beacons containing their UUID. An [sl_btmesh_evt_prov_unprov_beacon](sl-btmesh-evt-prov-unprov-beacon) will be generated for each beacon seen. Once the UUID of a device is known, the Provisioner may start provisioning the device with the [sl_btmesh_prov_create_provisioning_session](sl-btmesh-prov#sl-btmesh-prov-create-provisioning-session) command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_unprov_beacon](sl-btmesh-evt-prov-unprov-beacon)

##### sl_btmesh_prov_create_provisioning_session

`sl_status_t sl_btmesh_prov_create_provisioning_session(uint16_t netkey_index, uuid_128 uuid, uint8_t attention_timer_sec)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the initial network key, which is sent to the device during provisioning|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device|
|uint8_t|[in]|attention_timer_sec|Attention timer value, in seconds, which indicates the time that the provisioned device should attract human attention|

Initialize the provisioning session. After this command, it is possible to set the provisioning parameter with the following command:

- [sl_btmesh_prov_set_provisioning_suspend_event](sl-btmesh-prov#sl-btmesh-prov-set-provisioning-suspend-event)

After all optional parameters have been set, the provisioning process is triggered by one of the following commands:

- [sl_btmesh_prov_provision_adv_device](sl-btmesh-prov#sl-btmesh-prov-provision-adv-device)
- [sl_btmesh_prov_provision_gatt_device](sl-btmesh-prov#sl-btmesh-prov-provision-gatt-device)

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_prov_set_provisioning_suspend_event

`sl_status_t sl_btmesh_prov_set_provisioning_suspend_event(uint8_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|status|Controls when provisioning is suspended and [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended) event is created. The value is a bitmap so multiple possibilities can be set.<br/><br/>- **Bit 0 set** provisioning will be suspended when Capabilities PDU is received from the unprovisioned device<br/>- **Bit 1 set** provisioning will be suspended when the provisioning session is opened<br/><br/>If no bits are set (value is zero) provisioning will not be suspended. This is the default.|

Set whether the provisioning can be suspended at a specified point while it is occurring. Currently, this can happen after reception on provisioning capabilities message or when the provisioning link is opened.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended)

##### sl_btmesh_prov_provision_adv_device

`sl_status_t sl_btmesh_prov_provision_adv_device(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device|

Provision device over PB-ADV

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned)
- [sl_btmesh_evt_prov_provisioning_failed](sl-btmesh-evt-prov-provisioning-failed)

##### sl_btmesh_prov_provision_gatt_device

`sl_status_t sl_btmesh_prov_provision_gatt_device(uuid_128 uuid, uint8_t connection)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device|
|uint8_t|[in]|connection|Connection handle|

Provision device over PB-GATT

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned)
- [sl_btmesh_evt_prov_provisioning_failed](sl-btmesh-evt-prov-provisioning-failed)
- [sl_btmesh_evt_prov_capabilities](sl-btmesh-evt-prov-capabilities)

##### sl_btmesh_prov_provision_remote_device

`sl_status_t sl_btmesh_prov_provision_remote_device(uuid_128 uuid, uint16_t server)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device|
|uint16_t|[in]|server|Address of the remote provisioning server|

Provision device over remote provisioning server connection

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_device_provisioned](sl-btmesh-evt-prov-device-provisioned)
- [sl_btmesh_evt_prov_provisioning_failed](sl-btmesh-evt-prov-provisioning-failed)
- [sl_btmesh_evt_prov_capabilities](sl-btmesh-evt-prov-capabilities)

##### sl_btmesh_prov_continue_provisioning

`sl_status_t sl_btmesh_prov_continue_provisioning(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device being provisioned|

Continue provisioning after the suspension indicated by [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_prov_abort_provisioning

`sl_status_t sl_btmesh_prov_abort_provisioning(uuid_128 uuid, uint8_t reason)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device being provisioned|
|uint8_t|[in]|reason|Reason for aborting. Values are as follows:<br/><br/>- **1:** Invalid PDU<br/>- **2:** Invalid PDU format<br/>- **3:** Unexpected PDU<br/>- **4:** Confirmation failed<br/>- **5:** Out of resources<br/>- **6:** Decryption failed<br/>- **7:** Unexpected error<br/>- **8:** Unable to assign address|

Abort provisioning. This command is typically used after the suspension indicated by [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_prov_set_device_address

`sl_status_t sl_btmesh_prov_set_device_address(uuid_128 uuid, uint16_t address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device being provisioned|
|uint16_t|[in]|address|Unicast address to be assigned for the primary element of the node.|

Set the address for the device after the provisioning has been suspended, as indicated by [sl_btmesh_evt_prov_provisioning_suspended](sl-btmesh-evt-prov-provisioning-suspended) event.

Note the following: every element of the device is assigned an address when a device is successfully provisioned. The primary element is assigned the address given by this command, while the following elements are assigned addresses in a consecutive sequence. Care must be taken to give the device a primary address so that the range of addresses it receives does not overlap with any other active device's address range.

Note also that on reusing an address range that was previously used by another device that is no longer active in the network, an IV index update must have been fully completed in between device removal and address reuse. Otherwise, messages sent by the new device may be considered as replay attacks and be discarded by the receiving nodes.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_prov_create_network

`sl_status_t sl_btmesh_prov_create_network(uint16_t netkey_index, size_t key_len, const uint8_t *key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index to use for network key. Allowed values are from 0x000 to 0xfff.|
|size_t|[in]|key_len|Length of data in `key`|
|const uint8_t *|[in]|key|Key value to use. Set to zero-length array to generate a random key.|

Create a new network key on the Provisioner.

The created key can be deployed on a node using the [sl_btmesh_config_client_add_netkey](sl-btmesh-config-client#sl-btmesh-config-client-add-netkey) command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_create_appkey

`sl_status_t sl_btmesh_prov_create_appkey(uint16_t netkey_index, uint16_t appkey_index, size_t key_len, const uint8_t *key, size_t max_application_key_size, size_t *application_key_len, uint8_t *application_key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key to which the application key will be bound|
|uint16_t|[in]|appkey_index|Index to use for application key. Allowed values are from 0x000 to 0xfff.|
|size_t|[in]|key_len|Length of data in `key`|
|const uint8_t *|[in]|key|Key value to use; set to zero-length array to generate random key.|
|size_t|[in]|max_application_key_size|Size of output buffer passed in `application_key`|
|size_t *|[out]|application_key_len|On return, set to the length of output data written to `application_key`|
|uint8_t *|[out]|application_key|New application key. Ignore it if the result was non-zero.|

Create a new application key on the Provisioner.

An application key is always bound to a network key. In other words, the application key is only valid in the context of a particular network key. The selected network key must exist on the Provisioner (see [sl_btmesh_prov_create_network](sl-btmesh-prov#sl-btmesh-prov-create-network) command).

The created application key can be deployed on a node using the [sl_btmesh_config_client_add_appkey](sl-btmesh-config-client#sl-btmesh-config-client-add-appkey) command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_send_oob_pkey_response

`sl_status_t sl_btmesh_prov_send_oob_pkey_response(uuid_128 uuid, size_t pkey_len, const uint8_t *pkey)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device|
|size_t|[in]|pkey_len|Length of data in `pkey`|
|const uint8_t *|[in]|pkey|Public Key read out-of-band|

Respond to the prov_oob_pkey_request.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_send_oob_auth_response

`sl_status_t sl_btmesh_prov_send_oob_auth_response(uuid_128 uuid, size_t data_len, const uint8_t *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device|
|size_t|[in]|data_len|Length of data in `data`|
|const uint8_t *|[in]|data|Raw 16-byte or 32-byte array containing the static or output authentication data. The length of the data depends on the chosen provisioning algorithm; see [sl_btmesh_evt_prov_start_sent](sl-btmesh-evt-prov-start-sent) event for details on how to determine which provisioning algorithm was chosen.<br/><br/>Note that the raw data given to the stack must be encoded in the manner described in the Mesh Protocol 1.1 specifcation Section 5.4.2.4. Whether the output data should be treated as Numeric or Alphanumeric depends on the selected output action. The data type for Static OOB authentication data is Binary.|

Respond to the prov_oob_auth_request.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_set_oob_requirements

`sl_status_t sl_btmesh_prov_set_oob_requirements(uuid_128 uuid, uint8_t public_key, uint8_t auth_methods, uint16_t output_actions, uint16_t input_actions, uint8_t min_size, uint8_t max_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device being provisioned|
|uint8_t|[in]|public_key|The public key. Set to zero if the provisioning does not use OOB public Key.|
|uint8_t|[in]|auth_methods|Enum [sl_btmesh_node_auth_method_flag_t](sl-btmesh-node#sl-btmesh-node-auth-method-flag-t). Allowed OOB authentication methods The value is a bitmap so that multiple methods can be supported.|
|uint16_t|[in]|output_actions|Enum [sl_btmesh_node_oob_output_action_flag_t](sl-btmesh-node#sl-btmesh-node-oob-output-action-flag-t). Allowed OOB Output Action types|
|uint16_t|[in]|input_actions|Enum [sl_btmesh_node_oob_input_action_flag_t](sl-btmesh-node#sl-btmesh-node-oob-input-action-flag-t). Allowed OOB Input Action types|
|uint8_t|[in]|min_size|Minimum input/output OOB size. Values range from 0 (input/output OOB not used) to 8.|
|uint8_t|[in]|max_size|Maximum input/output OOB size. Must be larger than or equal to the minimum size. Values range from 0 (input/output OOB not used) to 8.|

Set the OOB requirements for a device being provisioned. This command can be issued after [sl_btmesh_prov_create_provisioning_session](sl-btmesh-prov#sl-btmesh-prov-create-provisioning-session).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_start_key_refresh

`sl_status_t sl_btmesh_prov_start_key_refresh(uint16_t netkey_index, uint8_t num_appkeys, size_t appkey_indices_len, const uint8_t *appkey_indices)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key to update|
|uint8_t|[in]|num_appkeys|Number of application keys to update; may be zero.|
|size_t|[in]|appkey_indices_len|Length of data in `appkey_indices`|
|const uint8_t *|[in]|appkey_indices|Indices of the application keys to update, represented as little endian two byte sequences. The array must contain num_appkeys indices and therefore 2*num_appkeys bytes total.|

Start a key refresh procedure in the network.

A key refresh procedure updates a network key and, optionally, application keys associated with it in all nodes of the network except for excluded nodes. After the refresh procedure is complete, the old keys will be discarded. Therefore, the excluded nodes, which did not receive new keys will be shut out of the network at the completion of the procedure.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_key_refresh_node_update](sl-btmesh-evt-prov-key-refresh-node-update)
- [sl_btmesh_evt_prov_key_refresh_phase_update](sl-btmesh-evt-prov-key-refresh-phase-update)
- [sl_btmesh_evt_prov_key_refresh_complete](sl-btmesh-evt-prov-key-refresh-complete)

##### sl_btmesh_prov_get_key_refresh_exclusion

`sl_status_t sl_btmesh_prov_get_key_refresh_exclusion(uint16_t key, uuid_128 uuid, uint8_t *status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key|Network key index|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device|
|uint8_t *|[out]|status|Non-zero for excluded node|

Check the key refresh exclusion status of a node. Excluded nodes do not participate in the key refresh procedure and can therefore be shut out of the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_set_key_refresh_exclusion

`sl_status_t sl_btmesh_prov_set_key_refresh_exclusion(uint16_t key, uint8_t status, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key|Network key index|
|uint8_t|[in]|status|Non-zero for excluded node|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device|

Set the key refresh exclusion status of a node. Excluded nodes do not participate in the key refresh procedure and can therefore be shut out of the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_set_key_refresh_failure

`sl_status_t sl_btmesh_prov_set_key_refresh_failure(uint16_t key, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key|Network key index|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device|

Mark the node as failed for the keyrefresh. This function should be called if the provisioner knows that the node has become unresponsive for some external reason (such as factory reset performed by the end user), and will not respond to key refresh messages even after a long delay. Note that if a node drops out of the key refresh procedure, it will not be possible to communicate with the node using the key that was refreshed during the key refresh procedure.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_phase_timeout_get

`sl_status_t sl_btmesh_prov_phase_timeout_get(uint32_t *phase_timeout_s)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *|[out]|phase_timeout_s|Value to get in seconds|

Get the phase_timeout_s parameter that will be used for the start key refresh command. A node fails the key refresh procedure phase, if it doesnt reply to the provisioner during the timeout.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_phase_timeout_set

`sl_status_t sl_btmesh_prov_phase_timeout_set(uint32_t phase_timeout_s)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|phase_timeout_s|Value to be set in seconds|

Set the phase_timeout_s parameter that will be used for the start key refresh command. A node fails the key refresh procedure phase, if it doesnt reply to the provisioner during the timeout. Maximum allowed value is 345600 sec (4days).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_get_ddb_entry

`sl_status_t sl_btmesh_prov_get_ddb_entry(uuid_128 uuid, aes_key_128 *device_key, uint16_t *netkey_index, uint16_t *address, uint8_t *elements)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device to retrieve|
|[aes_key_128](aes-key-128) *|[out]|device_key|Device Key|
|uint16_t *|[out]|netkey_index|Index of the network key with which the node was initially provisioned. Used for network-level encryption of Configuration Client messages.|
|uint16_t *|[out]|address|Unicast address of the primary element of the node|
|uint8_t *|[out]|elements|Number of elements in the node|

Get a Provisioner device database entry with a matching UUID.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_delete_ddb_entry

`sl_status_t sl_btmesh_prov_delete_ddb_entry(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the node to delete|

Delete the node information from the Provisioner database. Note that a successful result from this command only means the command has been accepted for processing. The status of the actual operation will be returned in the following event; application should not make new BGAPI requests until the event is received. Note also that this should be followed by a [sl_btmesh_prov_start_key_refresh](sl-btmesh-prov#sl-btmesh-prov-start-key-refresh) updating the keys of the remaining nodes to make sure the deleted node is shut off from the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_delete_ddb_entry_complete](sl-btmesh-evt-prov-delete-ddb-entry-complete)

##### sl_btmesh_prov_add_ddb_entry

`sl_status_t sl_btmesh_prov_add_ddb_entry(uuid_128 uuid, aes_key_128 device_key, uint16_t netkey_index, uint16_t address, uint8_t elements)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the node to add|
|[aes_key_128](aes-key-128)|[in]|device_key|Device key value for the node|
|uint16_t|[in]|netkey_index|Index of the network key the node will be used for configuration|
|uint16_t|[in]|address|Unicast address to allocate for the node's primary element|
|uint8_t|[in]|elements|Number of elements the device has|

Add a new node entry to the Provisioner's device database. Note that a successful result from this command only means the command has been accepted for processing. The status of the actual operation will be returned in the following event; application should not make new BGAPI requests until the event is received. Note also that the device key, primary element address, and network key need to be deployed to the node being added to ensure it's configurable. See [sl_btmesh_node_set_provisioning_data](sl-btmesh-node#sl-btmesh-node-set-provisioning-data) command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_add_ddb_entry_complete](sl-btmesh-evt-prov-add-ddb-entry-complete)

##### sl_btmesh_prov_list_ddb_entries

`SL_BGAPI_DEPRECATED sl_status_t sl_btmesh_prov_list_ddb_entries(uint16_t *count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|count|Number of events that will follow|

List nodes known by this Provisioner. A number of [sl_btmesh_evt_prov_ddb_list](sl-btmesh-evt-prov-ddb-list) events will be generated. This is a deprecated function. Please use [sl_btmesh_prov_get_ddb_entry_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-count) and [sl_btmesh_prov_get_ddb_entry_by_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-by-count) instead.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_ddb_list](sl-btmesh-evt-prov-ddb-list)

##### sl_btmesh_prov_initialize_network

`sl_status_t sl_btmesh_prov_initialize_network(uint16_t address, uint32_t ivi)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Address to assign for provisioner.|
|uint32_t|[in]|ivi|IV index of the network.|

Initialize the mesh network and assign the provisioner address and IV index for the network. If this command is not invoked prior to invoking [sl_btmesh_prov_create_network](sl-btmesh-prov#sl-btmesh-prov-create-network), the network will be initialized with default address and IV index.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_get_key_refresh_appkey_exclusion

`sl_status_t sl_btmesh_prov_get_key_refresh_appkey_exclusion(uint16_t netkey_index, uint16_t appkey_index, uuid_128 uuid, uint8_t *status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key index|
|uint16_t|[in]|appkey_index|Application key index|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device|
|uint8_t *|[out]|status|Non-zero for excluded node|

Check the application key refresh exclusion status of a node. Nodes which are excluded for a given application key do not receive updates for that particular application key, but do participate in the key refresh procedure as a whole. This enables the Provisioner to set up and update restricted sets of application keys across nodes.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_set_key_refresh_appkey_exclusion

`sl_status_t sl_btmesh_prov_set_key_refresh_appkey_exclusion(uint16_t netkey_index, uint16_t appkey_index, uint8_t status, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key index|
|uint16_t|[in]|appkey_index|Application key index|
|uint8_t|[in]|status|Non-zero for excluded node|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device|

Set the application key refresh exclusion status of a node. Nodes which are excluded for a given application key do not receive updates for that particular application key, but do participate in the key refresh procedure as a whole. This enables the Provisioner to set up and update restricted sets of application keys across nodes.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_stop_scan_unprov_beacons

`sl_status_t sl_btmesh_prov_stop_scan_unprov_beacons(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Stop scanning for unprovisioned device beacons.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_update_device_netkey_index

`sl_status_t sl_btmesh_prov_update_device_netkey_index(uuid_128 uuid, uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the node|
|uint16_t|[in]|netkey_index|Index of the network key used in configuring the node.|

Update a node's entry in the Provisioner's device database by setting a new value to the netkey_index field. The netkey_index field is used to determine the network key to use when encrypting and decrypting configuration model messages to and from the node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_suspend_key_refresh

`sl_status_t sl_btmesh_prov_suspend_key_refresh(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key identifying an ongoing key refresh procedure|

Suspend an ongoing key refresh procedure.

Suspending a key refresh procedure means no further requests for updating keys or setting key refresh phase will be sent to the network by the Provisioner until the key refresh procedure is resumed.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_resume_key_refresh

`sl_status_t sl_btmesh_prov_resume_key_refresh(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key identifying a suspended key refresh procedure|

Resume a suspended key refresh procedure.

By resuming a suspended key refresh procedure, the Provisioner will again start to send requests for updating keys or setting key refresh phase to the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_get_key_refresh_phase

`sl_status_t sl_btmesh_prov_get_key_refresh_phase(uint16_t netkey_index, uint8_t *phase)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key identifying an ongoing key refresh procedure|
|uint8_t *|[out]|phase|The current key refresh phase. Values are as follows:<br/><br/>- 0: Normal operation (no ongoing key refresh)<br/>- 1: First phase of key refresh procedure (key deployment)<br/>- 2: Second phase of key refresh procedure (new key activation)<br/>- 3: Third phase of key refresh procedure (old key deletion)|

Get the key refresh phase of an ongoing key refresh procedure.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_start_key_refresh_from_phase

`sl_status_t sl_btmesh_prov_start_key_refresh_from_phase(uint8_t phase, uint16_t netkey_index, uint8_t num_appkeys, size_t appkey_indices_len, const uint8_t *appkey_indices)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|phase|Current key refresh phase|
|uint16_t|[in]|netkey_index|Index of the network key identifying a key refresh procedure|
|uint8_t|[in]|num_appkeys|Number of application keys to update; may be zero.|
|size_t|[in]|appkey_indices_len|Length of data in `appkey_indices`|
|const uint8_t *|[in]|appkey_indices|Indices of the application keys to update, represented as little endian two byte sequences. The array must contain num_appkeys indices and therefore 2*num_appkeys bytes total.|

Start a key refresh procedure from a non-default phase. Before calling this function, keys to be used in the key refresh procedure should have been specified by calling [sl_btmesh_config_client_prepare_key_refresh](sl-btmesh-config-client#sl-btmesh-config-client-prepare-key-refresh) command.

Note that this command should not normally be used. It is intended only for resuming an interrupted key refresh procedure on a backup Provisioner when the original Provisioner, that started the key refresh procedure, is no longer available to complete the procedure.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_key_refresh_node_update](sl-btmesh-evt-prov-key-refresh-node-update)
- [sl_btmesh_evt_prov_key_refresh_phase_update](sl-btmesh-evt-prov-key-refresh-phase-update)
- [sl_btmesh_evt_prov_key_refresh_complete](sl-btmesh-evt-prov-key-refresh-complete)

##### sl_btmesh_prov_flush_key_refresh_state

`sl_status_t sl_btmesh_prov_flush_key_refresh_state(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key identifying a key refresh procedure|

Clear the key refresh state stored in persistent storage.

Note that this command should not normally be used. It is intended only for clearing stored key refresh state when a key refresh procedure has been suspended and will not be resumed, either because the network key has been deleted from all nodes or the responsibility for completing the key refresh has been moved to another Provisioner.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_get_provisioning_records_list

`sl_status_t sl_btmesh_prov_get_provisioning_records_list(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device being provisioned|

Get the list of provisioning records on the device. This command can be issued when provisioning is suspended after the provisioning session has been opened, but no earlier or later. The list of provisioning records on the device will be delivered with the [sl_btmesh_evt_prov_provisioning_records_list](sl-btmesh-evt-prov-provisioning-records-list) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_provisioning_records_list](sl-btmesh-evt-prov-provisioning-records-list)

##### sl_btmesh_prov_get_provisioning_record_data

`sl_status_t sl_btmesh_prov_get_provisioning_record_data(uuid_128 uuid, uint16_t record)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the Device being provisioned|
|uint16_t|[in]|record|Provisioning record ID|

Get provisioning record data from the device. This command can be issued when provisioning is suspended after the provisioning session has been opened, but no earlier or later. The provisioning record data will be delivered with the [sl_btmesh_evt_prov_provisioning_record_data](sl-btmesh-evt-prov-provisioning-record-data) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_prov_provisioning_record_data](sl-btmesh-evt-prov-provisioning-record-data)

##### sl_btmesh_prov_init_provisioning_records

`sl_status_t sl_btmesh_prov_init_provisioning_records(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize provisioning record retrieval functionality on the Provisioner. This must be called before trying to retrieve provisioning records list or individual record data.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_get_ddb_entry_count

`sl_status_t sl_btmesh_prov_get_ddb_entry_count(uint16_t *count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|count|Number of entries in the device database.|

Get the count of Provisioner device database entries.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_prov_get_ddb_entry_by_count

`sl_status_t sl_btmesh_prov_get_ddb_entry_by_count(uint16_t which, uuid_128 *uuid, aes_key_128 *device_key, uint16_t *netkey_index, uint16_t *address, uint8_t *elements)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|which|Ordinal for the entry to retrieve; must be smaller than the entry count returned by [sl_btmesh_prov_get_ddb_entry_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-count)|
|[uuid_128](uuid-128) *|[out]|uuid|UUID of the device|
|[aes_key_128](aes-key-128) *|[out]|device_key|Device Key|
|uint16_t *|[out]|netkey_index|Index of the network key with which the node was initially provisioned. Used for network-level encryption of Configuration Client messages.|
|uint16_t *|[out]|address|Unicast address of the primary element of the node|
|uint8_t *|[out]|elements|Number of elements in the node|

Get a Provisioner device database entry by ordinal number. Note that if items are added or removed while the entries in the device database are being iterated using this API, the API does not guarantee that each item will be reported, or that each item will be reported only once.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_prov_init_id 0x00150028`

`#define sl_btmesh_cmd_prov_scan_unprov_beacons_id 0x01150028`

`#define sl_btmesh_cmd_prov_create_provisioning_session_id 0x41150028`

`#define sl_btmesh_cmd_prov_set_provisioning_suspend_event_id 0x42150028`

`#define sl_btmesh_cmd_prov_provision_adv_device_id 0x43150028`

`#define sl_btmesh_cmd_prov_provision_gatt_device_id 0x44150028`

`#define sl_btmesh_cmd_prov_provision_remote_device_id 0x7f150028`

`#define sl_btmesh_cmd_prov_continue_provisioning_id 0x45150028`

`#define sl_btmesh_cmd_prov_abort_provisioning_id 0x47150028`

`#define sl_btmesh_cmd_prov_set_device_address_id 0x46150028`

`#define sl_btmesh_cmd_prov_create_network_id 0x03150028`

`#define sl_btmesh_cmd_prov_create_appkey_id 0x07150028`

`#define sl_btmesh_cmd_prov_send_oob_pkey_response_id 0x08150028`

`#define sl_btmesh_cmd_prov_send_oob_auth_response_id 0x09150028`

`#define sl_btmesh_cmd_prov_set_oob_requirements_id 0x0a150028`

`#define sl_btmesh_cmd_prov_start_key_refresh_id 0x0b150028`

`#define sl_btmesh_cmd_prov_get_key_refresh_exclusion_id 0x0c150028`

`#define sl_btmesh_cmd_prov_set_key_refresh_exclusion_id 0x0d150028`

`#define sl_btmesh_cmd_prov_set_key_refresh_failure_id 0x12150028`

`#define sl_btmesh_cmd_prov_phase_timeout_get_id 0x10150028`

`#define sl_btmesh_cmd_prov_phase_timeout_set_id 0x11150028`

`#define sl_btmesh_cmd_prov_get_ddb_entry_id 0x16150028`

`#define sl_btmesh_cmd_prov_delete_ddb_entry_id 0x17150028`

`#define sl_btmesh_cmd_prov_add_ddb_entry_id 0x18150028`

`#define sl_btmesh_cmd_prov_list_ddb_entries_id 0x19150028`

`#define sl_btmesh_cmd_prov_initialize_network_id 0x37150028`

`#define sl_btmesh_cmd_prov_get_key_refresh_appkey_exclusion_id 0x38150028`

`#define sl_btmesh_cmd_prov_set_key_refresh_appkey_exclusion_id 0x39150028`

`#define sl_btmesh_cmd_prov_stop_scan_unprov_beacons_id 0x3a150028`

`#define sl_btmesh_cmd_prov_update_device_netkey_index_id 0x3b150028`

`#define sl_btmesh_cmd_prov_suspend_key_refresh_id 0x3c150028`

`#define sl_btmesh_cmd_prov_resume_key_refresh_id 0x3d150028`

`#define sl_btmesh_cmd_prov_get_key_refresh_phase_id 0x3e150028`

`#define sl_btmesh_cmd_prov_start_key_refresh_from_phase_id 0x3f150028`

`#define sl_btmesh_cmd_prov_flush_key_refresh_state_id 0x40150028`

`#define sl_btmesh_cmd_prov_get_provisioning_records_list_id 0x1c150028`

`#define sl_btmesh_cmd_prov_get_provisioning_record_data_id 0x1d150028`

`#define sl_btmesh_cmd_prov_init_provisioning_records_id 0x1e150028`

`#define sl_btmesh_cmd_prov_get_ddb_entry_count_id 0x49150028`

`#define sl_btmesh_cmd_prov_get_ddb_entry_by_count_id 0x4a150028`

`#define sl_btmesh_rsp_prov_init_id 0x00150028`

`#define sl_btmesh_rsp_prov_scan_unprov_beacons_id 0x01150028`

`#define sl_btmesh_rsp_prov_create_provisioning_session_id 0x41150028`

`#define sl_btmesh_rsp_prov_set_provisioning_suspend_event_id 0x42150028`

`#define sl_btmesh_rsp_prov_provision_adv_device_id 0x43150028`

`#define sl_btmesh_rsp_prov_provision_gatt_device_id 0x44150028`

`#define sl_btmesh_rsp_prov_provision_remote_device_id 0x7f150028`

`#define sl_btmesh_rsp_prov_continue_provisioning_id 0x45150028`

`#define sl_btmesh_rsp_prov_abort_provisioning_id 0x47150028`

`#define sl_btmesh_rsp_prov_set_device_address_id 0x46150028`

`#define sl_btmesh_rsp_prov_create_network_id 0x03150028`

`#define sl_btmesh_rsp_prov_create_appkey_id 0x07150028`

`#define sl_btmesh_rsp_prov_send_oob_pkey_response_id 0x08150028`

`#define sl_btmesh_rsp_prov_send_oob_auth_response_id 0x09150028`

`#define sl_btmesh_rsp_prov_set_oob_requirements_id 0x0a150028`

`#define sl_btmesh_rsp_prov_start_key_refresh_id 0x0b150028`

`#define sl_btmesh_rsp_prov_get_key_refresh_exclusion_id 0x0c150028`

`#define sl_btmesh_rsp_prov_set_key_refresh_exclusion_id 0x0d150028`

`#define sl_btmesh_rsp_prov_set_key_refresh_failure_id 0x12150028`

`#define sl_btmesh_rsp_prov_phase_timeout_get_id 0x10150028`

`#define sl_btmesh_rsp_prov_phase_timeout_set_id 0x11150028`

`#define sl_btmesh_rsp_prov_get_ddb_entry_id 0x16150028`

`#define sl_btmesh_rsp_prov_delete_ddb_entry_id 0x17150028`

`#define sl_btmesh_rsp_prov_add_ddb_entry_id 0x18150028`

`#define sl_btmesh_rsp_prov_list_ddb_entries_id 0x19150028`

`#define sl_btmesh_rsp_prov_initialize_network_id 0x37150028`

`#define sl_btmesh_rsp_prov_get_key_refresh_appkey_exclusion_id 0x38150028`

`#define sl_btmesh_rsp_prov_set_key_refresh_appkey_exclusion_id 0x39150028`

`#define sl_btmesh_rsp_prov_stop_scan_unprov_beacons_id 0x3a150028`

`#define sl_btmesh_rsp_prov_update_device_netkey_index_id 0x3b150028`

`#define sl_btmesh_rsp_prov_suspend_key_refresh_id 0x3c150028`

`#define sl_btmesh_rsp_prov_resume_key_refresh_id 0x3d150028`

`#define sl_btmesh_rsp_prov_get_key_refresh_phase_id 0x3e150028`

`#define sl_btmesh_rsp_prov_start_key_refresh_from_phase_id 0x3f150028`

`#define sl_btmesh_rsp_prov_flush_key_refresh_state_id 0x40150028`

`#define sl_btmesh_rsp_prov_get_provisioning_records_list_id 0x1c150028`

`#define sl_btmesh_rsp_prov_get_provisioning_record_data_id 0x1d150028`

`#define sl_btmesh_rsp_prov_init_provisioning_records_id 0x1e150028`

`#define sl_btmesh_rsp_prov_get_ddb_entry_count_id 0x49150028`

`#define sl_btmesh_rsp_prov_get_ddb_entry_by_count_id 0x4a150028`

#### OOB Capabilities

OOB capability bitmask constants 

##### Macros

`#define SL_BTMESH_PROV_OOB_OTHER 0x1`

**Description**: Uncategorized

`#define SL_BTMESH_PROV_OOB_URI 0x2`

**Description**: URI or other electronic

`#define SL_BTMESH_PROV_OOB_2D_MR_CODE 0x4`

**Description**: 2D machine-readable code

`#define SL_BTMESH_PROV_OOB_BAR_CODE 0x8`

**Description**: Barcode

`#define SL_BTMESH_PROV_OOB_NFC 0x10`

**Description**: NFC

`#define SL_BTMESH_PROV_OOB_NUMBER 0x20`

**Description**: Number

`#define SL_BTMESH_PROV_OOB_STRING 0x40`

**Description**: String

`#define SL_BTMESH_PROV_OOB_RFU_7 0x80`

**Description**: Reserved

`#define SL_BTMESH_PROV_OOB_RFU_8 0x100`

**Description**: Reserved

`#define SL_BTMESH_PROV_OOB_RFU_9 0x200`

**Description**: Reserved

`#define SL_BTMESH_PROV_OOB_RFU_A 0x400`

**Description**: Reserved

`#define SL_BTMESH_PROV_OOB_LOC_ON_BOX 0x800`

**Description**: On the box

`#define SL_BTMESH_PROV_OOB_LOC_IN_BOX 0x1000`

**Description**: Inside the box

`#define SL_BTMESH_PROV_OOB_LOC_PAPER 0x2000`

**Description**: On a piece of paper

`#define SL_BTMESH_PROV_OOB_LOC_MANUAL 0x4000`

**Description**: In the device manual

`#define SL_BTMESH_PROV_OOB_LOC_DEVICE 0x8000`

**Description**: On the device

`#define SL_BTMESH_PROV_OOB_RFU_MASK 0x780`

**Description**: Mask of reserved bits

#### sl_btmesh_evt_prov_initialized

Provisioner is initialized and operational. 

##### Modules

[sl_btmesh_evt_prov_initialized_s](sl-btmesh-evt-prov-initialized-s)

##### Typedefs

###### sl_btmesh_evt_prov_initialized_t

`typedef struct sl_btmesh_evt_prov_initialized_s sl_btmesh_evt_prov_initialized_t`

##### Macros

`#define sl_btmesh_evt_prov_initialized_id 0x001500a8`

**Description**: Identifier of the initialized event.

Data structure of the initialized event. 

###### Public Attributes

###### networks (heading level 7)

```
uint8_t sl_btmesh_evt_prov_initialized_s::networks
```

**Details:** Number of network keys that the Provisioner has

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_prov_initialized_s::address
```

**Details:** Unicast address of the primary element of the Provisioner

###### iv_index (heading level 7)

```
uint32_t sl_btmesh_evt_prov_initialized_s::iv_index
```

**Details:** IVI for network primary network (index 0)

#### sl_btmesh_evt_prov_provisioning_suspended

Provisioning suspended. 

##### Modules

[sl_btmesh_evt_prov_provisioning_suspended_s](sl-btmesh-evt-prov-provisioning-suspended-s)

##### Typedefs

###### sl_btmesh_evt_prov_provisioning_suspended_t

`typedef struct sl_btmesh_evt_prov_provisioning_suspended_s sl_btmesh_evt_prov_provisioning_suspended_t`

##### Macros

`#define sl_btmesh_evt_prov_provisioning_suspended_id 0x181500a8`

**Description**: Identifier of the provisioning_suspended event.

Data structure of the provisioning_suspended event. 

###### Public Attributes

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_provisioning_suspended_s::uuid
```

**Details:** UUID of the device

###### reason (heading level 7)

```
uint8_t sl_btmesh_evt_prov_provisioning_suspended_s::reason
```

**Details:** Reason for suspension. Values are as follows:

- **0:** Capabilities Event received
- **1:** Provisioning link opened

#### sl_btmesh_evt_prov_capabilities

Provisioning capabilities message. 

##### Modules

[sl_btmesh_evt_prov_capabilities_s](sl-btmesh-evt-prov-capabilities-s)

##### Typedefs

###### sl_btmesh_evt_prov_capabilities_t

`typedef struct sl_btmesh_evt_prov_capabilities_s sl_btmesh_evt_prov_capabilities_t`

##### Macros

`#define sl_btmesh_evt_prov_capabilities_id 0x171500a8`

**Description**: Identifier of the capabilities event.

Data structure of the capabilities event. 

###### Public Attributes

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_capabilities_s::uuid
```

**Details:** UUID of the device being provisioned

###### elements (heading level 7)

```
uint8_t sl_btmesh_evt_prov_capabilities_s::elements
```

**Details:** Number of elements supported by the device

###### algorithms (heading level 7)

```
uint16_t sl_btmesh_evt_prov_capabilities_s::algorithms
```

**Details:** Supported algorithms and other capabilities.

###### pkey_type (heading level 7)

```
uint8_t sl_btmesh_evt_prov_capabilities_s::pkey_type
```

**Details:** Supported public key types

###### static_oob_type (heading level 7)

```
uint8_t sl_btmesh_evt_prov_capabilities_s::static_oob_type
```

**Details:** Supported static OOB Types

###### ouput_oob_size (heading level 7)

```
uint8_t sl_btmesh_evt_prov_capabilities_s::ouput_oob_size
```

**Details:** Maximum size of Output OOB supported

###### output_oob_action (heading level 7)

```
uint16_t sl_btmesh_evt_prov_capabilities_s::output_oob_action
```

**Details:** Supported Output OOB Actions

###### input_oob_size (heading level 7)

```
uint8_t sl_btmesh_evt_prov_capabilities_s::input_oob_size
```

**Details:** Maximum size of input OOB supported

###### intput_oob_action (heading level 7)

```
uint16_t sl_btmesh_evt_prov_capabilities_s::intput_oob_action
```

**Details:** Supported input OOB Actions

#### sl_btmesh_evt_prov_provisioning_failed

Provisioning a device failed. 

##### Modules

[sl_btmesh_evt_prov_provisioning_failed_s](sl-btmesh-evt-prov-provisioning-failed-s)

##### Typedefs

###### sl_btmesh_evt_prov_provisioning_failed_t

`typedef struct sl_btmesh_evt_prov_provisioning_failed_s sl_btmesh_evt_prov_provisioning_failed_t`

##### Macros

`#define sl_btmesh_evt_prov_provisioning_failed_id 0x011500a8`

**Description**: Identifier of the provisioning_failed event.

Data structure of the provisioning_failed event. 

###### Public Attributes

###### reason (heading level 7)

```
uint8_t sl_btmesh_evt_prov_provisioning_failed_s::reason
```

**Details:** Reason for failure. Values are as follows:

- **0:** Link closed
- **1:** Invalid PDU
- **2:** Invalid PDU format
- **3:** Unexpected PDU
- **4:** Confirmation failed
- **5:** Out of resources
- **6:** Decryption failed
- **7:** Unexpected error
- **8:** Unable to assign address

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_provisioning_failed_s::uuid
```

**Details:** UUID of the device

#### sl_btmesh_evt_prov_device_provisioned

Device provisioned successfully. 

##### Modules

[sl_btmesh_evt_prov_device_provisioned_s](sl-btmesh-evt-prov-device-provisioned-s)

##### Typedefs

###### sl_btmesh_evt_prov_device_provisioned_t

`typedef struct sl_btmesh_evt_prov_device_provisioned_s sl_btmesh_evt_prov_device_provisioned_t`

##### Macros

`#define sl_btmesh_evt_prov_device_provisioned_id 0x021500a8`

**Description**: Identifier of the device_provisioned event.

Data structure of the device_provisioned event. 

###### Public Attributes

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_prov_device_provisioned_s::address
```

**Details:** Address assigned to the node's primary element. If the node has multiple elements, they have been assigned an address in a consecutive sequence following the primary element address.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_device_provisioned_s::uuid
```

**Details:** UUID of the device

#### sl_btmesh_evt_prov_unprov_beacon

Unprovisioned beacon seen. 

##### Modules

[sl_btmesh_evt_prov_unprov_beacon_s](sl-btmesh-evt-prov-unprov-beacon-s)

##### Typedefs

###### sl_btmesh_evt_prov_unprov_beacon_t

`typedef struct sl_btmesh_evt_prov_unprov_beacon_s sl_btmesh_evt_prov_unprov_beacon_t`

##### Macros

`#define sl_btmesh_evt_prov_unprov_beacon_id 0x031500a8`

**Description**: Identifier of the unprov_beacon event.

Data structure of the unprov_beacon event. 

###### Public Attributes

###### oob_capabilities (heading level 7)

```
uint16_t sl_btmesh_evt_prov_unprov_beacon_s::oob_capabilities
```

**Details:** OOB capabilities bitfield, which indicates the means by which out-of-band provisioning data may be retrieved. See [OOB Capabilities](sl-btmesh-prov-oob-capabilities).

###### uri_hash (heading level 7)

```
uint32_t sl_btmesh_evt_prov_unprov_beacon_s::uri_hash
```

**Details:** Hash of the out-of-band URI, which is received in [sl_btmesh_evt_prov_uri](sl-btmesh-evt-prov-uri). If the URI bit (bit 1) is not set in the OOB capabilities bitfield, this field is ignored.

###### bearer (heading level 7)

```
uint8_t sl_btmesh_evt_prov_unprov_beacon_s::bearer
```

**Details:** Bearer on which the beacon was seen. Values are as follows:

- **0:** PB-ADV
- **1:** PB-GATT

###### address (heading level 7)

```
bd_addr sl_btmesh_evt_prov_unprov_beacon_s::address
```

**Details:** Address of the device beaconing

###### address_type (heading level 7)

```
uint8_t sl_btmesh_evt_prov_unprov_beacon_s::address_type
```

**Details:** Beaconing device address type. Values:

- **0:** Public address
- **1:** Random address

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_unprov_beacon_s::uuid
```

**Details:** 16-byte UUID of the beaconing device.

###### rssi (heading level 7)

```
int8_t sl_btmesh_evt_prov_unprov_beacon_s::rssi
```

**Details:** RSSI value of the beacon seen. Units: dBm.

#### sl_btmesh_evt_prov_oob_pkey_request

The Provisioner needs the OOB public key of the Device with given UUID. 

Input the key using prov_oob_pkey_rsp. 

##### Modules

[sl_btmesh_evt_prov_oob_pkey_request_s](sl-btmesh-evt-prov-oob-pkey-request-s)

##### Typedefs

###### sl_btmesh_evt_prov_oob_pkey_request_t

`typedef struct sl_btmesh_evt_prov_oob_pkey_request_s sl_btmesh_evt_prov_oob_pkey_request_t`

##### Macros

`#define sl_btmesh_evt_prov_oob_pkey_request_id 0x061500a8`

**Description**: Identifier of the oob_pkey_request event.

Data structure of the oob_pkey_request event. 

###### Public Attributes

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_oob_pkey_request_s::uuid
```

**Details:** UUID of the Device

#### sl_btmesh_evt_prov_oob_auth_request

Provide the Provisioner with the device's output or static data using the [sl_btmesh_prov_send_oob_auth_response](sl-btmesh-prov#sl-btmesh-prov-send-oob-auth-response) command. 

##### Modules

[sl_btmesh_evt_prov_oob_auth_request_s](sl-btmesh-evt-prov-oob-auth-request-s)

##### Typedefs

###### sl_btmesh_evt_prov_oob_auth_request_t

`typedef struct sl_btmesh_evt_prov_oob_auth_request_s sl_btmesh_evt_prov_oob_auth_request_t`

##### Macros

`#define sl_btmesh_evt_prov_oob_auth_request_id 0x071500a8`

**Description**: Identifier of the oob_auth_request event.

Data structure of the oob_auth_request event. 

###### Public Attributes

###### output (heading level 7)

```
uint8_t sl_btmesh_evt_prov_oob_auth_request_s::output
```

**Details:** Zero for static data, non-zero for output

###### output_action (heading level 7)

```
uint8_t sl_btmesh_evt_prov_oob_auth_request_s::output_action
```

**Details:** Enum [sl_btmesh_node_oob_output_action_t](sl-btmesh-node#sl-btmesh-node-oob-output-action-t). Output action type. Ignored for Static.

###### output_size (heading level 7)

```
uint8_t sl_btmesh_evt_prov_oob_auth_request_s::output_size
```

**Details:** Size of output data. Ignored for Static.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_oob_auth_request_s::uuid
```

**Details:** UUID of the device

#### sl_btmesh_evt_prov_oob_display_input

Random OOB input data was generated and should be displayed to and input with the device. 

##### Modules

[sl_btmesh_evt_prov_oob_display_input_s](sl-btmesh-evt-prov-oob-display-input-s)

##### Typedefs

###### sl_btmesh_evt_prov_oob_display_input_t

`typedef struct sl_btmesh_evt_prov_oob_display_input_s sl_btmesh_evt_prov_oob_display_input_t`

##### Macros

`#define sl_btmesh_evt_prov_oob_display_input_id 0x081500a8`

**Description**: Identifier of the oob_display_input event.

Data structure of the oob_display_input event. 

###### Public Attributes

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_oob_display_input_s::uuid
```

**Details:** UUID of the device

###### input_action (heading level 7)

```
uint8_t sl_btmesh_evt_prov_oob_display_input_s::input_action
```

**Details:** Enum [sl_btmesh_node_oob_input_action_t](sl-btmesh-node#sl-btmesh-node-oob-input-action-t). Input action type

###### input_size (heading level 7)

```
uint8_t sl_btmesh_evt_prov_oob_display_input_s::input_size
```

**Details:** Number of digits or characters

###### data (heading level 7)

```
uint8array sl_btmesh_evt_prov_oob_display_input_s::data
```

**Details:** Raw 16-byte or 32-byte array containing the input authentication data. The length of the data depends on the chosen provisioning algorithm; see [sl_btmesh_evt_prov_start_sent](sl-btmesh-evt-prov-start-sent) event for details on how to determine which provisioning algorithm was chosen.

Note that the raw data is encoded in the manner described in the Mesh Protocol 1.1 specifcation Section 5.4.2.4, and must be converted to a human-readable format for displaying. Whether the data should be treated as Numeric or Alphanumeric depends on the selected input action.

#### sl_btmesh_evt_prov_ddb_list

Provisioner's device database list entry. 

This event is generated by a deprecated function. Please use [sl_btmesh_prov_get_ddb_entry_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-count) and [sl_btmesh_prov_get_ddb_entry_by_count](sl-btmesh-prov#sl-btmesh-prov-get-ddb-entry-by-count) instead. 

##### Modules

[sl_btmesh_evt_prov_ddb_list_s](sl-btmesh-evt-prov-ddb-list-s)

##### Typedefs

###### sl_btmesh_evt_prov_ddb_list_t

`typedef struct sl_btmesh_evt_prov_ddb_list_s sl_btmesh_evt_prov_ddb_list_t`

##### Macros

`#define sl_btmesh_evt_prov_ddb_list_id 0x091500a8`

**Description**: Identifier of the ddb_list event.

Data structure of the ddb_list event. 

###### Public Attributes

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_ddb_list_s::uuid
```

**Details:** UUID of the Device

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_prov_ddb_list_s::address
```

**Details:** Unicast address of the primary element of the node

###### elements (heading level 7)

```
uint8_t sl_btmesh_evt_prov_ddb_list_s::elements
```

**Details:** Number of elements the device has

#### sl_btmesh_evt_prov_uri

URI advertisement received from a nearby device. 

##### Modules

[sl_btmesh_evt_prov_uri_s](sl-btmesh-evt-prov-uri-s)

##### Typedefs

###### sl_btmesh_evt_prov_uri_t

`typedef struct sl_btmesh_evt_prov_uri_s sl_btmesh_evt_prov_uri_t`

##### Macros

`#define sl_btmesh_evt_prov_uri_id 0x0d1500a8`

**Description**: Identifier of the uri event.

Data structure of the uri event. 

###### Public Attributes

###### hash (heading level 7)

```
uint32_t sl_btmesh_evt_prov_uri_s::hash
```

**Details:** URI hash. If a Provisioner is provisioning a device which supports out-of-band provisioning and has supplied a URI hash value in its Unprovisioned Device beacon, the Provisioner should check whether the hash matches this value.

###### data (heading level 7)

```
uint8array sl_btmesh_evt_prov_uri_s::data
```

**Details:** Raw URI data, formatted as specified in Bluetooth Core System Supplement v6.

#### sl_btmesh_evt_prov_key_refresh_phase_update

Key refresh phase change for a network key has occurred. 

This event is generated when all nodes participating in a key refresh procedure have been moved to a new state (or have timed out, dropping them from the key refresh procedure). 

##### Modules

[sl_btmesh_evt_prov_key_refresh_phase_update_s](sl-btmesh-evt-prov-key-refresh-phase-update-s)

##### Typedefs

###### sl_btmesh_evt_prov_key_refresh_phase_update_t

`typedef struct sl_btmesh_evt_prov_key_refresh_phase_update_s sl_btmesh_evt_prov_key_refresh_phase_update_t`

##### Macros

`#define sl_btmesh_evt_prov_key_refresh_phase_update_id 0x141500a8`

**Description**: Identifier of the key_refresh_phase_update event.

Data structure of the key_refresh_phase_update event. 

###### Public Attributes

###### key (heading level 7)

```
uint16_t sl_btmesh_evt_prov_key_refresh_phase_update_s::key
```

**Details:** Network key index

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_prov_key_refresh_phase_update_s::phase
```

**Details:** Phase moved into

#### sl_btmesh_evt_prov_key_refresh_node_update

Key refresh phase change for a node has occurred. 

This event is generated when a particular node has moved to a new key refresh phase. 

##### Modules

[sl_btmesh_evt_prov_key_refresh_node_update_s](sl-btmesh-evt-prov-key-refresh-node-update-s)

##### Typedefs

###### sl_btmesh_evt_prov_key_refresh_node_update_t

`typedef struct sl_btmesh_evt_prov_key_refresh_node_update_s sl_btmesh_evt_prov_key_refresh_node_update_t`

##### Macros

`#define sl_btmesh_evt_prov_key_refresh_node_update_id 0x151500a8`

**Description**: Identifier of the key_refresh_node_update event.

Data structure of the key_refresh_node_update event. 

###### Public Attributes

###### key (heading level 7)

```
uint16_t sl_btmesh_evt_prov_key_refresh_node_update_s::key
```

**Details:** Network key index

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_prov_key_refresh_node_update_s::phase
```

**Details:** Phase moved into

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_key_refresh_node_update_s::uuid
```

**Details:** 16-byte UUID of the node.

###### failure (heading level 7)

```
uint8_t sl_btmesh_evt_prov_key_refresh_node_update_s::failure
```

**Details:** Shows if the node failed the key refresh phase

#### sl_btmesh_evt_prov_key_refresh_complete

Key refresh for a network key has completed. 

##### Modules

[sl_btmesh_evt_prov_key_refresh_complete_s](sl-btmesh-evt-prov-key-refresh-complete-s)

##### Typedefs

###### sl_btmesh_evt_prov_key_refresh_complete_t

`typedef struct sl_btmesh_evt_prov_key_refresh_complete_s sl_btmesh_evt_prov_key_refresh_complete_t`

##### Macros

`#define sl_btmesh_evt_prov_key_refresh_complete_id 0x161500a8`

**Description**: Identifier of the key_refresh_complete event.

Data structure of the key_refresh_complete event. 

###### Public Attributes

###### key (heading level 7)

```
uint16_t sl_btmesh_evt_prov_key_refresh_complete_s::key
```

**Details:** Network key index

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_prov_key_refresh_complete_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

#### sl_btmesh_evt_prov_add_ddb_entry_complete

Adding a DDB entry has been completed. 

See the result code for operation status. 

##### Modules

[sl_btmesh_evt_prov_add_ddb_entry_complete_s](sl-btmesh-evt-prov-add-ddb-entry-complete-s)

##### Typedefs

###### sl_btmesh_evt_prov_add_ddb_entry_complete_t

`typedef struct sl_btmesh_evt_prov_add_ddb_entry_complete_s sl_btmesh_evt_prov_add_ddb_entry_complete_t`

##### Macros

`#define sl_btmesh_evt_prov_add_ddb_entry_complete_id 0x191500a8`

**Description**: Identifier of the add_ddb_entry_complete event.

Data structure of the add_ddb_entry_complete event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_prov_add_ddb_entry_complete_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_add_ddb_entry_complete_s::uuid
```

**Details:** UUID of the Device

#### sl_btmesh_evt_prov_delete_ddb_entry_complete

Deleting a DDB entry has been completed. 

See the result code for operation status. 

##### Modules

[sl_btmesh_evt_prov_delete_ddb_entry_complete_s](sl-btmesh-evt-prov-delete-ddb-entry-complete-s)

##### Typedefs

###### sl_btmesh_evt_prov_delete_ddb_entry_complete_t

`typedef struct sl_btmesh_evt_prov_delete_ddb_entry_complete_s sl_btmesh_evt_prov_delete_ddb_entry_complete_t`

##### Macros

`#define sl_btmesh_evt_prov_delete_ddb_entry_complete_id 0x1a1500a8`

**Description**: Identifier of the delete_ddb_entry_complete event.

Data structure of the delete_ddb_entry_complete event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_prov_delete_ddb_entry_complete_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_delete_ddb_entry_complete_s::uuid
```

**Details:** UUID of the Device

#### sl_btmesh_evt_prov_initialization_failed

Provisioner has not been initialized successfully and is not operational. 

It is not possible to use the device as a Provisioner. See the result code for details. 

##### Modules

[sl_btmesh_evt_prov_initialization_failed_s](sl-btmesh-evt-prov-initialization-failed-s)

##### Typedefs

###### sl_btmesh_evt_prov_initialization_failed_t

`typedef struct sl_btmesh_evt_prov_initialization_failed_s sl_btmesh_evt_prov_initialization_failed_t`

##### Macros

`#define sl_btmesh_evt_prov_initialization_failed_id 0x1b1500a8`

**Description**: Identifier of the initialization_failed event.

Data structure of the initialization_failed event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_prov_initialization_failed_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

#### sl_btmesh_evt_prov_provisioning_records_list

Provisioning records list received, or retrieval failed. 

##### Modules

[sl_btmesh_evt_prov_provisioning_records_list_s](sl-btmesh-evt-prov-provisioning-records-list-s)

##### Typedefs

###### sl_btmesh_evt_prov_provisioning_records_list_t

`typedef struct sl_btmesh_evt_prov_provisioning_records_list_s sl_btmesh_evt_prov_provisioning_records_list_t`

##### Macros

`#define sl_btmesh_evt_prov_provisioning_records_list_id 0x1c1500a8`

**Description**: Identifier of the provisioning_records_list event.

Data structure of the provisioning_records_list event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_prov_provisioning_records_list_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_provisioning_records_list_s::uuid
```

**Details:** UUID of the device

###### list (heading level 7)

```
uint8array sl_btmesh_evt_prov_provisioning_records_list_s::list
```

**Details:** Array of 16-bit provisioning record IDs

#### sl_btmesh_evt_prov_provisioning_record_data

Provisioning record data received, or retrieval failed. 

If successful, record data may be delivered fragmented to several events. The events will be delivered in order. 

##### Modules

[sl_btmesh_evt_prov_provisioning_record_data_s](sl-btmesh-evt-prov-provisioning-record-data-s)

##### Typedefs

###### sl_btmesh_evt_prov_provisioning_record_data_t

`typedef struct sl_btmesh_evt_prov_provisioning_record_data_s sl_btmesh_evt_prov_provisioning_record_data_t`

##### Macros

`#define sl_btmesh_evt_prov_provisioning_record_data_id 0x1d1500a8`

**Description**: Identifier of the provisioning_record_data event.

Data structure of the provisioning_record_data event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_prov_provisioning_record_data_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_provisioning_record_data_s::uuid
```

**Details:** UUID of the device

###### record (heading level 7)

```
uint16_t sl_btmesh_evt_prov_provisioning_record_data_s::record
```

**Details:** Provisioning record ID

###### final (heading level 7)

```
uint8_t sl_btmesh_evt_prov_provisioning_record_data_s::final
```

**Details:** Indicates the end of record data; if zero, more events will follow; if nonzero, this is the final data fragment

###### data (heading level 7)

```
uint8array sl_btmesh_evt_prov_provisioning_record_data_s::data
```

**Details:** Raw provisioning record data or fragment thereof

#### sl_btmesh_evt_prov_start_sent

Provisioning Start PDU sent. 

This diagnostic event shows the algorithm, public key, and authentication choices Provisioner made and communicated to the unprovisioned device. 

##### Modules

[sl_btmesh_evt_prov_start_sent_s](sl-btmesh-evt-prov-start-sent-s)

##### Typedefs

###### sl_btmesh_evt_prov_start_sent_t

`typedef struct sl_btmesh_evt_prov_start_sent_s sl_btmesh_evt_prov_start_sent_t`

##### Macros

`#define sl_btmesh_evt_prov_start_sent_id 0x1e1500a8`

**Description**: Identifier of the start_sent event.

Data structure of the start_sent event. 

###### Public Attributes

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_prov_start_sent_s::uuid
```

**Details:** UUID of the device

###### algorithm (heading level 7)

```
uint8_t sl_btmesh_evt_prov_start_sent_s::algorithm
```

**Details:** Selected provisioning algorithm

###### public_key (heading level 7)

```
uint8_t sl_btmesh_evt_prov_start_sent_s::public_key
```

**Details:** Selected OOB public key

###### authentication_method (heading level 7)

```
uint8_t sl_btmesh_evt_prov_start_sent_s::authentication_method
```

**Details:** Selected authentication method

###### authentication_action (heading level 7)

```
uint8_t sl_btmesh_evt_prov_start_sent_s::authentication_action
```

**Details:** Selected authentication action

###### authentication_size (heading level 7)

```
uint8_t sl_btmesh_evt_prov_start_sent_s::authentication_size
```

**Details:** Selected authentication size

### Bluetooth Mesh Proxy Connections

Bluetooth Mesh Proxy Connections. 

Bluetooth mesh stack functions for GATT proxy connections 

#### Modules

[sl_btmesh_evt_proxy_connected](sl-btmesh-evt-proxy-connected)

[sl_btmesh_evt_proxy_disconnected](sl-btmesh-evt-proxy-disconnected)

[sl_btmesh_evt_proxy_filter_status](sl-btmesh-evt-proxy-filter-status)

#### Functions

##### sl_btmesh_proxy_connect

`sl_status_t sl_btmesh_proxy_connect(uint8_t connection, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|connection|Connection handle|
|uint32_t *|[out]|handle|If a connection attempt is successfully initiated, a valid proxy handle will be returned.|

Start connecting a proxy client to a proxy server. After the connection is complete, a [sl_btmesh_evt_proxy_connected](sl-btmesh-evt-proxy-connected) event will be generated. LE-connection must be opened prior to opening the proxy connection.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_proxy_connected](sl-btmesh-evt-proxy-connected)
- [sl_btmesh_evt_proxy_disconnected](sl-btmesh-evt-proxy-disconnected)

##### sl_btmesh_proxy_disconnect

`sl_status_t sl_btmesh_proxy_disconnect(uint32_t handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|handle|Proxy handle|

Disconnect. This call can be used also for a connection, which is not yet fully formed.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_proxy_disconnected](sl-btmesh-evt-proxy-disconnected)

##### sl_btmesh_proxy_set_filter_type

`sl_status_t sl_btmesh_proxy_set_filter_type(uint32_t handle, uint16_t netkey_index, uint8_t type)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|handle|Proxy handle|
|uint16_t|[in]|netkey_index|Network key index used in encrypting the request to the proxy server|
|uint8_t|[in]|type|Filter type: 0x00 to allow traffic from the given address, 0x01 to block traffic from the given address|

Set up the proxy filtering type. At the proxy server side, this is a local configuration, while on the proxy client a proxy configuration PDU will be sent to the proxy server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_proxy_allow

`sl_status_t sl_btmesh_proxy_allow(uint32_t handle, uint16_t netkey_index, uint16_t address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|handle|Proxy handle|
|uint16_t|[in]|netkey_index|Network key index used in encrypting the request to the proxy server|
|uint16_t|[in]|address|Destination address to allow. The address may be either a unicast address, a group address, or a virtual address.|

Allow messages meant for the given address to be forwarded over the proxy connection to the proxy client. At the proxy server side, this is a local configuration, while on the proxy client a proxy configuration PDU will be sent to the proxy server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_proxy_deny

`sl_status_t sl_btmesh_proxy_deny(uint32_t handle, uint16_t netkey_index, uint16_t address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|handle|Proxy handle|
|uint16_t|[in]|netkey_index|Network key index used in encrypting the request to the proxy server|
|uint16_t|[in]|address|Destination address to block. The address may be either a unicast address, a group address, or a virtual address.|

Block messages meant for the given address from being forwarded over the proxy connection to the proxy client. At the proxy server side, this is a local configuration, while on the proxy client a proxy configuration PDU will be sent to the proxy server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_proxy_optimisation_toggle

`sl_status_t sl_btmesh_proxy_optimisation_toggle(uint8_t enable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|enable|Non zero - enable, otherwise disable|

In case of unicast address, if proxy identified the destination, the message will be forwarded only to that node, otherwise to all. This functionality could be enabled or disabled with this function.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_proxy_send_solicitation

`sl_status_t sl_btmesh_proxy_send_solicitation(uint16_t enc_netkey_index, uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key index used to encrypt the message|
|uint16_t|[in]|elem_index|Solicitation source element index. Proxy client may use the primary address of any of the secondary addresses as a solicitation source|
|uint16_t|[in]|dst|Solicitation destination address. Solicitation does not have a subscribe mechanism, the address can be the primary or any of the secondary addresses. In addition, 0xFFFC (All Proxies) is permitted|

Send Solicitation PDU to activate a Private Proxy on a node that support On-Demand Private Proxy.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_proxy_connect_id 0x00180028`

`#define sl_btmesh_cmd_proxy_disconnect_id 0x01180028`

`#define sl_btmesh_cmd_proxy_set_filter_type_id 0x02180028`

`#define sl_btmesh_cmd_proxy_allow_id 0x03180028`

`#define sl_btmesh_cmd_proxy_deny_id 0x04180028`

`#define sl_btmesh_cmd_proxy_optimisation_toggle_id 0x05180028`

`#define sl_btmesh_cmd_proxy_send_solicitation_id 0x06180028`

`#define sl_btmesh_rsp_proxy_connect_id 0x00180028`

`#define sl_btmesh_rsp_proxy_disconnect_id 0x01180028`

`#define sl_btmesh_rsp_proxy_set_filter_type_id 0x02180028`

`#define sl_btmesh_rsp_proxy_allow_id 0x03180028`

`#define sl_btmesh_rsp_proxy_deny_id 0x04180028`

`#define sl_btmesh_rsp_proxy_optimisation_toggle_id 0x05180028`

`#define sl_btmesh_rsp_proxy_send_solicitation_id 0x06180028`

#### sl_btmesh_evt_proxy_connected

Indication that a connection has been successfully formed, received as a response to the [sl_btmesh_proxy_connect](sl-btmesh-proxy#sl-btmesh-proxy-connect) command. 

##### Modules

[sl_btmesh_evt_proxy_connected_s](sl-btmesh-evt-proxy-connected-s)

##### Typedefs

###### sl_btmesh_evt_proxy_connected_t

`typedef struct sl_btmesh_evt_proxy_connected_s sl_btmesh_evt_proxy_connected_t`

##### Macros

`#define sl_btmesh_evt_proxy_connected_id 0x001800a8`

**Description**: Identifier of the connected event.

Data structure of the connected event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_proxy_connected_s::handle
```

**Details:** Proxy handle

#### sl_btmesh_evt_proxy_disconnected

Indication that a connection has been disconnected or a connection attempt failed, received as a response to [sl_btmesh_proxy_connect](sl-btmesh-proxy#sl-btmesh-proxy-connect) or [sl_btmesh_proxy_disconnect](sl-btmesh-proxy#sl-btmesh-proxy-disconnect) command. 

##### Modules

[sl_btmesh_evt_proxy_disconnected_s](sl-btmesh-evt-proxy-disconnected-s)

##### Typedefs

###### sl_btmesh_evt_proxy_disconnected_t

`typedef struct sl_btmesh_evt_proxy_disconnected_s sl_btmesh_evt_proxy_disconnected_t`

##### Macros

`#define sl_btmesh_evt_proxy_disconnected_id 0x011800a8`

**Description**: Identifier of the disconnected event.

Data structure of the disconnected event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_proxy_disconnected_s::handle
```

**Details:** Proxy handle

###### reason (heading level 7)

```
uint16_t sl_btmesh_evt_proxy_disconnected_s::reason
```

**Details:** Reason for disconnection

#### sl_btmesh_evt_proxy_filter_status

Proxy status report event. 

##### Modules

[sl_btmesh_evt_proxy_filter_status_s](sl-btmesh-evt-proxy-filter-status-s)

##### Typedefs

###### sl_btmesh_evt_proxy_filter_status_t

`typedef struct sl_btmesh_evt_proxy_filter_status_s sl_btmesh_evt_proxy_filter_status_t`

##### Macros

`#define sl_btmesh_evt_proxy_filter_status_id 0x021800a8`

**Description**: Identifier of the filter_status event.

Data structure of the filter_status event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_proxy_filter_status_s::handle
```

**Details:** Proxy handle

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_proxy_filter_status_s::type
```

**Details:** Filter type: 0x00 to allow traffic from the given address, 0x01 to block traffic from the given address

###### count (heading level 7)

```
uint16_t sl_btmesh_evt_proxy_filter_status_s::count
```

**Details:** Current filter list length

### Bluetooth Mesh Silabs Configuration Client Vendor Model

Bluetooth Mesh Silabs Configuration Client Vendor Model. 

Silicon Labs Configuration Client vendor model. It is used to configure global and per-model specific settings of nodes such as Tx-PHY for long packets, usage of advertising extensions (AE) on per-model basis. 

#### Modules

[sl_btmesh_evt_silabs_config_client_tx_status](sl-btmesh-evt-silabs-config-client-tx-status)

[sl_btmesh_evt_silabs_config_client_model_status](sl-btmesh-evt-silabs-config-client-model-status)

[sl_btmesh_evt_silabs_config_client_network_pdu_status](sl-btmesh-evt-silabs-config-client-network-pdu-status)

#### Enumerations

##### sl_btmesh_silabs_config_client_status_t

```
enum sl_btmesh_silabs_config_client_status_t {
    sl_btmesh_silabs_config_client_status_success = 0x0
    sl_btmesh_silabs_config_client_status_unknown_cmd = 0x1
    sl_btmesh_silabs_config_client_status_invalid_parameter = 0x2
    sl_btmesh_silabs_config_client_status_does_not_exist = 0x3
}
```

**Description:**

The Silabs Configuration Client Status codes.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_silabs_config_client_status_success|(0x0) The Client message was successfully processed by the Server.|
|sl_btmesh_silabs_config_client_status_unknown_cmd|(0x1) The command was not understood by the Server.|
|sl_btmesh_silabs_config_client_status_invalid_parameter|(0x2) A parameter in the Client message is outside of its valid range.|
|sl_btmesh_silabs_config_client_status_does_not_exist|(0x3) Resource specifed by the Client message does not exist.|

#### Functions

##### sl_btmesh_silabs_config_client_init

`sl_status_t sl_btmesh_silabs_config_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize Silabs Configuration client model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_client_set_tx

`sl_status_t sl_btmesh_silabs_config_client_set_tx(uint16_t server_address, uint16_t appkey_index, uint8_t tx_phy, uint32_t tx_options_bitmap)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|uint16_t|[in]|appkey_index|The application key index used|
|uint8_t|[in]|tx_phy|TX PHY for long packets (packets that would be segmented).<br/><br/>- 1: LE 1M PHY<br/>- 2: LE 2M PHY|
|uint32_t|[in]|tx_options_bitmap|TX options. NOTE: Currently not used: reserved for future use, set as 0.|

Set node specific TX configuration.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_silabs_config_client_tx_status](sl-btmesh-evt-silabs-config-client-tx-status)

##### sl_btmesh_silabs_config_client_get_tx

`sl_status_t sl_btmesh_silabs_config_client_get_tx(uint16_t server_address, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|uint16_t|[in]|appkey_index|The application key index used|

Get node specific TX configuration.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_silabs_config_client_tx_status](sl-btmesh-evt-silabs-config-client-tx-status)

##### sl_btmesh_silabs_config_client_set_model_enable

`sl_status_t sl_btmesh_silabs_config_client_set_model_enable(uint16_t server_address, uint16_t appkey_index, uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t enable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|uint16_t|[in]|appkey_index|The application key index used|
|uint16_t|[in]|elem_index|The index of the server target element, 0 is the primary element.|
|uint16_t|[in]|vendor_id|Vendor ID of the model to configure.|
|uint16_t|[in]|model_id|Model ID of the server target.|
|uint8_t|[in]|enable|Non zero - enable, otherwise disable|

Set TX over AE on per-model basis enable/disable state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_silabs_config_client_model_status](sl-btmesh-evt-silabs-config-client-model-status)

##### sl_btmesh_silabs_config_client_get_model_enable

`sl_status_t sl_btmesh_silabs_config_client_get_model_enable(uint16_t server_address, uint16_t appkey_index, uint16_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|uint16_t|[in]|appkey_index|The application key index used|
|uint16_t|[in]|elem_index|The index of the server target element, 0 is the primary element.|
|uint16_t|[in]|vendor_id|Vendor ID of the model to configure.|
|uint16_t|[in]|model_id|Model ID of the server target.|

Get TX over AE on per-model basis enable/disable state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_silabs_config_client_model_status](sl-btmesh-evt-silabs-config-client-model-status)

##### sl_btmesh_silabs_config_client_set_network_pdu

`sl_status_t sl_btmesh_silabs_config_client_set_network_pdu(uint16_t server_address, uint16_t appkey_index, uint16_t pdu_max_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|uint16_t|[in]|appkey_index|The application key index used|
|uint16_t|[in]|pdu_max_size|Network PDU max size. Valid range: 29 - 398.|

Set network PDU state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_silabs_config_client_network_pdu_status](sl-btmesh-evt-silabs-config-client-network-pdu-status)

##### sl_btmesh_silabs_config_client_get_network_pdu

`sl_status_t sl_btmesh_silabs_config_client_get_network_pdu(uint16_t server_address, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|uint16_t|[in]|appkey_index|The application key index used|

Get network PDU state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_silabs_config_client_network_pdu_status](sl-btmesh-evt-silabs-config-client-network-pdu-status)

##### sl_btmesh_silabs_config_client_deinit

`sl_status_t sl_btmesh_silabs_config_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize Silabs Configuration Client model. After this call, the model cannot be used until it is initialized again. See [sl_btmesh_silabs_config_client_init](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-init).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_silabs_config_client_init_id 0x00010028`

`#define sl_btmesh_cmd_silabs_config_client_set_tx_id 0x01010028`

`#define sl_btmesh_cmd_silabs_config_client_get_tx_id 0x02010028`

`#define sl_btmesh_cmd_silabs_config_client_set_model_enable_id 0x03010028`

`#define sl_btmesh_cmd_silabs_config_client_get_model_enable_id 0x04010028`

`#define sl_btmesh_cmd_silabs_config_client_set_network_pdu_id 0x05010028`

`#define sl_btmesh_cmd_silabs_config_client_get_network_pdu_id 0x06010028`

`#define sl_btmesh_cmd_silabs_config_client_deinit_id 0x07010028`

`#define sl_btmesh_rsp_silabs_config_client_init_id 0x00010028`

`#define sl_btmesh_rsp_silabs_config_client_set_tx_id 0x01010028`

`#define sl_btmesh_rsp_silabs_config_client_get_tx_id 0x02010028`

`#define sl_btmesh_rsp_silabs_config_client_set_model_enable_id 0x03010028`

`#define sl_btmesh_rsp_silabs_config_client_get_model_enable_id 0x04010028`

`#define sl_btmesh_rsp_silabs_config_client_set_network_pdu_id 0x05010028`

`#define sl_btmesh_rsp_silabs_config_client_get_network_pdu_id 0x06010028`

`#define sl_btmesh_rsp_silabs_config_client_deinit_id 0x07010028`

#### sl_btmesh_evt_silabs_config_client_tx_status

Node specific TX configuration state. 

Received as a response to the [sl_btmesh_silabs_config_client_set_tx](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-set-tx) and [sl_btmesh_silabs_config_client_get_tx](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-get-tx) command. 

##### Modules

[sl_btmesh_evt_silabs_config_client_tx_status_s](sl-btmesh-evt-silabs-config-client-tx-status-s)

##### Typedefs

###### sl_btmesh_evt_silabs_config_client_tx_status_t

`typedef struct sl_btmesh_evt_silabs_config_client_tx_status_s sl_btmesh_evt_silabs_config_client_tx_status_t`

##### Macros

`#define sl_btmesh_evt_silabs_config_client_tx_status_id 0x010100a8`

**Description**: Identifier of the tx_status event.

Data structure of the tx_status event. 

###### Public Attributes

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_tx_status_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_client_tx_status_s::status
```

**Details:** Enum [sl_btmesh_silabs_config_client_status_t](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-status-t). Status code from the Server.

###### tx_phy (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_client_tx_status_s::tx_phy
```

**Details:** TX PHY for long packets (packets that would be segmented).

- 1: LE 1M PHY
- 2: LE 2M PHY

###### tx_options_bitmap (heading level 7)

```
uint32_t sl_btmesh_evt_silabs_config_client_tx_status_s::tx_options_bitmap
```

**Details:** TX options. NOTE: Currently not used: reserved for future use.

#### sl_btmesh_evt_silabs_config_client_model_status

TX over AE on per-model basis enable/disable state. 

Received as a response to the [sl_btmesh_silabs_config_client_set_model_enable](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-set-model-enable) and [sl_btmesh_silabs_config_client_get_model_enable](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-get-model-enable) command. 

##### Modules

[sl_btmesh_evt_silabs_config_client_model_status_s](sl-btmesh-evt-silabs-config-client-model-status-s)

##### Typedefs

###### sl_btmesh_evt_silabs_config_client_model_status_t

`typedef struct sl_btmesh_evt_silabs_config_client_model_status_s sl_btmesh_evt_silabs_config_client_model_status_t`

##### Macros

`#define sl_btmesh_evt_silabs_config_client_model_status_id 0x020100a8`

**Description**: Identifier of the model_status event.

Data structure of the model_status event. 

###### Public Attributes

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_model_status_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_client_model_status_s::status
```

**Details:** Enum [sl_btmesh_silabs_config_client_status_t](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-status-t). Status code from the Server.

###### elem_index (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_client_model_status_s::elem_index
```

**Details:** Element index of model to configure.

###### vendor_id (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_model_status_s::vendor_id
```

**Details:** Vendor ID of model to configure.

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_model_status_s::model_id
```

**Details:** Model ID of model to configure.

###### value (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_model_status_s::value
```

**Details:** Extended packet size to set, currently 1 to use extended 0 to not

#### sl_btmesh_evt_silabs_config_client_network_pdu_status

Node specific Network PDU configuration state. 

Received as a response to the [sl_btmesh_silabs_config_client_set_network_pdu](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-set-network-pdu) and [sl_btmesh_silabs_config_client_get_network_pdu](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-get-network-pdu) command. 

##### Modules

[sl_btmesh_evt_silabs_config_client_network_pdu_status_s](sl-btmesh-evt-silabs-config-client-network-pdu-status-s)

##### Typedefs

###### sl_btmesh_evt_silabs_config_client_network_pdu_status_t

`typedef struct sl_btmesh_evt_silabs_config_client_network_pdu_status_s sl_btmesh_evt_silabs_config_client_network_pdu_status_t`

##### Macros

`#define sl_btmesh_evt_silabs_config_client_network_pdu_status_id 0x030100a8`

**Description**: Identifier of the network_pdu_status event.

Data structure of the network_pdu_status event. 

###### Public Attributes

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_network_pdu_status_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_client_network_pdu_status_s::status
```

**Details:** Enum [sl_btmesh_silabs_config_client_status_t](sl-btmesh-silabs-config-client#sl-btmesh-silabs-config-client-status-t). Status code from the Server.

###### pdu_max_size (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_client_network_pdu_status_s::pdu_max_size
```

**Details:** Network PDU max size

### Bluetooth Mesh Vendor Model

Bluetooth Mesh Vendor Model. 

Vendor model API provides functionality to send and receive vendor-specific messages.

Throughout the API, the manipulated model is identified by its element address, vendor ID, and model ID.

The API has functions for sending, receiving, and publishing messages. The application has to implement additional complex functionality (state machines or other model-specific logic).

The stack will handle Mesh transaction layer segmentation and reassembly automatically if the messages sent are long enough to require it.

Note that as the application layer overhead for vendor messages is three bytes (vendor ID and opcode) and the access layer MIC is at least four bytes, the longest vendor application payload which can be sent using an unsegmented transport layer PDU is eight bytes. On the other hand, the longest vendor application payload which can be sent using transport layer segmentation is 377 bytes (fragmented into 32 segments). 

#### Modules

[sl_btmesh_evt_vendor_model_receive](sl-btmesh-evt-vendor-model-receive)

[sl_btmesh_evt_vendor_model_send_complete](sl-btmesh-evt-vendor-model-send-complete)

#### Enumerations

##### sl_btmesh_vendor_model_options_t

```
enum sl_btmesh_vendor_model_options_t {
    sl_btmesh_vendor_model_heap_work_buffer = 0x0
}
```

**Description:**

Key values to identify vendor model configuration options.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_vendor_model_heap_work_buffer|(0x0) If set to 1, each vendor model allocates a heap work buffer for messages being received. If set to 0, no heap work buffer allocation is made, which saves memory but risks losing messages in a high load environment. Range: 0...1 Default: 1|

#### Functions

##### sl_btmesh_vendor_model_send

`sl_status_t sl_btmesh_vendor_model_send(uint16_t destination_address, int8_t va_index, uint16_t appkey_index, uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t nonrelayed, uint8_t opcode, uint8_t final, size_t payload_len, const uint8_t *payload)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|destination_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|int8_t|[in]|va_index|Index of the destination Label UUID (used only is the destination address is a virtual address)|
|uint16_t|[in]|appkey_index|The application key index used|
|uint16_t|[in]|elem_index|Sending model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the sending model|
|uint16_t|[in]|model_id|Model ID of the sending model|
|uint8_t|[in]|nonrelayed|If the message is a response to a received message, set this parameter according to what was received in the receive event. Otherwise, set to non-zero if the message affects only devices in the immediate radio neighborhood.|
|uint8_t|[in]|opcode|Message opcode|
|uint8_t|[in]|final|Indicates whether this payload chunk is the final one of the message or whether more will follow.|
|size_t|[in]|payload_len|Length of data in `payload`|
|const uint8_t *|[in]|payload|Payload data (either complete or partial; see final parameter).|

Send vendor-specific data.

Note that, because of the bgapi event length restrictions, the message sent may need to be fragmented into several commands. If this is the case, the application must issue the commands in the correct order and mark the command carrying the last message fragment with the final flag set to a non-zero value. The stack will not start sending the message until the complete message is provided by the application. Fragments from multiple messages must not be interleaved.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_set_publication

`sl_status_t sl_btmesh_vendor_model_set_publication(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t opcode, uint8_t final, size_t payload_len, const uint8_t *payload)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Publishing model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the model|
|uint16_t|[in]|model_id|Model ID of the model|
|uint8_t|[in]|opcode|Message opcode|
|uint8_t|[in]|final|Indicates whether this payload chunk is the final one of the message or whether more will follow.|
|size_t|[in]|payload_len|Length of data in `payload`|
|const uint8_t *|[in]|payload|Payload data (either complete or partial; see final parameter).|

Set the vendor model publication message.

The model publication message will be sent out when the model publication occurs either periodically (if the model is configured for periodic publishing) or explicitly (see [sl_btmesh_vendor_model_publish](sl-btmesh-vendor-model#sl-btmesh-vendor-model-publish).

Note that, because of bgapi length requirements, the message may need to be fragmented over multiple commands. If this is the case, the application must issue the commands in the correct order and mark the command carrying the last message fragment with the final flag set to a non-zero value. The stack will not assign the message to the model until the complete message is provided by the application.

To disable publication, the publication message may be erased using the [sl_btmesh_vendor_model_clear_publication](sl-btmesh-vendor-model#sl-btmesh-vendor-model-clear-publication) command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_clear_publication

`sl_status_t sl_btmesh_vendor_model_clear_publication(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Publishing model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the model|
|uint16_t|[in]|model_id|Model ID of the model|

Clear the vendor model publication message.

Clearing the model publication message disables model publishing, which can be re-enabled by defining the publication message using the [sl_btmesh_vendor_model_set_publication](sl-btmesh-vendor-model#sl-btmesh-vendor-model-set-publication) command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_publish

`sl_status_t sl_btmesh_vendor_model_publish(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Publishing model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the model|
|uint16_t|[in]|model_id|Model ID of the model|

Publish the vendor model publication message.

Sends the stored publication message to the network using the application key and destination address stored in the model publication parameters.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_init

`sl_status_t sl_btmesh_vendor_model_init(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t publish, size_t opcodes_len, const uint8_t *opcodes)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the model|
|uint16_t|[in]|model_id|Model ID of the model|
|uint8_t|[in]|publish|Indicates if the model is a publish model (non-zero) or not (zero).|
|size_t|[in]|opcodes_len|Length of data in `opcodes`|
|const uint8_t *|[in]|opcodes|Array of opcodes the model can handle|

Initialize the vendor model. This function has to be called before the model can be used. Note that the model can be deinitialized if it is no longer needed. See [sl_btmesh_vendor_model_deinit](sl-btmesh-vendor-model#sl-btmesh-vendor-model-deinit).

Opcodes that the model is able to receive at initialization must be defined. This enables the stack to pass only valid messages up to the model during runtime. Per Mesh specification there are up to 64 opcodes per vendor, ranging from 0 to 63. Specifying opcodes outside of that range will result in an error response. Duplicate opcodes in the array do not result in an error, but will of course be recorded only once.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_deinit

`sl_status_t sl_btmesh_vendor_model_deinit(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the model|
|uint16_t|[in]|model_id|Model ID of the model|

Deinitialize the model. After this call, the model cannot be used until it is initialized again. See [sl_btmesh_vendor_model_init](sl-btmesh-vendor-model#sl-btmesh-vendor-model-init).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_send_tracked

`sl_status_t sl_btmesh_vendor_model_send_tracked(uint16_t destination_address, int8_t va_index, uint16_t appkey_index, uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t nonrelayed, uint8_t segment, uint8_t opcode, uint8_t final, size_t payload_len, const uint8_t *payload, uint16_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|destination_address|Destination address of the message. It can be a unicast address, a group address, or a virtual address.|
|int8_t|[in]|va_index|Index of the destination Label UUID (used only is the destination address is a virtual address)|
|uint16_t|[in]|appkey_index|The application key index used|
|uint16_t|[in]|elem_index|Sending model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the sending model|
|uint16_t|[in]|model_id|Model ID of the sending model|
|uint8_t|[in]|nonrelayed|If the message is a response to a received message, set this parameter according to what was received in the receive event. Otherwise, set to non-zero if the message affects only devices in the immediate radio neighborhood.|
|uint8_t|[in]|segment|If nonzero, instruct the stack to use transport layer segmentation, even if the data would be short enough to send as an unsegmented message. If zero, stack selects automatically based on data length whether to use segmentation or not.|
|uint8_t|[in]|opcode|Message opcode|
|uint8_t|[in]|final|Indicates whether this payload chunk is the final one of the message or whether more will follow.|
|size_t|[in]|payload_len|Length of data in `payload`|
|const uint8_t *|[in]|payload|Payload data (either complete or partial; see final parameter).|
|uint16_t *|[out]|handle|Tracking handle for the message sending. Note that a valid handle is returned only when the final payload fragment is received by the stack (as indicated by the final parameter of this message) and the message is accepted for delivery (as indicated by the result code). Otherwise the value of this parameter should be ignored.|

Send vendor-specific data with a delivery report.

This command works otherwise as [sl_btmesh_vendor_model_send](sl-btmesh-vendor-model#sl-btmesh-vendor-model-send) but also provides a tracking handle if there is no immediate local error. Once the message sending completes a [sl_btmesh_evt_vendor_model_send_complete](sl-btmesh-evt-vendor-model-send-complete) event is generated, and the handle received here can be used to correlate the event to the sent message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_set_publication_tracked

`sl_status_t sl_btmesh_vendor_model_set_publication_tracked(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t segment, uint8_t opcode, uint8_t final, size_t payload_len, const uint8_t *payload, uint16_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Publishing model element index|
|uint16_t|[in]|vendor_id|Vendor ID of the model|
|uint16_t|[in]|model_id|Model ID of the model|
|uint8_t|[in]|segment|If nonzero, instruct the stack to use transport layer segmentation, even if the data would be short enough to publish as an unsegmented message. If zero, stack selects automatically based on data length whether to use segmentation or not.|
|uint8_t|[in]|opcode|Message opcode|
|uint8_t|[in]|final|Indicates whether this payload chunk is the final one of the message or whether more will follow.|
|size_t|[in]|payload_len|Length of data in `payload`|
|const uint8_t *|[in]|payload|Payload data (either complete or partial; see final parameter).|
|uint16_t *|[out]|handle|Tracking handle for the message publishing. Note that a valid handle is returned only when the final payload fragment is received by the stack (as indicated by the final parameter of this message) and the message is accepted for publication (as indicated by the result code). Otherwise the value of this parameter should be ignored. attempt|

Set the vendor model publication message with a delivery report.

This command works otherwise as [sl_btmesh_vendor_model_set_publication](sl-btmesh-vendor-model#sl-btmesh-vendor-model-set-publication) but also sets up a tracking handle for monitoring message delivery. When the message publishing completes a [sl_btmesh_evt_vendor_model_send_complete](sl-btmesh-evt-vendor-model-send-complete) event is generated, and the handle received here can be used to correlate the event to the sent message.

Note that the same tracking handle will be reported multiple times in case of periodic publication or publication retransmissions.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_vendor_model_set_option

`sl_status_t sl_btmesh_vendor_model_set_option(uint8_t option, uint32_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|option|Enum [sl_btmesh_vendor_model_options_t](sl-btmesh-vendor-model#sl-btmesh-vendor-model-options-t). Configuration option.|
|uint32_t|[in]|value|Configuration value|

Set global vendor model configuration options.

This command sets global configuration options for all vendor models. Options take effect when models are initialized, so this command should be called before any [sl_btmesh_vendor_model_init](sl-btmesh-vendor-model#sl-btmesh-vendor-model-init) call.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_vendor_model_send_id 0x00190028`

`#define sl_btmesh_cmd_vendor_model_set_publication_id 0x01190028`

`#define sl_btmesh_cmd_vendor_model_clear_publication_id 0x02190028`

`#define sl_btmesh_cmd_vendor_model_publish_id 0x03190028`

`#define sl_btmesh_cmd_vendor_model_init_id 0x04190028`

`#define sl_btmesh_cmd_vendor_model_deinit_id 0x05190028`

`#define sl_btmesh_cmd_vendor_model_send_tracked_id 0x06190028`

`#define sl_btmesh_cmd_vendor_model_set_publication_tracked_id 0x07190028`

`#define sl_btmesh_cmd_vendor_model_set_option_id 0x08190028`

`#define sl_btmesh_rsp_vendor_model_send_id 0x00190028`

`#define sl_btmesh_rsp_vendor_model_set_publication_id 0x01190028`

`#define sl_btmesh_rsp_vendor_model_clear_publication_id 0x02190028`

`#define sl_btmesh_rsp_vendor_model_publish_id 0x03190028`

`#define sl_btmesh_rsp_vendor_model_init_id 0x04190028`

`#define sl_btmesh_rsp_vendor_model_deinit_id 0x05190028`

`#define sl_btmesh_rsp_vendor_model_send_tracked_id 0x06190028`

`#define sl_btmesh_rsp_vendor_model_set_publication_tracked_id 0x07190028`

`#define sl_btmesh_rsp_vendor_model_set_option_id 0x08190028`

#### sl_btmesh_evt_vendor_model_receive

Vendor model message reception event. 

Stack generates this event when a vendor message with a valid opcode is received.

Note that because of the bgapi event length restrictions, the message may be fragmented into several events. If this is the case, the events will be generated by the stack in the correct order and the last event will be marked with the final flag set to a non-zero value. The application has to concatenate the messages into a single buffer if necessary. 

##### Modules

[sl_btmesh_evt_vendor_model_receive_s](sl-btmesh-evt-vendor-model-receive-s)

##### Typedefs

###### sl_btmesh_evt_vendor_model_receive_t

`typedef struct sl_btmesh_evt_vendor_model_receive_s sl_btmesh_evt_vendor_model_receive_t`

##### Macros

`#define sl_btmesh_evt_vendor_model_receive_id 0x001900a8`

**Description**: Identifier of the receive event.

Data structure of the receive event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_receive_s::destination_address
```

**Details:** Address the message was sent to. It can be either the model element's unicast address or a subscription address of the model

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_receive_s::elem_index
```

**Details:** Receiving model element index

###### vendor_id (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_receive_s::vendor_id
```

**Details:** Vendor ID of the receiving model

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_receive_s::model_id
```

**Details:** Model ID of the receiving model

###### source_address (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_receive_s::source_address
```

**Details:** Unicast address of the model which sent the message

###### va_index (heading level 7)

```
int8_t sl_btmesh_evt_vendor_model_receive_s::va_index
```

**Details:** Index of the destination Label UUID (valid only is the destination address is a virtual addres)

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_receive_s::appkey_index
```

**Details:** The application key index used

###### nonrelayed (heading level 7)

```
uint8_t sl_btmesh_evt_vendor_model_receive_s::nonrelayed
```

**Details:** If non-zero, indicates that the received message was not relayed (TTL was zero), which means that the devices are within direct radio range of each other.

###### message_flags (heading level 7)

```
uint8_t sl_btmesh_evt_vendor_model_receive_s::message_flags
```

**Details:** Unsigned 8-bit integer

###### opcode (heading level 7)

```
uint8_t sl_btmesh_evt_vendor_model_receive_s::opcode
```

**Details:** Message opcode

###### final (heading level 7)

```
uint8_t sl_btmesh_evt_vendor_model_receive_s::final
```

**Details:** Indicates whether this payload chunk is the final one of the message or whether more will follow

###### payload (heading level 7)

```
uint8array sl_btmesh_evt_vendor_model_receive_s::payload
```

**Details:** Payload data (either complete or partial; see final parameter)

#### sl_btmesh_evt_vendor_model_send_complete

Vendor model message send complete event. 

Stack generates this event when a vendor message has been sent or published, either successfully or unsuccessfully.

The time this event is generated depends on the message being sent or published. For an unsegmented message the event is generated immediately after the network PDU is sent out, while for a segmented message the event is generated once the segmented message transmission state machine completes. 

##### Modules

[sl_btmesh_evt_vendor_model_send_complete_s](sl-btmesh-evt-vendor-model-send-complete-s)

##### Typedefs

###### sl_btmesh_evt_vendor_model_send_complete_t

`typedef struct sl_btmesh_evt_vendor_model_send_complete_s sl_btmesh_evt_vendor_model_send_complete_t`

##### Macros

`#define sl_btmesh_evt_vendor_model_send_complete_id 0x011900a8`

**Description**: Identifier of the send_complete event.

Data structure of the send_complete event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_send_complete_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint16_t sl_btmesh_evt_vendor_model_send_complete_s::handle
```

**Details:** Tracking handle for the message sending attempt as reported by [sl_btmesh_vendor_model_send_tracked](sl-btmesh-vendor-model#sl-btmesh-vendor-model-send-tracked) or [sl_btmesh_vendor_model_set_publication_tracked](sl-btmesh-vendor-model#sl-btmesh-vendor-model-set-publication-tracked) command responses.

###### message_flags (heading level 7)

```
uint8_t sl_btmesh_evt_vendor_model_send_complete_s::message_flags
```

**Details:** Unsigned 8-bit integer

### Bluetooth Mesh Health Client Model

Bluetooth Mesh Health Client Model. 

This class provides the commands and messages to interface with the Health Client model. 

#### Modules

[sl_btmesh_evt_health_client_server_status](sl-btmesh-evt-health-client-server-status)

[sl_btmesh_evt_health_client_server_status_period](sl-btmesh-evt-health-client-server-status-period)

[sl_btmesh_evt_health_client_server_status_attention](sl-btmesh-evt-health-client-server-status-attention)

#### Functions

##### sl_btmesh_health_client_init

`sl_status_t sl_btmesh_health_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize health client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_health_client_deinit

`sl_status_t sl_btmesh_health_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize health client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_health_client_get

`sl_status_t sl_btmesh_health_client_get(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. May be a unicast address or a group address.|
|uint16_t|[in]|elem_index|Client model element index. Identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|
|uint16_t|[in]|vendor_id|Bluetooth vendor ID used in the request|

Get the registered fault status of a Health Server model or models in the network.

Besides the immediate result code, the response or responses (if the destination server address is a group address) from the network will generate [sl_btmesh_evt_health_client_server_status](sl-btmesh-evt-health-client-server-status).

**Returns**

- If an error occurs locally, (for instance, because of invalid parameters) an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status](sl-btmesh-evt-health-client-server-status)

##### sl_btmesh_health_client_clear

`sl_status_t sl_btmesh_health_client_clear(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id, uint8_t reliable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. May be a unicast address or a group address.|
|uint16_t|[in]|elem_index|Client model element index. Identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|
|uint16_t|[in]|vendor_id|Bluetooth vendor ID used in the request|
|uint8_t|[in]|reliable|If non-zero, a reliable model message is used.|

Clear the fault status of a Health Server model or models in the network.

Besides the immediate result code, the response or responses (if the destination server address is a group address) from the network will generate [sl_btmesh_evt_health_client_server_status](sl-btmesh-evt-health-client-server-status).

**Returns**

- If an error occurs locally (for instance, because of invalid parameters), an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status](sl-btmesh-evt-health-client-server-status)

##### sl_btmesh_health_client_test

`sl_status_t sl_btmesh_health_client_test(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t test_id, uint16_t vendor_id, uint8_t reliable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. May be a unicast address or a group address.|
|uint16_t|[in]|elem_index|Client model element index. Identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|
|uint8_t|[in]|test_id|Test ID used in the request|
|uint16_t|[in]|vendor_id|Bluetooth vendor ID used in the request|
|uint8_t|[in]|reliable|If non-zero, a reliable model message is used.|

Execute a self test on a server model or models in the network.

**Returns**

- If an error occurs locally (for instance, because of invalid parameters) an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status](sl-btmesh-evt-health-client-server-status)

##### sl_btmesh_health_client_get_period

`sl_status_t sl_btmesh_health_client_get_period(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address, which may be a unicast address or a group address|
|uint16_t|[in]|elem_index|Client model element index. Identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|

Get the health period log of a Health Server model or models in the network.

Except for the immediate result code, the response or responses (if the destination server address is a group address) from the network will generate [sl_btmesh_evt_health_client_server_status_period](sl-btmesh-evt-health-client-server-status-period).

**Returns**

- If an error occurs locally, (for instance, because of invalid parameters) an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status_period](sl-btmesh-evt-health-client-server-status-period)

##### sl_btmesh_health_client_set_period

`sl_status_t sl_btmesh_health_client_set_period(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t period, uint8_t reliable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. May be a unicast address or a group address.|
|uint16_t|[in]|elem_index|Client model element index, which identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|
|uint8_t|[in]|period|Health period divisor value. Valid range: 0 - 16.|
|uint8_t|[in]|reliable|If non-zero, a reliable model message is used.|

Set the health period divisor of a Health Server model or models in the network.

Except for the immediate result code, the response or responses (if the destination server address is a group address) from the network will generate [sl_btmesh_evt_health_client_server_status_period](sl-btmesh-evt-health-client-server-status-period).

**Returns**

- If an error occurs locally (for instance, because of invalid parameters), an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status_period](sl-btmesh-evt-health-client-server-status-period)

##### sl_btmesh_health_client_get_attention

`sl_status_t sl_btmesh_health_client_get_attention(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. May be a unicast address or a group address.|
|uint16_t|[in]|elem_index|Client model element index. Identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|

Get the attention timer value of a Health Server model or models in the network.

Besides the immediate result code, the response or responses (if the destination server address is a group address) from the network will generate [sl_btmesh_evt_health_client_server_status_attention](sl-btmesh-evt-health-client-server-status-attention).

**Returns**

- If an error occurs locally (for instance, because of invalid parameters), an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status_attention](sl-btmesh-evt-health-client-server-status-attention)

##### sl_btmesh_health_client_set_attention

`sl_status_t sl_btmesh_health_client_set_attention(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t attention_sec, uint8_t reliable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. May be a unicast address or a group address.|
|uint16_t|[in]|elem_index|Client model element index. Identifies the client model used for sending the request.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request|
|uint8_t|[in]|attention_sec|Attention timer period in seconds|
|uint8_t|[in]|reliable|If non-zero, a reliable model message is used.|

Set the attention timer value of a Health Server model or models in the network.

Except for the immediate result code, the response or responses (if the destination server address is a group address) from the network will generate [sl_btmesh_evt_health_client_server_status_attention](sl-btmesh-evt-health-client-server-status-attention).

**Returns**

- If an error occurs locally (for instance, because of invalid parameters), an errorcode parameter is returned immediately.

**Events**

- [sl_btmesh_evt_health_client_server_status_attention](sl-btmesh-evt-health-client-server-status-attention)

#### Macros

`#define sl_btmesh_cmd_health_client_init_id 0x071a0028`

`#define sl_btmesh_cmd_health_client_deinit_id 0x081a0028`

`#define sl_btmesh_cmd_health_client_get_id 0x001a0028`

`#define sl_btmesh_cmd_health_client_clear_id 0x011a0028`

`#define sl_btmesh_cmd_health_client_test_id 0x021a0028`

`#define sl_btmesh_cmd_health_client_get_period_id 0x031a0028`

`#define sl_btmesh_cmd_health_client_set_period_id 0x041a0028`

`#define sl_btmesh_cmd_health_client_get_attention_id 0x051a0028`

`#define sl_btmesh_cmd_health_client_set_attention_id 0x061a0028`

`#define sl_btmesh_rsp_health_client_init_id 0x071a0028`

`#define sl_btmesh_rsp_health_client_deinit_id 0x081a0028`

`#define sl_btmesh_rsp_health_client_get_id 0x001a0028`

`#define sl_btmesh_rsp_health_client_clear_id 0x011a0028`

`#define sl_btmesh_rsp_health_client_test_id 0x021a0028`

`#define sl_btmesh_rsp_health_client_get_period_id 0x031a0028`

`#define sl_btmesh_rsp_health_client_set_period_id 0x041a0028`

`#define sl_btmesh_rsp_health_client_get_attention_id 0x051a0028`

`#define sl_btmesh_rsp_health_client_set_attention_id 0x061a0028`

#### sl_btmesh_evt_health_client_server_status

Receiving a Health Server fault status message generates this event. 

The Client model may receive a status message because:

- it made a [sl_btmesh_health_client_get](sl-btmesh-health-client#sl-btmesh-health-client-get) to which a Server model responded
- it made a [sl_btmesh_health_client_clear](sl-btmesh-health-client#sl-btmesh-health-client-clear) to which a Server model responded
- it made a [sl_btmesh_health_client_test](sl-btmesh-health-client#sl-btmesh-health-client-test) to which a Server model responded

##### Modules

[sl_btmesh_evt_health_client_server_status_s](sl-btmesh-evt-health-client-server-status-s)

##### Typedefs

###### sl_btmesh_evt_health_client_server_status_t

`typedef struct sl_btmesh_evt_health_client_server_status_s sl_btmesh_evt_health_client_server_status_t`

##### Macros

`#define sl_btmesh_evt_health_client_server_status_id 0x001a00a8`

**Description**: Identifier of the server_status event.

Data structure of the server_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_s::client_address
```

**Details:** Destination address the message was sent to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_s::elem_index
```

**Details:** Client model element index. Identifies the client model which received the status message.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_s::server_address
```

**Details:** Address of the Server model which sent the message

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_s::result
```

**Details:** Response status. If an error occurs (e.g., request timeout), the parameters other than element index, client address, and server address are to be ignored.

###### current (heading level 7)

```
uint8_t sl_btmesh_evt_health_client_server_status_s::current
```

**Details:** Whether the event lists current fault array or registered fault array

###### test_id (heading level 7)

```
uint8_t sl_btmesh_evt_health_client_server_status_s::test_id
```

**Details:** Test ID

###### vendor_id (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_s::vendor_id
```

**Details:** Bluetooth vendor ID used in the request

###### faults (heading level 7)

```
uint8array sl_btmesh_evt_health_client_server_status_s::faults
```

**Details:** Fault array. See the Bluetooth Mesh Profile specification for a list of defined fault IDs.

#### sl_btmesh_evt_health_client_server_status_period

Receiving a Health Server period status message generates this event. 

The Client model may receive a status message because:

- it made a [sl_btmesh_health_client_get_period](sl-btmesh-health-client#sl-btmesh-health-client-get-period) to which a Server model responded
- it made a [sl_btmesh_health_client_set_period](sl-btmesh-health-client#sl-btmesh-health-client-set-period) to which a Server model responded

##### Modules

[sl_btmesh_evt_health_client_server_status_period_s](sl-btmesh-evt-health-client-server-status-period-s)

##### Typedefs

###### sl_btmesh_evt_health_client_server_status_period_t

`typedef struct sl_btmesh_evt_health_client_server_status_period_s sl_btmesh_evt_health_client_server_status_period_t`

##### Macros

`#define sl_btmesh_evt_health_client_server_status_period_id 0x011a00a8`

**Description**: Identifier of the server_status_period event.

Data structure of the server_status_period event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_period_s::client_address
```

**Details:** Destination address the message was sent to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_period_s::elem_index
```

**Details:** Client model element index. Identifies the client model, which received the status message.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_period_s::server_address
```

**Details:** Address of the Server model which sent the message

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_period_s::result
```

**Details:** Response status. If an error occurs (e.g., request timeout), ignore the parameters other than element index, client address, and server address.

###### period (heading level 7)

```
uint8_t sl_btmesh_evt_health_client_server_status_period_s::period
```

**Details:** Health period divisor value

#### sl_btmesh_evt_health_client_server_status_attention

Receiving a Health Server attention status message generates this event. 

The Client model may receive a status message because:

- it made a [sl_btmesh_health_client_get_attention](sl-btmesh-health-client#sl-btmesh-health-client-get-attention) to which a Server model responded
- it made a [sl_btmesh_health_client_set_attention](sl-btmesh-health-client#sl-btmesh-health-client-set-attention) to which a Server model responded

##### Modules

[sl_btmesh_evt_health_client_server_status_attention_s](sl-btmesh-evt-health-client-server-status-attention-s)

##### Typedefs

###### sl_btmesh_evt_health_client_server_status_attention_t

`typedef struct sl_btmesh_evt_health_client_server_status_attention_s sl_btmesh_evt_health_client_server_status_attention_t`

##### Macros

`#define sl_btmesh_evt_health_client_server_status_attention_id 0x021a00a8`

**Description**: Identifier of the server_status_attention event.

Data structure of the server_status_attention event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_attention_s::client_address
```

**Details:** Destination address the message was sent to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_attention_s::elem_index
```

**Details:** Client model element index. Identifies the client model which received the status message.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_attention_s::server_address
```

**Details:** Address of the Server model which sent the message

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_health_client_server_status_attention_s::result
```

**Details:** Response status. If an error occurs (e.g., request timeout), ignore the parameters other than element index, client address, and server address.

###### attention_sec (heading level 7)

```
uint8_t sl_btmesh_evt_health_client_server_status_attention_s::attention_sec
```

**Details:** Current attention timer value in seconds

### Bluetooth Mesh Health Server Model

Bluetooth Mesh Health Server Model. 

This class provides the commands and messages to interface with the Health Server model 

#### Modules

[sl_btmesh_evt_health_server_attention](sl-btmesh-evt-health-server-attention)

[sl_btmesh_evt_health_server_test_request](sl-btmesh-evt-health-server-test-request)

#### Functions

##### sl_btmesh_health_server_set_fault

`sl_status_t sl_btmesh_health_server_set_fault(uint16_t elem_index, uint8_t id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element on which the fault is occurring|
|uint8_t|[in]|id|Fault ID. See the Mesh Profile specification for IDs defined by the Bluetooth SIG.|

Set the fault condition on an element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_health_server_clear_fault

`sl_status_t sl_btmesh_health_server_clear_fault(uint16_t elem_index, uint8_t id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element on which the fault is no longer occurring.|
|uint8_t|[in]|id|Fault ID. See the Mesh Profile specification for IDs defined by the Bluetooth SIG.|

Clear the fault condition on an element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_health_server_send_test_response

`sl_status_t sl_btmesh_health_server_send_test_response(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Address of the client model which sent the message|
|uint16_t|[in]|elem_index|Server model element index. Identifies the Server model that received the request as well as the element on which the test is to be performed.|
|uint16_t|[in]|appkey_index|The application key index to use in encrypting the request.|
|uint16_t|[in]|vendor_id|Bluetooth vendor ID used in the request|

Indicate to the stack that a test request has been completed and that the status may be communicated to the Health Client, which made the test request.

**Returns**

- If an error occurs locally (for instance, because of invalid parameters), an errorcode parameter is returned immediately.

#### Macros

`#define sl_btmesh_cmd_health_server_set_fault_id 0x001b0028`

`#define sl_btmesh_cmd_health_server_clear_fault_id 0x011b0028`

`#define sl_btmesh_cmd_health_server_send_test_response_id 0x021b0028`

`#define sl_btmesh_rsp_health_server_set_fault_id 0x001b0028`

`#define sl_btmesh_rsp_health_server_clear_fault_id 0x011b0028`

`#define sl_btmesh_rsp_health_server_send_test_response_id 0x021b0028`

#### sl_btmesh_evt_health_server_attention

The attention timer on an element is set to a given value. This may happen, for instance, during provisioning. The application should use suitable means to get the user's attention, e.g., by vibrating or blinking an LED. 

##### Modules

[sl_btmesh_evt_health_server_attention_s](sl-btmesh-evt-health-server-attention-s)

##### Typedefs

###### sl_btmesh_evt_health_server_attention_t

`typedef struct sl_btmesh_evt_health_server_attention_s sl_btmesh_evt_health_server_attention_t`

##### Macros

`#define sl_btmesh_evt_health_server_attention_id 0x001b00a8`

**Description**: Identifier of the attention event.

Data structure of the attention event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_health_server_attention_s::elem_index
```

**Details:** Index of the element for which attention timer was set

###### timer_sec (heading level 7)

```
uint8_t sl_btmesh_evt_health_server_attention_s::timer_sec
```

**Details:** Timer value in seconds. If zero, user attention is no longer required.

#### sl_btmesh_evt_health_server_test_request

Health client request for a self test generates this event. After the test has been executed, test results may need to be reported. 

##### Modules

[sl_btmesh_evt_health_server_test_request_s](sl-btmesh-evt-health-server-test-request-s)

##### Typedefs

###### sl_btmesh_evt_health_server_test_request_t

`typedef struct sl_btmesh_evt_health_server_test_request_s sl_btmesh_evt_health_server_test_request_t`

##### Macros

`#define sl_btmesh_evt_health_server_test_request_id 0x011b00a8`

**Description**: Identifier of the test_request event.

Data structure of the test_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_server_test_request_s::server_address
```

**Details:** Destination address the message was sent to. It can be either the Server model element's unicast address, or a subscription address of the Server model.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_health_server_test_request_s::elem_index
```

**Details:** Server model element index. Identifies the Server model that received the request as well as the element on which the test is to be performed.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_health_server_test_request_s::client_address
```

**Details:** Address of the client model which sent the message

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_health_server_test_request_s::appkey_index
```

**Details:** The application key index to use in encrypting the request. Any response sent must be encrypted using the same key.

###### test_id (heading level 7)

```
uint8_t sl_btmesh_evt_health_server_test_request_s::test_id
```

**Details:** Test ID

###### vendor_id (heading level 7)

```
uint16_t sl_btmesh_evt_health_server_test_request_s::vendor_id
```

**Details:** Bluetooth vendor ID used in the request

###### response_required (heading level 7)

```
uint8_t sl_btmesh_evt_health_server_test_request_s::response_required
```

**Details:** Non-zero if client expects a response. The application should issue a [sl_btmesh_health_server_send_test_response](sl-btmesh-health-server#sl-btmesh-health-server-send-test-response) once it has processed the request.

### Bluetooth Mesh Generic Client Model

Bluetooth Mesh Generic Client Model. 

Generic client model API provides a functionality to send and receive messages using Bluetooth SIG client models, including generic client models and lighting client models.

In the API, the client model that is used is identified by its element address and model ID, while the server model responding to client model requests is identified by its element address and model ID.

The API has functions for querying server model states, requesting server model state changes, and publishing messages. The application has to implement more complex functionality (state machines or other model-specific logic).

Data for state change requests and server responses is passed as serialized byte arrays through BGAPI. There are functions to convert byte arrays to and from model state structures in the Bluetooth mesh SDK.

The stack will handle Mesh transaction layer segmentation and reassembly automatically if the messages sent are long enough to require it.

**Note on time resolution**

Because of message formatting, transition time and remaining time resolution units depend on the requested or reported value. For example, until 6.2 seconds it is 100 ms; until 62 seconds it is 1 s; until 620 seconds it is 10 s; and until 620 minutes it is 10 minutes. The value cannot be longer than 620 minutes. Therefore, it is not possible to request a delay of exactly 7500 ms. The resolution unit is 1 s between 6.2 and 62 seconds, so the value would be rounded down to 7 s.

Delay resolution is 5 ms and values will be rounded down to the closest 5 ms. The value can't be longer than 1275 ms. 

#### Modules

[Generic Client Get State Types](sl-btmesh-generic-client-get-state-type)

[Generic Client Set Request Types](sl-btmesh-generic-client-set-request-type)

[sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status)

#### Functions

##### sl_btmesh_generic_client_get

`sl_status_t sl_btmesh_generic_client_get(uint16_t server_address, uint16_t elem_index, uint16_t model_id, uint16_t appkey_index, uint8_t type)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|model_id|Client model ID|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|type|Model-specific state type, identifying the kind of state to retrieve. See [Generic Client Get State Types](sl-btmesh-generic-client-get-state-type) list for details.|

Get the current state of a server model or models in the network. Besides the immediate result code, the response or responses from the network will generate server state report events for the replies received.

The server model responses will be reported in [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status) events.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status)

##### sl_btmesh_generic_client_set

`sl_status_t sl_btmesh_generic_client_set(uint16_t server_address, uint16_t elem_index, uint16_t model_id, uint16_t appkey_index, uint8_t tid, uint32_t transition_ms, uint16_t delay_ms, uint16_t flags, uint8_t type, size_t parameters_len, const uint8_t *parameters)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|model_id|Client model ID|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|tid|Transaction identifier. This applies to those messages the Mesh Model specification defines as transactional and can be left as zero for others.|
|uint32_t|[in]|transition_ms|Transition time (in milliseconds) for the state change. If both the transition time and the delay are zero, the transition is immediate.<br/><br/>This applies to messages the Mesh Model specification defines to have transition and delay times and can be left as zero for others.|
|uint16_t|[in]|delay_ms|Delay time (in milliseconds) before starting the state change. If both the transition time and the delay are zero, the transition is immediate.<br/><br/>This applies to messages the Mesh Model specification defines to have transition and delay times and can be left as zero for others.|
|uint16_t|[in]|flags|Message flags. Bitmask of the following:<br/><br/>- **Bit 0:** Response required. If non-zero, the client expects a response from the server<br/>- **Bit 1:** Default transition timer. If non-zero, the client requests that server uses its default transition timer and the supplied transition and delay values are ignored.|
|uint8_t|[in]|type|Model-specific request type. See set request types list for details.|
|size_t|[in]|parameters_len|Length of data in `parameters`|
|const uint8_t *|[in]|parameters|Message-specific set request parameters serialized into a byte array|

Set the current state of a server model or models in the network. Besides the immediate result code, the response or responses from the network will generate server state report events for the replies received.

The server model responses will be reported in [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status) events. Note that for responses to be generated the corresponding flag needs to be set.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status)

##### sl_btmesh_generic_client_publish

`sl_status_t sl_btmesh_generic_client_publish(uint16_t elem_index, uint16_t model_id, uint8_t tid, uint32_t transition_ms, uint16_t delay_ms, uint16_t flags, uint8_t type, size_t parameters_len, const uint8_t *parameters)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|model_id|Client model ID|
|uint8_t|[in]|tid|Transaction identifier|
|uint32_t|[in]|transition_ms|Transition time (in milliseconds) for the state change. If both the transition time and the delay are zero, the transition is immediate.<br/><br/>This applies to messages the Mesh Model specification defines to have transition and delay times and can be left as zero for others.|
|uint16_t|[in]|delay_ms|Delay time (in milliseconds) before starting the state change. If both the transition time and the delay are zero, the transition is immediate.<br/><br/>This applies to messages the Mesh Model specification defines to have transition and delay times, and can be left as zero for others.|
|uint16_t|[in]|flags|Message flags. Bitmask of the following:<br/><br/>- **Bit 0:** Response required. If non-zero, the client expects a response from the server<br/>- **Bit 1:** Default transition timer. If non-zero client requests that server uses its default transition timer and the supplied transition and delay values are ignored.|
|uint8_t|[in]|type|Model-specific request type. See set request types list for details.|
|size_t|[in]|parameters_len|Length of data in `parameters`|
|const uint8_t *|[in]|parameters|Message-specific set request parameters serialized into a byte array|

Publish a set request to the network using the publish address and publish application key of the model. The message will be received by the server models which subscribe to the publish address, and there's no need to explicitly specify a destination address or application key.

The server model responses will be reported in [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status) events. To generate responses, the corresponding flag needs to be set.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status)

##### sl_btmesh_generic_client_get_params

`sl_status_t sl_btmesh_generic_client_get_params(uint16_t server_address, uint16_t elem_index, uint16_t model_id, uint16_t appkey_index, uint8_t type, size_t parameters_len, const uint8_t *parameters)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|model_id|Client model ID|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|type|Model-specific state type, identifying the kind of state to retrieve. See [Generic Client Get State Types](sl-btmesh-generic-client-get-state-type) list for details.|
|size_t|[in]|parameters_len|Length of data in `parameters`|
|const uint8_t *|[in]|parameters|Message-specific get request parameters serialized into a byte array|

Get the current state of a server model or models in the network, with additional parameters detailing the request. Besides the immediate result code, the response or responses from the network will generate server state report events for the replies received.

The server model responses will be reported in [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status) events.

This call is used to query properties, for which the property ID is given as a parameter.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_generic_client_server_status](sl-btmesh-evt-generic-client-server-status)

##### sl_btmesh_generic_client_init

`sl_status_t sl_btmesh_generic_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic and lighting client models. This command initializes all generic and lighting client models on the device. Alternatively, only the necessary client models can be initialized using model-specific initialization commands. Using model-specific initialization can result in a smaller firmware image size for SoC projects.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_common

`sl_status_t sl_btmesh_generic_client_init_common(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the generic client model common functionality. This command should be called only after all model-specific initialization calls for all generic and lighting client models on the device are done. An error will be returned if some of the generic and lighting client models were not initialized before calling this API. It does not need to be called if [sl_btmesh_generic_client_init](sl-btmesh-generic-client#sl-btmesh-generic-client-init) is used.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_on_off

`sl_status_t sl_btmesh_generic_client_init_on_off(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic on/off client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_level

`sl_status_t sl_btmesh_generic_client_init_level(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic level client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_default_transition_time

`sl_status_t sl_btmesh_generic_client_init_default_transition_time(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic default transition time client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_power_on_off

`sl_status_t sl_btmesh_generic_client_init_power_on_off(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic power on/off client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_power_level

`sl_status_t sl_btmesh_generic_client_init_power_level(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic power level client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_battery

`sl_status_t sl_btmesh_generic_client_init_battery(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic battery client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_location

`sl_status_t sl_btmesh_generic_client_init_location(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic location client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_property

`sl_status_t sl_btmesh_generic_client_init_property(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic property client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_lightness

`sl_status_t sl_btmesh_generic_client_init_lightness(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize light lightness client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_ctl

`sl_status_t sl_btmesh_generic_client_init_ctl(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize light CTL client models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_client_init_hsl

`sl_status_t sl_btmesh_generic_client_init_hsl(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize light HSL client models

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_generic_client_get_id 0x001e0028`

`#define sl_btmesh_cmd_generic_client_set_id 0x011e0028`

`#define sl_btmesh_cmd_generic_client_publish_id 0x021e0028`

`#define sl_btmesh_cmd_generic_client_get_params_id 0x031e0028`

`#define sl_btmesh_cmd_generic_client_init_id 0x041e0028`

`#define sl_btmesh_cmd_generic_client_init_common_id 0x051e0028`

`#define sl_btmesh_cmd_generic_client_init_on_off_id 0x061e0028`

`#define sl_btmesh_cmd_generic_client_init_level_id 0x071e0028`

`#define sl_btmesh_cmd_generic_client_init_default_transition_time_id 0x081e0028`

`#define sl_btmesh_cmd_generic_client_init_power_on_off_id 0x091e0028`

`#define sl_btmesh_cmd_generic_client_init_power_level_id 0x0a1e0028`

`#define sl_btmesh_cmd_generic_client_init_battery_id 0x0b1e0028`

`#define sl_btmesh_cmd_generic_client_init_location_id 0x0c1e0028`

`#define sl_btmesh_cmd_generic_client_init_property_id 0x0d1e0028`

`#define sl_btmesh_cmd_generic_client_init_lightness_id 0x0e1e0028`

`#define sl_btmesh_cmd_generic_client_init_ctl_id 0x0f1e0028`

`#define sl_btmesh_cmd_generic_client_init_hsl_id 0x101e0028`

`#define sl_btmesh_rsp_generic_client_get_id 0x001e0028`

`#define sl_btmesh_rsp_generic_client_set_id 0x011e0028`

`#define sl_btmesh_rsp_generic_client_publish_id 0x021e0028`

`#define sl_btmesh_rsp_generic_client_get_params_id 0x031e0028`

`#define sl_btmesh_rsp_generic_client_init_id 0x041e0028`

`#define sl_btmesh_rsp_generic_client_init_common_id 0x051e0028`

`#define sl_btmesh_rsp_generic_client_init_on_off_id 0x061e0028`

`#define sl_btmesh_rsp_generic_client_init_level_id 0x071e0028`

`#define sl_btmesh_rsp_generic_client_init_default_transition_time_id 0x081e0028`

`#define sl_btmesh_rsp_generic_client_init_power_on_off_id 0x091e0028`

`#define sl_btmesh_rsp_generic_client_init_power_level_id 0x0a1e0028`

`#define sl_btmesh_rsp_generic_client_init_battery_id 0x0b1e0028`

`#define sl_btmesh_rsp_generic_client_init_location_id 0x0c1e0028`

`#define sl_btmesh_rsp_generic_client_init_property_id 0x0d1e0028`

`#define sl_btmesh_rsp_generic_client_init_lightness_id 0x0e1e0028`

`#define sl_btmesh_rsp_generic_client_init_ctl_id 0x0f1e0028`

`#define sl_btmesh_rsp_generic_client_init_hsl_id 0x101e0028`

#### Generic Client Get State Types

Generic client get state type identifies the state which the client retrieves from the remote server model. 

##### Macros

`#define SL_BTMESH_GENERIC_CLIENT_STATE_ON_OFF 0x0`

**Description**: Generic on/off get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_ON_POWER_UP 0x1`

**Description**: Generic on power up get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LEVEL 0x2`

**Description**: Generic level get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_POWER_LEVEL 0x3`

**Description**: Generic power level get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_POWER_LEVEL_LAST 0x4`

**Description**: Generic power level last get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_POWER_LEVEL_DEFAULT 0x5`

**Description**: Generic power level default get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_POWER_LEVEL_RANGE 0x6`

**Description**: Generic power level range get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_TRANSITION_TIME 0x6`

**Description**: Generic transition time get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_BATTERY 0x8`

**Description**: Generic battery get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LOCATION_GLOBAL 0x9`

**Description**: Generic global location get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LOCATION_LOCAL 0xa`

**Description**: Generic local location get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_USER 0xb`

**Description**: Generic user property get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_ADMIN 0xc`

**Description**: Generic admin property get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_MANUF 0xd`

**Description**: Generic manufacturer property get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_LIST_USER 0xe`

**Description**: Generic user property list get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_LIST_ADMIN 0xf`

**Description**: Generic admin property list get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_LIST_MANUF 0x10`

**Description**: Generic manufacturer property list get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_PROPERTY_LIST_CLIENT 0x11`

**Description**: Generic client property list get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LIGHTNESS_ACTUAL 0x80`

**Description**: Light actual lightness get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LIGHTNESS_LINEAR 0x81`

**Description**: Light linear lightness get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LIGHTNESS_LAST 0x82`

**Description**: Light last lightness get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LIGHTNESS_DEFAULT 0x83`

**Description**: Light default lightness get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_LIGHTNESS_RANGE 0x84`

**Description**: Light lightness range get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_CTL 0x85`

**Description**: Light lightness, color temperature, and delta UV server state identifier. Not to be used by client get requests.

`#define SL_BTMESH_GENERIC_CLIENT_STATE_CTL_TEMPERATURE 0x86`

**Description**: Light color temperature and delta UV get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_CTL_DEFAULT 0x87`

**Description**: Light lightness, color temperature, and delta UV default get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_CTL_RANGE 0x88`

**Description**: Light color temperature range get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_CTL_LIGHTNESS_TEMPERATURE 0x89`

**Description**: Light lightness and color temperature get request.

`#define SL_BTMESH_GENERIC_CLIENT_STATE_HSL 0x8a`

**Description**: Light lightness, color hue, and color saturation current value get request.

`#define SL_BTMESH_GENERIC_CLIENT_STATE_HSL_HUE 0x8b`

**Description**: Light color hue get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_HSL_SATURATION 0x8c`

**Description**: Light color saturation get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_HSL_DEFAULT 0x8d`

**Description**: Light lightness, color hue, and color saturation default get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_HSL_RANGE 0x8e`

**Description**: Light color hue and saturation range get request

`#define SL_BTMESH_GENERIC_CLIENT_STATE_HSL_TARGET 0x8f`

**Description**: Light lightness, color hue, and color saturation target value get request.

#### Generic Client Set Request Types

Generic client set request type identifies the state which the client requests to be set to a new value on the remote server model. 

##### Macros

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_ON_OFF 0x0`

**Description**: Generic on/off set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_ON_POWER_UP 0x1`

**Description**: Generic on power up set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LEVEL 0x2`

**Description**: Generic level set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LEVEL_DELTA 0x3`

**Description**: Generic level delta set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LEVEL_MOVE 0x4`

**Description**: Generic level move set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LEVEL_HALT 0x5`

**Description**: Generic level halt request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_POWER_LEVEL 0x6`

**Description**: Generic power level set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_POWER_LEVEL_DEFAULT 0x7`

**Description**: Generic power level default set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_POWER_LEVEL_RANGE 0x8`

**Description**: Generic power level range set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_TRANSITION_TIME 0x9`

**Description**: Generic transition time set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LOCATION_GLOBAL 0xa`

**Description**: Generic global location set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LOCATION_LOCAL 0xb`

**Description**: Generic local location set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_PROPERTY_USER 0xc`

**Description**: Generic user property set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_PROPERTY_ADMIN 0xd`

**Description**: Generic admin property set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_PROPERTY_MANUF 0xe`

**Description**: Generic manufacturer property set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LIGHTNESS_ACTUAL 0x80`

**Description**: Light actual lightness set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LIGHTNESS_LINEAR 0x81`

**Description**: Light linear lightness set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LIGHTNESS_DEFAULT 0x82`

**Description**: Light default lightness set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_LIGHTNESS_RANGE 0x83`

**Description**: Light lightness range set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_CTL 0x84`

**Description**: Light lightness, color temperature, and delta UV set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_CTL_TEMPERATURE 0x85`

**Description**: Light color temperature and delta UV set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_CTL_DEFAULT 0x86`

**Description**: Light lightness, color temperature, and delta UV default set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_CTL_RANGE 0x87`

**Description**: Light color temperature range set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_HSL 0x88`

**Description**: Light lightness, color hue, and color saturation set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_HSL_HUE 0x89`

**Description**: Light color hue set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_HSL_SATURATION 0x8a`

**Description**: Light color saturation set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_HSL_DEFAULT 0x8b`

**Description**: Light lightness, color hue, and color saturation default set request

`#define SL_BTMESH_GENERIC_CLIENT_REQUEST_HSL_RANGE 0x8c`

**Description**: Light color hue and color saturation range set request

#### sl_btmesh_evt_generic_client_server_status

Status report sent by a server model. 

This may be generated either because of a response to a get or set request was received by the client model or because the client model received a spontaneously generated status indication sent to an address the model was subscribed to. 

##### Modules

[sl_btmesh_evt_generic_client_server_status_s](sl-btmesh-evt-generic-client-server-status-s)

##### Typedefs

###### sl_btmesh_evt_generic_client_server_status_t

`typedef struct sl_btmesh_evt_generic_client_server_status_s sl_btmesh_evt_generic_client_server_status_t`

##### Macros

`#define sl_btmesh_evt_generic_client_server_status_id 0x001e00a8`

**Description**: Identifier of the server_status event.

Data structure of the server_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_generic_client_server_status_s::client_address
```

**Details:** Address that the message was sent to, which can be either the model element's unicast address or a subscription address of the model

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_generic_client_server_status_s::elem_index
```

**Details:** Client model element index

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_generic_client_server_status_s::model_id
```

**Details:** Client model ID

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_generic_client_server_status_s::server_address
```

**Details:** Address of the server model which sent the message

###### remaining_ms (heading level 7)

```
uint32_t sl_btmesh_evt_generic_client_server_status_s::remaining_ms
```

**Details:** Time (in milliseconds) remaining before transition from the current state to target state is complete. Set to zero if no transition is taking place or if transition time does not apply to the message.

###### flags (heading level 7)

```
uint16_t sl_btmesh_evt_generic_client_server_status_s::flags
```

**Details:** Message flags. It is a bitmask of the following values:

- **Bit 0:** Non-relayed. If non-zero, indicates a response to a non-relayed request.

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_generic_client_server_status_s::type
```

**Details:** Model-specific state type, identifying the kind of state reported in the status event. See get state types list for details.

###### parameters (heading level 7)

```
uint8array sl_btmesh_evt_generic_client_server_status_s::parameters
```

**Details:** Message-specific parameters, serialized into a byte array

### Bluetooth Mesh Generic Server Model

Bluetooth Mesh Generic Server Model. 

Generic server model API provides functionality to send and receive messages using Bluetooth SIG server models, including generic server models and lighting server models.

Throughout the API the server model being used is identified by its element address and model ID, while the client model generating requests to the server model is identified by its element address and model ID.

The generic server model API is designed on the premise that the actual state the model represents resides in and is owned by the application, not by the stack.

The model acts as a cache for client queries. In other words, the stack handles state requests from the client automatically. The application does not need to handle those. The cached value is also used for periodic publication.

The flip side of caching is that when the state represented by the model changes in the application, it must update the cached value to the stack by issuing a [sl_btmesh_generic_server_update](sl-btmesh-generic-server#sl-btmesh-generic-server-update) command.

When a client model requests a state change, the stack will generate a [sl_btmesh_evt_generic_server_client_request](sl-btmesh-evt-generic-server-client-request) event which the application must process. Then, if the client needs a response the application has to issue a [sl_btmesh_generic_server_respond](sl-btmesh-generic-server#sl-btmesh-generic-server-respond) command corresponding to the request. Otherwise, the application only has to update the state with a [sl_btmesh_generic_server_update](sl-btmesh-generic-server#sl-btmesh-generic-server-update) command, which does not result in sending any messages to the network.

Note that, because the Mesh Model specification requires that certain states are bound together and because the stack enforces that, updating one cached state may result in an update of the corresponding bound state, for which the stack generates a [sl_btmesh_evt_generic_server_state_changed](sl-btmesh-evt-generic-server-state-changed) event. For example, when a dimmable light is switched off, the lightness level bound to the on/off state, is also set to zero because the states are bound.

Data for state change requests and server responses is passed as serialized byte arrays through BGAPI. Bluetooth mesh SDK has functions to convert byte arrays to and from model state structures.

The stack will handle Mesh transaction layer segmentation and reassembly automatically if the messages sent are long enough to require it.

**Note on time resolution**

Because of message formatting, transition time and remaining time resolution units depend on the requested or reported value. For example, until 6.2 seconds it is 100 ms; until 62 seconds it is 1 s; until 620 seconds it is 10 s; and until 620 minutes it is 10 minutes. The value can't be longer than 620 minutes. Therefore, it is not possible to request a delay of exactly 7500 ms. The resolution unit is 1 s between 6.2 and 62 seconds, so the value is rounded down to 7 s.

Delay resolution is 5 ms and values will be rounded down to the closest 5 ms. The value can't be longer than 1275 ms. 

#### Modules

[sl_btmesh_evt_generic_server_client_request](sl-btmesh-evt-generic-server-client-request)

[sl_btmesh_evt_generic_server_state_changed](sl-btmesh-evt-generic-server-state-changed)

[sl_btmesh_evt_generic_server_state_recall](sl-btmesh-evt-generic-server-state-recall)

#### Functions

##### sl_btmesh_generic_server_respond

`sl_status_t sl_btmesh_generic_server_respond(uint16_t client_address, uint16_t elem_index, uint16_t model_id, uint16_t appkey_index, uint32_t remaining_ms, uint16_t flags, uint8_t type, size_t parameters_len, const uint8_t *parameters)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Address of the client model which sent the message|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|model_id|Server model ID|
|uint16_t|[in]|appkey_index|The application key index used|
|uint32_t|[in]|remaining_ms|Time (in milliseconds) remaining before transition from current state to target state is complete. Set to zero if no transition is taking place or if the transition time does not apply to the state change.|
|uint16_t|[in]|flags|Message flags. Bitmask of the following:<br/><br/>- **Bit 0:** Non-relayed. If non-zero, indicates a response to a non-relayed request.|
|uint8_t|[in]|type|Model-specific state type, identifying the kind of state to be updated. See [Generic Client Get State Types](sl-btmesh-generic-client-get-state-type) list for details.|
|size_t|[in]|parameters_len|Length of data in `parameters`|
|const uint8_t *|[in]|parameters|Message-specific parameters serialized into a byte array|

Server response to a client request. This command must be used when an application updates the server model state as a response to a [sl_btmesh_evt_generic_server_client_request](sl-btmesh-evt-generic-server-client-request) event which required a response.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_update

`sl_status_t sl_btmesh_generic_server_update(uint16_t elem_index, uint16_t model_id, uint32_t remaining_ms, uint8_t type, size_t parameters_len, const uint8_t *parameters)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|model_id|Server model ID|
|uint32_t|[in]|remaining_ms|Time (in milliseconds) remaining before transition from current state to target state is complete. Set to zero if no transition is taking place or if transition time does not apply to the state change.|
|uint8_t|[in]|type|Model-specific state type, identifying the kind of state to be updated. See [Generic Client Get State Types](sl-btmesh-generic-client-get-state-type) list for details.|
|size_t|[in]|parameters_len|Length of data in `parameters`|
|const uint8_t *|[in]|parameters|Message-specific parameters, serialized into a byte array|

Server state update. This command must be used when an application updates the server model state as a response to a [sl_btmesh_evt_generic_server_client_request](sl-btmesh-evt-generic-server-client-request) event which did not require a response, but also when the application state changes spontaneously or as a result of some external (non-Mesh) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_publish

`sl_status_t sl_btmesh_generic_server_publish(uint16_t elem_index, uint16_t model_id, uint8_t type)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|model_id|Server model ID|
|uint8_t|[in]|type|Model-specific state type, identifying the kind of state used in the published message. See [Generic Client Get State Types](sl-btmesh-generic-client-get-state-type) list for details.|

Publish the server state to the network using the publish parameters configured in the model. The message is constructed using the cached state in the stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init

`sl_status_t sl_btmesh_generic_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic and lighting server models. This command initializes all generic and lighting server models on the device. Alternatively, only the necessary server models can be initialized using model-specific initialization commands. Using model-specific initialization can result in a smaller firmware image size for SoC projects.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_common

`sl_status_t sl_btmesh_generic_server_init_common(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the generic server model common functionality. This should be called only after all model-specific initialization calls for all generic and lighting server models on the device are done. An error will be returned if some of the generic and lighting server models were not initialized before calling this API. It does not need to be called if [sl_btmesh_generic_server_init](sl-btmesh-generic-server#sl-btmesh-generic-server-init) is used.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_on_off

`sl_status_t sl_btmesh_generic_server_init_on_off(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic on/off server models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_level

`sl_status_t sl_btmesh_generic_server_init_level(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic level server models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_default_transition_time

`sl_status_t sl_btmesh_generic_server_init_default_transition_time(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic default transition time server models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_power_on_off

`sl_status_t sl_btmesh_generic_server_init_power_on_off(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic power on/off server models, power on/off setup server models, and all models they extend.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_power_level

`sl_status_t sl_btmesh_generic_server_init_power_level(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic power level server models, power level setup server models, and all models they extend.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_battery

`sl_status_t sl_btmesh_generic_server_init_battery(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic battery server models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_location

`sl_status_t sl_btmesh_generic_server_init_location(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic location and generic location setup server models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_property

`sl_status_t sl_btmesh_generic_server_init_property(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize generic property server models.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_lightness

`sl_status_t sl_btmesh_generic_server_init_lightness(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize light lightness server models, light lightness setup server models, and all models they extend.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_ctl

`sl_status_t sl_btmesh_generic_server_init_ctl(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize light CTL server models, light CTL temperature server models, light CTL setup server models, and all models they extend.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_init_hsl

`sl_status_t sl_btmesh_generic_server_init_hsl(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize light HSL server models, light HSL hue server models, light HSL saturation server models, light HSL setup server models, and all models they extend

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_generic_server_get_cached_state

`sl_status_t sl_btmesh_generic_server_get_cached_state(uint16_t elem_index, uint16_t model_id, uint8_t type, uint32_t *remaining_ms, size_t max_parameters_size, size_t *parameters_len, uint8_t *parameters)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|model_id|Server model ID|
|uint8_t|[in]|type|Model-specific state type, identifying the kind of state reported in the state change event. See [Generic Client Get State Types](sl-btmesh-generic-client-get-state-type) list for details.|
|uint32_t *|[out]|remaining_ms|Time (in milliseconds) remaining before transition from current state to target state is complete. Ignored if no transition is taking place.|
|size_t|[in]|max_parameters_size|Size of output buffer passed in `parameters`|
|size_t *|[out]|parameters_len|On return, set to the length of output data written to `parameters`|
|uint8_t *|[out]|parameters|Message-specific parameters, serialized into a byte array|

Get model cached state. This command can be used to get cached model states after scene recall when using compacted recall events. This command supports only those states that would have been reported by [sl_btmesh_evt_generic_server_state_recall](sl-btmesh-evt-generic-server-state-recall) events.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_generic_server_respond_id 0x001f0028`

`#define sl_btmesh_cmd_generic_server_update_id 0x011f0028`

`#define sl_btmesh_cmd_generic_server_publish_id 0x021f0028`

`#define sl_btmesh_cmd_generic_server_init_id 0x041f0028`

`#define sl_btmesh_cmd_generic_server_init_common_id 0x051f0028`

`#define sl_btmesh_cmd_generic_server_init_on_off_id 0x061f0028`

`#define sl_btmesh_cmd_generic_server_init_level_id 0x071f0028`

`#define sl_btmesh_cmd_generic_server_init_default_transition_time_id 0x081f0028`

`#define sl_btmesh_cmd_generic_server_init_power_on_off_id 0x091f0028`

`#define sl_btmesh_cmd_generic_server_init_power_level_id 0x0a1f0028`

`#define sl_btmesh_cmd_generic_server_init_battery_id 0x0b1f0028`

`#define sl_btmesh_cmd_generic_server_init_location_id 0x0c1f0028`

`#define sl_btmesh_cmd_generic_server_init_property_id 0x0d1f0028`

`#define sl_btmesh_cmd_generic_server_init_lightness_id 0x0e1f0028`

`#define sl_btmesh_cmd_generic_server_init_ctl_id 0x0f1f0028`

`#define sl_btmesh_cmd_generic_server_init_hsl_id 0x101f0028`

`#define sl_btmesh_cmd_generic_server_get_cached_state_id 0x111f0028`

`#define sl_btmesh_rsp_generic_server_respond_id 0x001f0028`

`#define sl_btmesh_rsp_generic_server_update_id 0x011f0028`

`#define sl_btmesh_rsp_generic_server_publish_id 0x021f0028`

`#define sl_btmesh_rsp_generic_server_init_id 0x041f0028`

`#define sl_btmesh_rsp_generic_server_init_common_id 0x051f0028`

`#define sl_btmesh_rsp_generic_server_init_on_off_id 0x061f0028`

`#define sl_btmesh_rsp_generic_server_init_level_id 0x071f0028`

`#define sl_btmesh_rsp_generic_server_init_default_transition_time_id 0x081f0028`

`#define sl_btmesh_rsp_generic_server_init_power_on_off_id 0x091f0028`

`#define sl_btmesh_rsp_generic_server_init_power_level_id 0x0a1f0028`

`#define sl_btmesh_rsp_generic_server_init_battery_id 0x0b1f0028`

`#define sl_btmesh_rsp_generic_server_init_location_id 0x0c1f0028`

`#define sl_btmesh_rsp_generic_server_init_property_id 0x0d1f0028`

`#define sl_btmesh_rsp_generic_server_init_lightness_id 0x0e1f0028`

`#define sl_btmesh_rsp_generic_server_init_ctl_id 0x0f1f0028`

`#define sl_btmesh_rsp_generic_server_init_hsl_id 0x101f0028`

`#define sl_btmesh_rsp_generic_server_get_cached_state_id 0x111f0028`

#### sl_btmesh_evt_generic_server_client_request

State change request sent by a client model. 

This may be generated either because of a request directly to this model, or a request sent to an address which is subscribed to by the model. 

##### Modules

[sl_btmesh_evt_generic_server_client_request_s](sl-btmesh-evt-generic-server-client-request-s)

##### Typedefs

###### sl_btmesh_evt_generic_server_client_request_t

`typedef struct sl_btmesh_evt_generic_server_client_request_s sl_btmesh_evt_generic_server_client_request_t`

##### Macros

`#define sl_btmesh_evt_generic_server_client_request_id 0x001f00a8`

**Description**: Identifier of the client_request event.

Data structure of the client_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::server_address
```

**Details:** Address the message was sent to, which can be either the model element's unicast address, or model's subscription address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::elem_index
```

**Details:** Server model element index

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::model_id
```

**Details:** Server model ID

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::client_address
```

**Details:** Address of the client model which sent the message

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::appkey_index
```

**Details:** The application key index used in encrypting the request; Responses need to be encrypted with the same key.

###### transition_ms (heading level 7)

```
uint32_t sl_btmesh_evt_generic_server_client_request_s::transition_ms
```

**Details:** Requested transition time (in milliseconds) for the state change. If both the transition time and the delay are zero, the transition is immediate.

This applies to messages, which the Mesh Model specification defines to have transition and delay times and will be zero for others.

###### delay_ms (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::delay_ms
```

**Details:** Delay time (in milliseconds) before starting the state change. If both the transition time and the delay are zero, the transition is immediate.

This applies to messages, which the Mesh Model specification defines to have transition and delay times and will be zero for others.

###### flags (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_client_request_s::flags
```

**Details:** Message flags. Bitmask of the following values:

- **Bit 0:** Non-relayed. If non-zero, indicates that the client message was not relayed (TTL was zero) and that the server is within direct radio range of the client.
- **Bit 1:** Response required. If non-zero, the client expects a response from the server.

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_generic_server_client_request_s::type
```

**Details:** Model-specific request type. See set request types list for details.

###### parameters (heading level 7)

```
uint8array sl_btmesh_evt_generic_server_client_request_s::parameters
```

**Details:** Message-specific parameters serialized into a byte array

#### sl_btmesh_evt_generic_server_state_changed

Cached model state changed. 

This may happen either as a direct result of model state update by the application, in which case the event can be ignored, or because the update of one model state resulted in an update of a bound model state according to the Mesh model specification. In this case, the application should update its own value accordingly. 

##### Modules

[sl_btmesh_evt_generic_server_state_changed_s](sl-btmesh-evt-generic-server-state-changed-s)

##### Typedefs

###### sl_btmesh_evt_generic_server_state_changed_t

`typedef struct sl_btmesh_evt_generic_server_state_changed_s sl_btmesh_evt_generic_server_state_changed_t`

##### Macros

`#define sl_btmesh_evt_generic_server_state_changed_id 0x011f00a8`

**Description**: Identifier of the state_changed event.

Data structure of the state_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_state_changed_s::elem_index
```

**Details:** Server model element index

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_state_changed_s::model_id
```

**Details:** Server model ID

###### remaining_ms (heading level 7)

```
uint32_t sl_btmesh_evt_generic_server_state_changed_s::remaining_ms
```

**Details:** Time (in milliseconds) remaining before transition from current state to target state is complete. Ignored if no transition is taking place.

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_generic_server_state_changed_s::type
```

**Details:** Model-specific state type, identifying the kind of state reported in the state change event. See get state types list for details.

###### parameters (heading level 7)

```
uint8array sl_btmesh_evt_generic_server_state_changed_s::parameters
```

**Details:** Message-specific parameters, serialized into a byte array

#### sl_btmesh_evt_generic_server_state_recall

Cached model state changed due to scene recall operation. 

##### Modules

[sl_btmesh_evt_generic_server_state_recall_s](sl-btmesh-evt-generic-server-state-recall-s)

##### Typedefs

###### sl_btmesh_evt_generic_server_state_recall_t

`typedef struct sl_btmesh_evt_generic_server_state_recall_s sl_btmesh_evt_generic_server_state_recall_t`

##### Macros

`#define sl_btmesh_evt_generic_server_state_recall_id 0x021f00a8`

**Description**: Identifier of the state_recall event.

Data structure of the state_recall event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_state_recall_s::elem_index
```

**Details:** Server model element index

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_generic_server_state_recall_s::model_id
```

**Details:** Server model ID

###### transition_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_generic_server_state_recall_s::transition_time_ms
```

**Details:** Time (in milliseconds) remaining before transition from current state to target state should be complete. Ignored if no transition is taking place.

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_generic_server_state_recall_s::type
```

**Details:** Model-specific state type, identifying the kind of state reported in the state change event. See get state types list for details.

###### parameters (heading level 7)

```
uint8array sl_btmesh_evt_generic_server_state_recall_s::parameters
```

**Details:** Model state - specific parameters, serialized into a byte array

### Bluetooth Mesh Test Utilities

Bluetooth Mesh Test Utilities. 

These commands are meant for development and testing. Do not use in production software. 

#### Modules

[sl_btmesh_evt_test_local_heartbeat_subscription_complete](sl-btmesh-evt-test-local-heartbeat-subscription-complete)

[sl_btmesh_evt_test_replay_protection_list_entry_set](sl-btmesh-evt-test-replay-protection-list-entry-set)

[sl_btmesh_evt_test_replay_protection_list_entry_cleared](sl-btmesh-evt-test-replay-protection-list-entry-cleared)

[sl_btmesh_evt_test_replay_protection_list_saved](sl-btmesh-evt-test-replay-protection-list-saved)

[sl_btmesh_evt_test_replay_protection_list_full](sl-btmesh-evt-test-replay-protection-list-full)

#### Enumerations

##### sl_btmesh_test_key_type_t

```
enum sl_btmesh_test_key_type_t {
    sl_btmesh_test_key_type_net = 0x0
    sl_btmesh_test_key_type_app = 0x1
}
```

**Description:**

Specify the type of a key in key manipulation commands.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_test_key_type_net|(0x0) Network key|
|sl_btmesh_test_key_type_app|(0x1) Application key|

#### Functions

##### sl_btmesh_test_get_nettx

`sl_status_t sl_btmesh_test_get_nettx(uint8_t *count, uint8_t *interval)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|count|Number of network layer transmissions beyond the initial one. Range: 0-7.|
|uint8_t *|[out]|interval|Transmit interval steps. The interval between transmissions is a random value between 10*(1+steps) and 10*(2+steps) milliseconds. For example, for a value of 2, the interval is between 30 and 40 milliseconds. Range: 0-31.|

Get the network transmit state of a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_nettx

`sl_status_t sl_btmesh_test_set_nettx(uint8_t count, uint8_t interval)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|count|Number of network layer transmissions beyond the initial one. Range: 0-7.|
|uint8_t|[in]|interval|Transmit interval steps. The interval between transmissions is a random value between 10*(1+steps) and 10*(2+steps) milliseconds. For example, for a value of 2 the interval would be between 30 and 40 milliseconds. Range: 0-31.|

Set the network transmit state of a node locally. Normally, the network transmit state is controlled by the Provisioner. This command overrides any setting done by the Provisioner.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_relay

`sl_status_t sl_btmesh_test_get_relay(uint8_t *enabled, uint8_t *count, uint8_t *interval)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|enabled|State value indicating whether the relay functionality is not enabled on the node (0), is enabled on the node (1), or is not available (2).|
|uint8_t *|[out]|count|Number of relay transmissions beyond the initial one. Range: 0-7.|
|uint8_t *|[out]|interval|Relay retransmit interval steps. The interval between transmissions is 10*(1+steps) milliseconds. Range: 0-31.|

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_relay

`sl_status_t sl_btmesh_test_set_relay(uint8_t enabled, uint8_t count, uint8_t interval)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|enabled|Indicates whether the relay functionality is enabled on the node (1) or not (0); value indicating disabled (2) can't be set.|
|uint8_t|[in]|count|Number of relay transmissions beyond the initial one. Range: 0-7.|
|uint8_t|[in]|interval|Relay retransmit interval steps. The interval between transmissions is 10*(1+steps) milliseconds. Range: 0-31.|

Set the relay state and the relay retransmit state of a node locally. Normally, these states are controlled by the Provisioner. This command overrides any settings done by the Provisioner.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_ivupdate_test_mode

`sl_status_t sl_btmesh_test_set_ivupdate_test_mode(uint8_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|mode|Whether test mode is enabled (1) or disabled (0).|

By default, IV index update is limited in how often the update procedure can be performed. This test command can be called to set IV update test mode where any time limits are ignored.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_ivupdate_test_mode

`sl_status_t sl_btmesh_test_get_ivupdate_test_mode(uint8_t *mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|mode|Indicates whether test mode is enabled (1) or disabled (0).|

Get the current IV update test mode. See [sl_btmesh_test_set_ivupdate_test_mode](sl-btmesh-test#sl-btmesh-test-set-ivupdate-test-mode) for details.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_ivupdate_state

`sl_status_t sl_btmesh_test_set_ivupdate_state(uint8_t state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|state|Indicates whether IV update state should be entered (1) or exited (0).|

Forcefully change the IV update state on the device. Normally, the state changes as a result of an IV index update procedure progressing from one state to the next.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_send_beacons

`sl_status_t sl_btmesh_test_send_beacons(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Send secure network beacons for every network key on the device, regardless of beacon configuration state or how many beacons sent by other devices have been observed.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_bind_local_model_app

`sl_status_t sl_btmesh_test_bind_local_model_app(uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target Element, 0 is primary element|
|uint16_t|[in]|appkey_index|The Appkey to use for binding|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for SIG models.|
|uint16_t|[in]|model_id|Model ID|

Bind a Model to an Appkey locally.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_unbind_local_model_app

`sl_status_t sl_btmesh_test_unbind_local_model_app(uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is primary element|
|uint16_t|[in]|appkey_index|The Appkey to use for binding|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for SIG models.|
|uint16_t|[in]|model_id|Model ID|

Remove a binding between a model and an application key locally.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_add_local_model_sub

`sl_status_t sl_btmesh_test_add_local_model_sub(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|uint16_t|[in]|sub_address|The address to add to the subscription list|

Add an address to a local model's subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_remove_local_model_sub

`sl_status_t sl_btmesh_test_remove_local_model_sub(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|uint16_t|[in]|sub_address|The address to remove from the subscription list|

Remove an address from a local model's subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_add_local_model_sub_va

`sl_status_t sl_btmesh_test_add_local_model_sub_va(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, size_t sub_address_len, const uint8_t *sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|size_t|[in]|sub_address_len|Length of data in `sub_address`|
|const uint8_t *|[in]|sub_address|The Label UUID to add to the subscription list. The array must be exactly 16 bytes long.|

Add a virtual address to a local model's subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_remove_local_model_sub_va

`sl_status_t sl_btmesh_test_remove_local_model_sub_va(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, size_t sub_address_len, const uint8_t *sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|size_t|[in]|sub_address_len|Length of data in `sub_address`|
|const uint8_t *|[in]|sub_address|The Label UUID to remove from the subscription list. The array must be exactly 16 bytes long.|

Remove a virtual address from a local model's subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_local_model_sub

`sl_status_t sl_btmesh_test_get_local_model_sub(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, size_t max_addresses_size, size_t *addresses_len, uint8_t *addresses)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|size_t|[in]|max_addresses_size|Size of output buffer passed in `addresses`|
|size_t *|[out]|addresses_len|On return, set to the length of output data written to `addresses`|
|uint8_t *|[out]|addresses|List of 16-bit Mesh addresses; empty if not subscribed to any address. Ignore if the result code is non-zero.|

Get all entries in a local model's subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_local_model_pub

`sl_status_t sl_btmesh_test_set_local_model_pub(uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id, uint16_t model_id, uint16_t pub_address, uint8_t ttl, uint8_t period, uint8_t retrans, uint8_t credentials)`

**Parameters:**

<table>
  <thead>
    <th>Type</th>
    <th>Direction</th>
    <th>Argument Name</th>
    <th>Description</th>
  </thead>
  <tbody>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>elem_index</td>
      <td>The index of the target element, where 0 is the primary element</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>appkey_index</td>
      <td>The application key index to use for the application messages published</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>vendor_id</td>
      <td>Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>model_id</td>
      <td>Model ID</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>pub_address</td>
      <td>The address to publish to</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>ttl</td>
      <td>Time-to-Live value for published messages. Valid values: range[0 - 127] and 255.</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>period</td>
      <td>Publication period encoded as step count and step resolution. The encoding is as follows:

- **Bits 0..5:** Step count
- **Bits 6..7:** Step resolution:  
  - 00: 100 milliseconds  
  - 01: 1 second  
  - 10: 10 seconds  
  - 11: 10 minutes</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>retrans</td>
      <td>Retransmission count and interval, which controls number of times that the model re-publishes the same message after the initial publish transmission and the cadence of retransmissions.

Retransmission count is encoded in the three low bits of the value, ranging from 0 to 7. Default value is 0 (no retransmissions).

Retransmission interval is encoded in the five high bits of the value, ranging from 0 to 31, in 50-millisecond units. Value of 0 corresponds to 50 ms, while value of 31 corresponds to 1600 ms.</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>credentials</td>
      <td>Friendship credentials flag</td>
    </tr>
  </tbody>
</table>

Set a local model's publication address, key, and parameters.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_local_model_pub_va

`sl_status_t sl_btmesh_test_set_local_model_pub_va(uint16_t elem_index, uint16_t appkey_index, uint16_t vendor_id, uint16_t model_id, uint8_t ttl, uint8_t period, uint8_t retrans, uint8_t credentials, size_t pub_address_len, const uint8_t *pub_address)`

**Parameters:**

<table>
  <thead>
    <th>Type</th>
    <th>Direction</th>
    <th>Argument Name</th>
    <th>Description</th>
  </thead>
  <tbody>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>elem_index</td>
      <td>The index of the target element, 0 is the primary element</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>appkey_index</td>
      <td>The application key index to use for the published messages</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>vendor_id</td>
      <td>Vendor ID of the configured model. Use 0xffff for Bluetooth SIG models.</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>model_id</td>
      <td>Model ID of the configured model</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>ttl</td>
      <td>Publication time-to-live value. Valid values: range[0 - 127] and 255.</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>period</td>
      <td>Publication period encoded as step count and step resolution. The encoding is as follows:

- **Bits 0..5:** Step count
- **Bits 6..7:** Step resolution:  
  - 00: 100 milliseconds  
  - 01: 1 second  
  - 10: 10 seconds  
  - 11: 10 minutes</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>retrans</td>
      <td>See documentation of [sl_btmesh_test_set_local_model_pub](sl-btmesh-test#sl-btmesh-test-set-local-model-pub) for details.</td>
    </tr>
    <tr>
      <td>uint8_t</td>
      <td>[in]</td>
      <td>credentials</td>
      <td>Friendship credentials flag</td>
    </tr>
    <tr>
      <td>size_t</td>
      <td>[in]</td>
      <td>pub_address_len</td>
      <td>Length of data in `pub_address`</td>
    </tr>
    <tr>
      <td>const uint8_t *</td>
      <td>[in]</td>
      <td>pub_address</td>
      <td>The Label UUID to publish to. The byte array must be exactly 16 bytes long.</td>
    </tr>
  </tbody>
</table>

Set a model's publication virtual address, key, and parameters.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_local_model_pub

`sl_status_t sl_btmesh_test_get_local_model_pub(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t *appkey_index, uint16_t *pub_address, uint8_t *ttl, uint8_t *period, uint8_t *retrans, uint8_t *credentials)`

**Parameters:**

<table>
  <thead>
    <th>Type</th>
    <th>Direction</th>
    <th>Argument Name</th>
    <th>Description</th>
  </thead>
  <tbody>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>elem_index</td>
      <td>The index of the target element, 0 is the primary element</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>vendor_id</td>
      <td>Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.</td>
    </tr>
    <tr>
      <td>uint16_t</td>
      <td>[in]</td>
      <td>model_id</td>
      <td>Model ID</td>
    </tr>
    <tr>
      <td>uint16_t *</td>
      <td>[out]</td>
      <td>appkey_index</td>
      <td>The application key index used for the application messages published</td>
    </tr>
    <tr>
      <td>uint16_t *</td>
      <td>[out]</td>
      <td>pub_address</td>
      <td>The address published to</td>
    </tr>
    <tr>
      <td>uint8_t *</td>
      <td>[out]</td>
      <td>ttl</td>
      <td>Time-to-Live value for published messages</td>
    </tr>
    <tr>
      <td>uint8_t *</td>
      <td>[out]</td>
      <td>period</td>
      <td>Publication period encoded as step count and step resolution. The encoding is as follows:

- **Bits 0..5:** Step count
- **Bits 6..7:** Step resolution:  
  - 00: 100 milliseconds  
  - 01: 1 second  
  - 10: 10 seconds  
  - 11: 10 minutes</td>
    </tr>
    <tr>
      <td>uint8_t *</td>
      <td>[out]</td>
      <td>retrans</td>
      <td>See documentation of [sl_btmesh_test_set_local_model_pub](sl-btmesh-test#sl-btmesh-test-set-local-model-pub) for details.</td>
    </tr>
    <tr>
      <td>uint8_t *</td>
      <td>[out]</td>
      <td>credentials</td>
      <td>Friendship credentials flag</td>
    </tr>
  </tbody>
</table>

Get a local model's publication address, key, and parameters.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_local_heartbeat_subscription

`sl_status_t sl_btmesh_test_set_local_heartbeat_subscription(uint16_t subscription_source, uint16_t subscription_destination, uint8_t period_log)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|subscription_source|Source address for heartbeat messages. Must be either a unicast address or the unassigned address, in which case heartbeat messages are not processed.|
|uint16_t|[in]|subscription_destination|Destination address for heartbeat messages. The address must be either the unicast address of the primary element of the node, a group address, or the unassigned address. If it is the unassigned address, heartbeat messages are not processed.|
|uint8_t|[in]|period_log|Heartbeat subscription period setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not received<br/>- **0x01 .. 0x11:** Node will receive heartbeat messages for 2^(n-1) seconds<br/>- **0x12 .. 0xff:** Prohibited|

Set local node heartbeat subscription parameters. Normally heartbeat subscription is controlled by the Provisioner.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_local_heartbeat_subscription

`sl_status_t sl_btmesh_test_get_local_heartbeat_subscription(uint16_t *count, uint8_t *hop_min, uint8_t *hop_max)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|count|Number of received heartbeat messages|
|uint8_t *|[out]|hop_min|Minimum observed hop count in heartbeat messages|
|uint8_t *|[out]|hop_max|Maximum observed hop count in heartbeat messages|

Get the local node heartbeat subscription state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_local_heartbeat_publication

`sl_status_t sl_btmesh_test_get_local_heartbeat_publication(uint16_t *publication_address, uint8_t *count, uint8_t *period_log, uint8_t *ttl, uint16_t *features, uint16_t *publication_netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|publication_address|Heartbeat publication address|
|uint8_t *|[out]|count|Heartbeat publication remaining count|
|uint8_t *|[out]|period_log|Heartbeat publication period setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not sent<br/>- **0x01 .. 0x11:** Node will send a heartbeat message every 2^(n-1) seconds<br/>- **0x12 .. 0xff:** Prohibited|
|uint8_t *|[out]|ttl|Time-to-live parameter for heartbeat messages|
|uint16_t *|[out]|features|Heartbeat trigger setting|
|uint16_t *|[out]|publication_netkey_index|Index of the network key used to encrypt heartbeat messages|

Get the heartbeat publication state of a local node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_local_heartbeat_publication

`sl_status_t sl_btmesh_test_set_local_heartbeat_publication(uint16_t publication_address, uint8_t count_log, uint8_t period_log, uint8_t ttl, uint16_t features, uint16_t publication_netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|publication_address|Heartbeat publication address. The address can't be a virtual address. Note that it can be the unassigned address, in which case the heartbeat publishing is disabled.|
|uint8_t|[in]|count_log|Heartbeat publication count setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not sent<br/>- **0x01 .. 0x11:** Node will send 2^(n-1) heartbeat messages<br/>- **0x12 .. 0xfe:** Prohibited<br/>- **0xff:** Hearbeat messages are sent indefinitely|
|uint8_t|[in]|period_log|Heartbeat publication period setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not sent<br/>- **0x01 .. 0x11:** Node will send a heartbeat message every 2^(n-1) seconds<br/>- **0x12 .. 0xff:** Prohibited|
|uint8_t|[in]|ttl|Time-to-live parameter for heartbeat messages. Valid values: range[0 - 127].|
|uint16_t|[in]|features|Heartbeat trigger setting. For bits set in the bitmask, reconfiguration of the node feature associated with the bit will result in the node emitting a heartbeat message. Valid values are as follows:<br/><br/>- **Bit 0:** Relay feature<br/>- **Bit 1:** Proxy feature<br/>- **Bit 2:** Friend feature<br/>- **Bit 3:** Low power feature<br/><br/>Remaining bits are reserved for future use.|
|uint16_t|[in]|publication_netkey_index|Index of the network key used to encrypt heartbeat messages|

Set the heartbeat publication state of a local node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_add_local_key

`sl_status_t sl_btmesh_test_add_local_key(uint8_t key_type, aes_key_128 key, uint16_t key_index, uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|key_type|Enum [sl_btmesh_test_key_type_t](sl-btmesh-test#sl-btmesh-test-key-type-t). 0 for network key, 1 for application key|
|[aes_key_128](aes-key-128)|[in]|key|Key data|
|uint16_t|[in]|key_index|Index for the added key (must be unused)|
|uint16_t|[in]|netkey_index|Network key index to which the application key is bound; ignored for network keys|

Add a network or application key locally.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_remove_local_key

`sl_status_t sl_btmesh_test_remove_local_key(uint8_t key_type, uint16_t key_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|key_type|Enum [sl_btmesh_test_key_type_t](sl-btmesh-test#sl-btmesh-test-key-type-t). 0 for network key, 1 for application key|
|uint16_t|[in]|key_index|Index of the key to delete|

Delete a network or application key locally.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_update_local_key

`sl_status_t sl_btmesh_test_update_local_key(uint8_t key_type, aes_key_128 key, uint16_t key_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|key_type|Enum [sl_btmesh_test_key_type_t](sl-btmesh-test#sl-btmesh-test-key-type-t). 0 for network key, 1 for application key|
|[aes_key_128](aes-key-128)|[in]|key|Key data|
|uint16_t|[in]|key_index|Index for the key to update|

Update the network or application key value locally.

Copies the existing network key value to the old value and replaces the current value with the given key data.

Note that the standard way to update keys on the Provisioner as well as on nodes is to run the key refresh procedure. This command is for debugging only.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_adv_bearer_state

`sl_status_t sl_btmesh_test_set_adv_bearer_state(uint8_t state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|state|0: disable advertisement, 1: enable advertisement.|

Disable or enable advertisement bearer for sending.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_prov_get_device_key

`sl_status_t sl_btmesh_test_prov_get_device_key(uint16_t address, aes_key_128 *device_key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Address of the node|
|[aes_key_128](aes-key-128) *|[out]|device_key|Device key, 16-bytes|

Get the device key with the address of the node's primary element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_prov_prepare_key_refresh

`SL_BGAPI_DEPRECATED sl_status_t sl_btmesh_test_prov_prepare_key_refresh(aes_key_128 net_key, size_t app_keys_len, const uint8_t *app_keys)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[aes_key_128](aes-key-128)|[in]|net_key|New net key|
|size_t|[in]|app_keys_len|Length of data in `app_keys`|
|const uint8_t *|[in]|app_keys|list of new application keys, 16-bytes each|

Prepare the key refresh by feeding the new network key and all needed application keys. The function can be called multiple times to include more application keys. The network key must be the same in all calls. If the network key is changed, the network key from the 1st command is used. Sending application key data with length zero results in all initialization data being forgotten unless this is done in the first prepare command i.e., trying to update only the network key. Also starting the key refresh procedure results in all the preparation data being forgotten.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_cancel_segmented_tx

`sl_status_t sl_btmesh_test_cancel_segmented_tx(uint16_t src_addr, uint16_t dst_addr)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|src_addr|Source address for the segmented message|
|uint16_t|[in]|dst_addr|Destination address for the segmented message|

Cancel sending a segmented message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_iv_index

`sl_status_t sl_btmesh_test_set_iv_index(uint32_t iv_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|iv_index|IV Index value to use|

Set the IV index value of the node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_element_seqnum

`sl_status_t sl_btmesh_test_set_element_seqnum(uint16_t elem_index, uint32_t seqnum)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint32_t|[in]|seqnum|Sequence number to set on the target element|

Set the current sequence number of an element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_model_option

`sl_status_t sl_btmesh_test_set_model_option(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t option, uint32_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|elem_index||
|uint16_t|N/A|vendor_id||
|uint16_t|N/A|model_id||
|uint8_t|N/A|option||
|uint32_t|N/A|value||

##### sl_btmesh_test_get_local_model_app_bindings

`sl_status_t sl_btmesh_test_get_local_model_app_bindings(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, size_t max_appkeys_size, size_t *appkeys_len, uint8_t *appkeys)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The index of the target element, 0 is the primary element|
|uint16_t|[in]|vendor_id|Vendor ID for vendor-specific models. Use 0xffff for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID|
|size_t|[in]|max_appkeys_size|Size of output buffer passed in `appkeys`|
|size_t *|[out]|appkeys_len|On return, set to the length of output data written to `appkeys`|
|uint8_t *|[out]|appkeys|List of 16-bit application key indices; empty if model has not been bound to any application key.|

Get the application key bindings of a model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_replay_protection_list_entry

`sl_status_t sl_btmesh_test_get_replay_protection_list_entry(uint16_t address, uint32_t *seq, uint32_t *seq_ivindex)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Source address to check|
|uint32_t *|[out]|seq|Stored sequence number for the address; not a valid value if the result is not SL_STATUS_OK.|
|uint32_t *|[out]|seq_ivindex|IV index in use at the time the sequence number was stored in the replay protection list; not a valid value if result is not SL_STATUS_OK.|

Get the replay protection list entry for an address.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_clear_replay_protection_list_entry

`sl_status_t sl_btmesh_test_clear_replay_protection_list_entry(uint16_t address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Source address to use in finding the entry|

Clear the replay protection list entry for an address. Use this command carefully because it may expose the node to replay attacks when misused.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_replay_protection_list_diagnostics

`sl_status_t sl_btmesh_test_set_replay_protection_list_diagnostics(uint8_t enable)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|enable|Enable (nonzero) or disable (zero) diagnostic events for replay protection list|

Enable or disable replay protection list diagnostic events. When enabled, events related to the replay protection list changes are generated.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_model_option

`sl_status_t sl_btmesh_test_get_model_option(uint16_t elem_index, uint16_t vendor_id, uint16_t model_id, uint8_t option, uint32_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|elem_index||
|uint16_t|N/A|vendor_id||
|uint16_t|N/A|model_id||
|uint8_t|N/A|option||
|uint32_t *|N/A|value||

##### sl_btmesh_test_get_default_ttl

`sl_status_t sl_btmesh_test_get_default_ttl(uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|value|Default time-to-live value. Valid value range is from 2 to 127 for relayed PDUs, and 0 to indicate non-relayed PDUs|

Get node default TTL state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_default_ttl

`sl_status_t sl_btmesh_test_set_default_ttl(uint8_t set_value, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|set_value|Default time-to-live value. See [sl_btmesh_test_get_default_ttl](sl-btmesh-test#sl-btmesh-test-get-default-ttl) for details.|
|uint8_t *|[out]|value|Default time-to-live value. See [sl_btmesh_test_get_default_ttl](sl-btmesh-test#sl-btmesh-test-get-default-ttl) for details.|

Set node default TTL state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_gatt_proxy

`sl_status_t sl_btmesh_test_get_gatt_proxy(uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|value|GATT proxy value of the node. Valid values are:<br/><br/>- 0: GATT proxy feature is disabled<br/>- 1: GATT proxy feature is enabled<br/>- 2: GATT proxy feature is not supported|

Get node GATT proxy state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_gatt_proxy

`sl_status_t sl_btmesh_test_set_gatt_proxy(uint8_t set_value, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|set_value|GATT proxy value to set. Valid values are:<br/><br/>- 0: Proxy feature is disabled<br/>- 1: Proxy feature is enabled|
|uint8_t *|[out]|value|GATT proxy state value. See [sl_btmesh_test_get_gatt_proxy](sl-btmesh-test#sl-btmesh-test-get-gatt-proxy) for details.|

Set node GATT proxy state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_gatt_proxy_status](sl-btmesh-evt-config-client-gatt-proxy-status)

##### sl_btmesh_test_get_identity

`sl_status_t sl_btmesh_test_get_identity(uint16_t get_netkey_index, uint16_t *netkey_index, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|get_netkey_index|Network key index for which the state is queried|
|uint16_t *|[out]|netkey_index|Network key index for which the state is queried|
|uint8_t *|[out]|value|Identity state of the node for the used network index. Valid values are as follows:<br/><br/>- 0: Node identity advertising is disabled<br/>- 1: Node identity advertising is enabled<br/>- 2: Node identity advertising is not supported|

Get node identity state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_identity

`sl_status_t sl_btmesh_test_set_identity(uint16_t set_netkey_index, uint8_t set_value, uint16_t *netkey_index, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|set_netkey_index|Network key index for which the state is configured|
|uint8_t|[in]|set_value|Identity value to set. Valid values are:<br/><br/>- 0: Node identity advertising is disabled<br/>- 1: Node identity advertising is enabled|
|uint16_t *|[out]|netkey_index|Network key index for which the state is set|
|uint8_t *|[out]|value|Identity state of the node for the used network index. See [sl_btmesh_test_get_identity](sl-btmesh-test#sl-btmesh-test-get-identity) for details|

Set node identity state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_friend

`sl_status_t sl_btmesh_test_get_friend(uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|value|Friend state value. Valid values are:<br/><br/>- 0: Friend feature is not enabled<br/>- 1: Friend feature is enabled<br/>- 2: Friend feature is not supported|

Get node friend state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_friend

`sl_status_t sl_btmesh_test_set_friend(uint8_t set_value, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|set_value|Friend value to set. Valid values are:<br/><br/>- 0: Friend feature is not enabled<br/>- 1: Friend feature is enabled|
|uint8_t *|[out]|value|Friend state value. See [sl_btmesh_test_get_friend](sl-btmesh-test#sl-btmesh-test-get-friend) for detais.|

Set node friend state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_beacon

`sl_status_t sl_btmesh_test_get_beacon(uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|value|Secure network beacon value. Valid values are:<br/><br/>- 0: Node is not broadcasting secure network beacons<br/>- 1: Node is broadcasting secure network beacons|

Get node secure network beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_beacon

`sl_status_t sl_btmesh_test_set_beacon(uint8_t set_value, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|set_value|Secure network beacon value to set. Valid values are:<br/><br/>- 0: Node is not broadcasting secure network beacons<br/>- 1: Node is broadcasting secure network beacons|
|uint8_t *|[out]|value|Secure network beacon value of the node.|

Set node secure network beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_get_private_identity

`sl_status_t sl_btmesh_test_get_private_identity(uint16_t get_netkey_index, uint16_t *netkey_index, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|get_netkey_index|Network key index for which the state is queried|
|uint16_t *|[out]|netkey_index|Network key index for which the state is queried|
|uint8_t *|[out]|value|Private identity state of the node for the used network index. Valid values are as follows:<br/><br/>- 0: Node private identity advertising is disabled<br/>- 1: Node private identity advertising is enabled<br/>- 2: Node private identity advertising is not supported|

Get node private identity state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_private_identity

`sl_status_t sl_btmesh_test_set_private_identity(uint16_t set_netkey_index, uint8_t set_value, uint16_t *netkey_index, uint8_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|set_netkey_index|Network key index for which the state is configured|
|uint8_t|[in]|set_value|Identity value to set. Valid values are:<br/><br/>- 0: Node private identity advertising is disabled<br/>- 1: Node private identity advertising is enabled|
|uint16_t *|[out]|netkey_index|Network key index for which the state is set|
|uint8_t *|[out]|value|Identity state of the node for the used network index. See [sl_btmesh_test_get_private_identity](sl-btmesh-test#sl-btmesh-test-get-private-identity) for details|

Set node private identity state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_adv_provisioning_bearer_timing

`sl_status_t sl_btmesh_test_set_adv_provisioning_bearer_timing(uint16_t pbadv_interval_ms, uint16_t pbadv_variation_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|pbadv_interval_ms|PB-ADV Tx interval. Value is in milliseconds. Range: 10 to 1000.|
|uint16_t|[in]|pbadv_variation_ms|PB-ADV Tx interval variation. A random delay between 0 and this value is added to the PB-ADV Tx interval when transmitting a PB-ADV PDU. Value is in milliseconds. Range: 10 to 1000.|

Set PB-ADV provisioning bearer timing. This controls how PB-ADV provisioning PDUs are transmitted by the device; each transmission is preceded by a delay that is computed by adding together a minimum interval with a random variation.

If this setting is not applied, a default interval of 20 ms and a default variation of 30 ms is used, meaning that a single advertisement is sent with a delay ranging from 20 to 50 ms.

Note that using a non-default setting is against the Mesh specification and should only used for troubleshooting.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_update_keyrefresh_phase

`sl_status_t sl_btmesh_test_update_keyrefresh_phase(uint16_t network_key_index, uint8_t *phase)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|network_key_index|Index for the key to put into next phase|
|uint8_t *|[out]|phase|Key refresh phase state of the node for the given network key. Valid values are:<br/><br/>- 0: Normal operation<br/>- 1: First phase of key refresh procedure<br/>- 2: Second phase of key refresh procedure|

Change keyrefresh phase of of a network id.

Update is done with following logic depending on current keyrefresh phase:

- Phase 0 : return an errorcode for wrong phase
- Phase 1 : set phase to 2
- Phase 2 : set phase to 3
- Phase 3 : Leave phase 3 as is

This command is for debugging only

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_send_private_beacons

`sl_status_t sl_btmesh_test_send_private_beacons(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Send private network beacons for every network key on the device, regardless of beacon configuration state or how many beacons sent by other devices have been observed.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_adv_params

`sl_status_t sl_btmesh_test_set_adv_params(uint16_t adv_interval_min, uint16_t adv_interval_max, uint8_t adv_repeat_packets, uint8_t adv_channel_map)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|adv_interval_min|Minimum advertisement interval. Value is in units of 0.625 ms. Default value is 32 (20 ms). Must be equal to or greater than 32.|
|uint16_t|[in]|adv_interval_max|Maximum advertisement interval. Value is in units of 0.625 ms. Must be equal to or greater than the minimum interval. Default value is 32 (20 ms). Must be equal to or less than 16384.|
|uint8_t|[in]|adv_repeat_packets|Number of times to repeat each packet on all selected advertisement channels. Range: 1-5. Default value is 1.|
|uint8_t|[in]|adv_channel_map|Advertisement channel selection bitmask. Range: 0x1-0x7. Default value: 7 (all channels)|

Set the non-default advertisement parameters used in mesh communications. Call this command before [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) or [sl_btmesh_prov_init](sl-btmesh-prov#sl-btmesh-prov-init) for the settings to take effect.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_set_scan_params

`sl_status_t sl_btmesh_test_set_scan_params(uint16_t scan_interval, uint16_t scan_window)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|scan_interval|Scan interval. Value is in units of 0.625 ms. Range: 0x0004 to 0x4000 (time range of 2.5 ms to 10.24 s). Default value is 160 (100 ms).|
|uint16_t|[in]|scan_window|Scan window. Value is in units of 0.625 ms. Must be equal to or less than the scan interval.|

Set the non-default scanning parameters used in mesh communications. Call this command before [sl_btmesh_node_init](sl-btmesh-node#sl-btmesh-node-init) or [sl_btmesh_prov_init](sl-btmesh-prov#sl-btmesh-prov-init) for the settings to take effect.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_test_adv_use_random_address

`sl_status_t sl_btmesh_test_adv_use_random_address(uint8_t address_type)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|address_type|Address type:<br/><br/>- **0:** Reset random address usage. Public address will used for advertisements.<br/>- **1:** Set random address usage. New random address will be generated and taken into use.|

Set advertiser to use ramdom or public address. New setting will take effect with the next advertisement.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_test_get_nettx_id 0x00220028`

`#define sl_btmesh_cmd_test_set_nettx_id 0x01220028`

`#define sl_btmesh_cmd_test_get_relay_id 0x02220028`

`#define sl_btmesh_cmd_test_set_relay_id 0x03220028`

`#define sl_btmesh_cmd_test_set_ivupdate_test_mode_id 0x05220028`

`#define sl_btmesh_cmd_test_get_ivupdate_test_mode_id 0x06220028`

`#define sl_btmesh_cmd_test_set_ivupdate_state_id 0x08220028`

`#define sl_btmesh_cmd_test_send_beacons_id 0x09220028`

`#define sl_btmesh_cmd_test_bind_local_model_app_id 0x0a220028`

`#define sl_btmesh_cmd_test_unbind_local_model_app_id 0x0b220028`

`#define sl_btmesh_cmd_test_add_local_model_sub_id 0x0c220028`

`#define sl_btmesh_cmd_test_remove_local_model_sub_id 0x0d220028`

`#define sl_btmesh_cmd_test_add_local_model_sub_va_id 0x0e220028`

`#define sl_btmesh_cmd_test_remove_local_model_sub_va_id 0x0f220028`

`#define sl_btmesh_cmd_test_get_local_model_sub_id 0x10220028`

`#define sl_btmesh_cmd_test_set_local_model_pub_id 0x11220028`

`#define sl_btmesh_cmd_test_set_local_model_pub_va_id 0x12220028`

`#define sl_btmesh_cmd_test_get_local_model_pub_id 0x13220028`

`#define sl_btmesh_cmd_test_set_local_heartbeat_subscription_id 0x14220028`

`#define sl_btmesh_cmd_test_get_local_heartbeat_subscription_id 0x15220028`

`#define sl_btmesh_cmd_test_get_local_heartbeat_publication_id 0x16220028`

`#define sl_btmesh_cmd_test_set_local_heartbeat_publication_id 0x17220028`

`#define sl_btmesh_cmd_test_add_local_key_id 0x1a220028`

`#define sl_btmesh_cmd_test_remove_local_key_id 0x1b220028`

`#define sl_btmesh_cmd_test_update_local_key_id 0x1c220028`

`#define sl_btmesh_cmd_test_set_adv_bearer_state_id 0x1f220028`

`#define sl_btmesh_cmd_test_prov_get_device_key_id 0x23220028`

`#define sl_btmesh_cmd_test_prov_prepare_key_refresh_id 0x24220028`

`#define sl_btmesh_cmd_test_cancel_segmented_tx_id 0x25220028`

`#define sl_btmesh_cmd_test_set_iv_index_id 0x26220028`

`#define sl_btmesh_cmd_test_set_element_seqnum_id 0x27220028`

`#define sl_btmesh_cmd_test_set_model_option_id 0x28220028`

`#define sl_btmesh_cmd_test_get_local_model_app_bindings_id 0x29220028`

`#define sl_btmesh_cmd_test_get_replay_protection_list_entry_id 0x2a220028`

`#define sl_btmesh_cmd_test_clear_replay_protection_list_entry_id 0x2b220028`

`#define sl_btmesh_cmd_test_set_replay_protection_list_diagnostics_id 0x2c220028`

`#define sl_btmesh_cmd_test_get_model_option_id 0x2d220028`

`#define sl_btmesh_cmd_test_get_default_ttl_id 0x2e220028`

`#define sl_btmesh_cmd_test_set_default_ttl_id 0x2f220028`

`#define sl_btmesh_cmd_test_get_gatt_proxy_id 0x30220028`

`#define sl_btmesh_cmd_test_set_gatt_proxy_id 0x31220028`

`#define sl_btmesh_cmd_test_get_identity_id 0x32220028`

`#define sl_btmesh_cmd_test_set_identity_id 0x33220028`

`#define sl_btmesh_cmd_test_get_friend_id 0x34220028`

`#define sl_btmesh_cmd_test_set_friend_id 0x35220028`

`#define sl_btmesh_cmd_test_get_beacon_id 0x36220028`

`#define sl_btmesh_cmd_test_set_beacon_id 0x37220028`

`#define sl_btmesh_cmd_test_get_private_identity_id 0x38220028`

`#define sl_btmesh_cmd_test_set_private_identity_id 0x39220028`

`#define sl_btmesh_cmd_test_set_adv_provisioning_bearer_timing_id 0x3a220028`

`#define sl_btmesh_cmd_test_update_keyrefresh_phase_id 0x3b220028`

`#define sl_btmesh_cmd_test_send_private_beacons_id 0x3c220028`

`#define sl_btmesh_cmd_test_set_adv_params_id 0x3d220028`

`#define sl_btmesh_cmd_test_set_scan_params_id 0x3e220028`

`#define sl_btmesh_cmd_test_adv_use_random_address_id 0x3f220028`

`#define sl_btmesh_rsp_test_get_nettx_id 0x00220028`

`#define sl_btmesh_rsp_test_set_nettx_id 0x01220028`

`#define sl_btmesh_rsp_test_get_relay_id 0x02220028`

`#define sl_btmesh_rsp_test_set_relay_id 0x03220028`

`#define sl_btmesh_rsp_test_set_ivupdate_test_mode_id 0x05220028`

`#define sl_btmesh_rsp_test_get_ivupdate_test_mode_id 0x06220028`

`#define sl_btmesh_rsp_test_set_ivupdate_state_id 0x08220028`

`#define sl_btmesh_rsp_test_send_beacons_id 0x09220028`

`#define sl_btmesh_rsp_test_bind_local_model_app_id 0x0a220028`

`#define sl_btmesh_rsp_test_unbind_local_model_app_id 0x0b220028`

`#define sl_btmesh_rsp_test_add_local_model_sub_id 0x0c220028`

`#define sl_btmesh_rsp_test_remove_local_model_sub_id 0x0d220028`

`#define sl_btmesh_rsp_test_add_local_model_sub_va_id 0x0e220028`

`#define sl_btmesh_rsp_test_remove_local_model_sub_va_id 0x0f220028`

`#define sl_btmesh_rsp_test_get_local_model_sub_id 0x10220028`

`#define sl_btmesh_rsp_test_set_local_model_pub_id 0x11220028`

`#define sl_btmesh_rsp_test_set_local_model_pub_va_id 0x12220028`

`#define sl_btmesh_rsp_test_get_local_model_pub_id 0x13220028`

`#define sl_btmesh_rsp_test_set_local_heartbeat_subscription_id 0x14220028`

`#define sl_btmesh_rsp_test_get_local_heartbeat_subscription_id 0x15220028`

`#define sl_btmesh_rsp_test_get_local_heartbeat_publication_id 0x16220028`

`#define sl_btmesh_rsp_test_set_local_heartbeat_publication_id 0x17220028`

`#define sl_btmesh_rsp_test_add_local_key_id 0x1a220028`

`#define sl_btmesh_rsp_test_remove_local_key_id 0x1b220028`

`#define sl_btmesh_rsp_test_update_local_key_id 0x1c220028`

`#define sl_btmesh_rsp_test_set_adv_bearer_state_id 0x1f220028`

`#define sl_btmesh_rsp_test_prov_get_device_key_id 0x23220028`

`#define sl_btmesh_rsp_test_prov_prepare_key_refresh_id 0x24220028`

`#define sl_btmesh_rsp_test_cancel_segmented_tx_id 0x25220028`

`#define sl_btmesh_rsp_test_set_iv_index_id 0x26220028`

`#define sl_btmesh_rsp_test_set_element_seqnum_id 0x27220028`

`#define sl_btmesh_rsp_test_set_model_option_id 0x28220028`

`#define sl_btmesh_rsp_test_get_local_model_app_bindings_id 0x29220028`

`#define sl_btmesh_rsp_test_get_replay_protection_list_entry_id 0x2a220028`

`#define sl_btmesh_rsp_test_clear_replay_protection_list_entry_id 0x2b220028`

`#define sl_btmesh_rsp_test_set_replay_protection_list_diagnostics_id 0x2c220028`

`#define sl_btmesh_rsp_test_get_model_option_id 0x2d220028`

`#define sl_btmesh_rsp_test_get_default_ttl_id 0x2e220028`

`#define sl_btmesh_rsp_test_set_default_ttl_id 0x2f220028`

`#define sl_btmesh_rsp_test_get_gatt_proxy_id 0x30220028`

`#define sl_btmesh_rsp_test_set_gatt_proxy_id 0x31220028`

`#define sl_btmesh_rsp_test_get_identity_id 0x32220028`

`#define sl_btmesh_rsp_test_set_identity_id 0x33220028`

`#define sl_btmesh_rsp_test_get_friend_id 0x34220028`

`#define sl_btmesh_rsp_test_set_friend_id 0x35220028`

`#define sl_btmesh_rsp_test_get_beacon_id 0x36220028`

`#define sl_btmesh_rsp_test_set_beacon_id 0x37220028`

`#define sl_btmesh_rsp_test_get_private_identity_id 0x38220028`

`#define sl_btmesh_rsp_test_set_private_identity_id 0x39220028`

`#define sl_btmesh_rsp_test_set_adv_provisioning_bearer_timing_id 0x3a220028`

`#define sl_btmesh_rsp_test_update_keyrefresh_phase_id 0x3b220028`

`#define sl_btmesh_rsp_test_send_private_beacons_id 0x3c220028`

`#define sl_btmesh_rsp_test_set_adv_params_id 0x3d220028`

`#define sl_btmesh_rsp_test_set_scan_params_id 0x3e220028`

`#define sl_btmesh_rsp_test_adv_use_random_address_id 0x3f220028`

#### sl_btmesh_evt_test_replay_protection_list_full

Indication that replay protection list is full when trying to process a message. 

##### Macros

`#define sl_btmesh_evt_test_replay_protection_list_full_id 0x042200a8`

**Description**: Identifier of the replay_protection_list_full event.

#### sl_btmesh_evt_test_local_heartbeat_subscription_complete

Indicate that the heartbeat subscription period is over. 

##### Modules

[sl_btmesh_evt_test_local_heartbeat_subscription_complete_s](sl-btmesh-evt-test-local-heartbeat-subscription-complete-s)

##### Typedefs

###### sl_btmesh_evt_test_local_heartbeat_subscription_complete_t

`typedef struct sl_btmesh_evt_test_local_heartbeat_subscription_complete_s sl_btmesh_evt_test_local_heartbeat_subscription_complete_t`

##### Macros

`#define sl_btmesh_evt_test_local_heartbeat_subscription_complete_id 0x002200a8`

**Description**: Identifier of the local_heartbeat_subscription_complete event.

Data structure of the local_heartbeat_subscription_complete event. 

###### Public Attributes

###### count (heading level 7)

```
uint16_t sl_btmesh_evt_test_local_heartbeat_subscription_complete_s::count
```

**Details:** Number of received heartbeat messages

###### hop_min (heading level 7)

```
uint8_t sl_btmesh_evt_test_local_heartbeat_subscription_complete_s::hop_min
```

**Details:** Minimum observed hop count in heartbeat messages

###### hop_max (heading level 7)

```
uint8_t sl_btmesh_evt_test_local_heartbeat_subscription_complete_s::hop_max
```

**Details:** Maximum observed hop count in heartbeat messages

#### sl_btmesh_evt_test_replay_protection_list_entry_set

Indication that a replay protection list entry has been set. 

##### Modules

[sl_btmesh_evt_test_replay_protection_list_entry_set_s](sl-btmesh-evt-test-replay-protection-list-entry-set-s)

##### Typedefs

###### sl_btmesh_evt_test_replay_protection_list_entry_set_t

`typedef struct sl_btmesh_evt_test_replay_protection_list_entry_set_s sl_btmesh_evt_test_replay_protection_list_entry_set_t`

##### Macros

`#define sl_btmesh_evt_test_replay_protection_list_entry_set_id 0x012200a8`

**Description**: Identifier of the replay_protection_list_entry_set event.

Data structure of the replay_protection_list_entry_set event. 

###### Public Attributes

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_test_replay_protection_list_entry_set_s::address
```

**Details:** Source address for the replay protection list entry

###### cancel (heading level 7)

```
uint8_t sl_btmesh_evt_test_replay_protection_list_entry_set_s::cancel
```

**Details:** Nonzero when replay protection list update relates to a cancelled segmented reception

#### sl_btmesh_evt_test_replay_protection_list_entry_cleared

Indication that a replay protection list entry has been cleared. 

##### Modules

[sl_btmesh_evt_test_replay_protection_list_entry_cleared_s](sl-btmesh-evt-test-replay-protection-list-entry-cleared-s)

##### Typedefs

###### sl_btmesh_evt_test_replay_protection_list_entry_cleared_t

`typedef struct sl_btmesh_evt_test_replay_protection_list_entry_cleared_s sl_btmesh_evt_test_replay_protection_list_entry_cleared_t`

##### Macros

`#define sl_btmesh_evt_test_replay_protection_list_entry_cleared_id 0x022200a8`

**Description**: Identifier of the replay_protection_list_entry_cleared event.

Data structure of the replay_protection_list_entry_cleared event. 

###### Public Attributes

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_test_replay_protection_list_entry_cleared_s::address
```

**Details:** Source address for the replay protection list entry

#### sl_btmesh_evt_test_replay_protection_list_saved

Indication that replay protection list has been saved. 

##### Modules

[sl_btmesh_evt_test_replay_protection_list_saved_s](sl-btmesh-evt-test-replay-protection-list-saved-s)

##### Typedefs

###### sl_btmesh_evt_test_replay_protection_list_saved_t

`typedef struct sl_btmesh_evt_test_replay_protection_list_saved_s sl_btmesh_evt_test_replay_protection_list_saved_t`

##### Macros

`#define sl_btmesh_evt_test_replay_protection_list_saved_id 0x032200a8`

**Description**: Identifier of the replay_protection_list_saved event.

Data structure of the replay_protection_list_saved event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_test_replay_protection_list_saved_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### saved_count (heading level 7)

```
uint16_t sl_btmesh_evt_test_replay_protection_list_saved_s::saved_count
```

**Details:** Number of entries saved successfully

###### total_count (heading level 7)

```
uint16_t sl_btmesh_evt_test_replay_protection_list_saved_s::total_count
```

**Details:** Number of entries in the list in total

### Bluetooth Mesh Low Power Node API

Bluetooth Mesh Low Power Node API. 

These commands and events are for low-power operation, available in nodes which have the LPN feature. 

#### Modules

[sl_btmesh_evt_lpn_friendship_established](sl-btmesh-evt-lpn-friendship-established)

[sl_btmesh_evt_lpn_friendship_failed](sl-btmesh-evt-lpn-friendship-failed)

[sl_btmesh_evt_lpn_friendship_terminated](sl-btmesh-evt-lpn-friendship-terminated)

#### Enumerations

##### sl_btmesh_lpn_settings_t

```
enum sl_btmesh_lpn_settings_t {
    sl_btmesh_lpn_queue_length = 0x0
    sl_btmesh_lpn_poll_timeout = 0x1
    sl_btmesh_lpn_receive_delay = 0x2
    sl_btmesh_lpn_request_retries = 0x3
    sl_btmesh_lpn_retry_interval = 0x4
    sl_btmesh_lpn_clock_accuracy = 0x5
    sl_btmesh_lpn_max_receive_window = 0x6
    sl_btmesh_lpn_min_subscription_list_size = 0x7
    sl_btmesh_lpn_min_friend_offer_rssi = 0x8
    sl_btmesh_lpn_receive_window_factor = 0x9
    sl_btmesh_lpn_rssi_factor = 0xa
    sl_btmesh_lpn_friend_offer_listen_timeout_slack = 0xb
}
```

**Description:**

Key values to identify LPN configurations.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_lpn_queue_length|(0x0) Minimum queue length that the friend must support. Choose an appropriate length based on the expected message frequency and LPN sleep period because messages that do not fit into the friend queue are dropped. Note that the given value is rounded up to the nearest power of

1. Range: 2..128|
|sl_btmesh_lpn_poll_timeout|(0x1) Poll timeout in milliseconds, which is the longest time that LPN sleeps in between querying its friend for queued messages. Long poll timeout allows the LPN to sleep for longer periods, at the expense of increased latency for receiving messages. Note that the given value is rounded up to the nearest 100 ms Range: 1 s to 95 h 59 min 59 s 900 ms|
|sl_btmesh_lpn_receive_delay|(0x2) Receive delay in milliseconds. Receive delay is the time between the LPN sending a request and listening for a response. Receive delay allows the friend node time to prepare the message and LPN to sleep. Range: 10 ms to 255 ms The default receive delay in 10 ms.|
|sl_btmesh_lpn_request_retries|(0x3) Request retry is the number of retry attempts to repeat e.g., the friend poll message if the friend update was not received by the LPN. Range is from 0 to 239, default is 5|
|sl_btmesh_lpn_retry_interval|(0x4) Time interval between retry attempts in milliseconds. Range is 0 to 60000 ms (1 minute), default is 100 ms.|
|sl_btmesh_lpn_clock_accuracy|(0x5) Clock accuracy in ppm, which will be taken into account when opening and closing the receive window, and determining the poll timeout. Should be used with care, because inaccurate clock can increase the receive window lenght to up to 2,5 times in some cases. Default value is 0.|
|sl_btmesh_lpn_max_receive_window|(0x6) Maximum acceptable friend receive window in milliseconds. Friend offers with a larger receive window will be rejected. This configuration also limits how long the LPN waits for friend offers, because friends with large receive windows will delay their friend offer messages longer. Range: 1 ms to 255 ms. Default is 255 ms.|
|sl_btmesh_lpn_min_subscription_list_size|(0x7) Minimum subscription list size that the friend must support. Friend offers with a smaller subscription list size will be rejected. Range: 0..255 Default is 0.|
|sl_btmesh_lpn_min_friend_offer_rssi|(0x8) Minimum acceptable RSSI value in dBm reported by friend offer messages. This configuration also limits how long the LPN waits for friend offers, because friends with low RSSI values will delay their friend offer messages longer. Note that in practice the RSSI value is a negative number, and values larger than -20 dBm are not frequently observed in real life scenarios. The friend may also report that it does not support RSSI reporting, in which case an empty RSSI value is also accepted. The value is interpreted as a two's complement 8-bit signed integer, even though the type of the parameter is uint32. The most significant 24 bits of the uint32 value are ignored, so it does not matter whether the value -55 is given as 0x000000c9 or 0xffffffc9, as an example. Range: -128..127. Default is -128.|
|sl_btmesh_lpn_receive_window_factor|(0x9) Value for ReceiveWindowFactor. This informs the friend how much it should delay sending its friend offer message based on its receive window capability. The factor value is 1

- 0.5 * receive_window_factor. Range: 0..3. Default is 0 (factor of 1).|
|sl_btmesh_lpn_rssi_factor|(0xa) Value for RSSIFactor. This informs the friend how much it should delay sending its friend offer message based on its measured RSSI of the friend request. The factor value is 1

- 0.5 * rssi_factor. Range: 0..3. Default is 0 (factor of 1).|
|sl_btmesh_lpn_friend_offer_listen_timeout_slack|(0xb) Amount of time in milliseconds to listen for friend offers after their expected arrival time based on the maximum receive window and minimum RSSI and their respective factors. Since the advertisement message timings are generally not exact, some slack should be allowed to avoid missing valid friend offers. If the calculated time plus slack exceeds 1000 ms, then the time is clamped to 1000 ms. Range: 1..1000 ms. Default is 20 ms.|

#### Functions

##### sl_btmesh_lpn_init

`sl_status_t sl_btmesh_lpn_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the Low Power node (LPN) mode. The node needs to be provisioned before calling this command. After the LPN mode is initialized, the node can't operate in the network without a Friend node. To establish a friendship with a nearby Friend node, use the [sl_btmesh_lpn_establish_friendship](sl-btmesh-lpn#sl-btmesh-lpn-establish-friendship) command. Make this call before calling the other commands in this class.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lpn_deinit

`sl_status_t sl_btmesh_lpn_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the LPN functionality. After calling this command, a possible friendship with a Friend node is terminated and the node can operate in the network independently. After calling this command, do not call any other command in this class before the Low Power mode is [sl_btmesh_lpn_init](sl-btmesh-lpn#sl-btmesh-lpn-init) again.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lpn_establish_friendship

`sl_status_t sl_btmesh_lpn_establish_friendship(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key index used in friendship request|

Establish a friendship. After a friendship has been established, the node can start saving power.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lpn_friendship_established](sl-btmesh-evt-lpn-friendship-established)
- [sl_btmesh_evt_lpn_friendship_failed](sl-btmesh-evt-lpn-friendship-failed)

##### sl_btmesh_lpn_poll

`sl_status_t sl_btmesh_lpn_poll(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key index used in poll|

Poll the Friend node for stored messages and security updates. This command may be used if the application is expecting to receive messages at a specific time. However, it is not required for correct operation, because the procedure will be performed autonomously before the poll timeout expires.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lpn_terminate_friendship

`sl_status_t sl_btmesh_lpn_terminate_friendship(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key index used in friendship request|

Terminate an already established friendship. [sl_btmesh_evt_lpn_friendship_terminated](sl-btmesh-evt-lpn-friendship-terminated) event will be emitted when the friendship termination has been completed.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lpn_friendship_terminated](sl-btmesh-evt-lpn-friendship-terminated)

##### sl_btmesh_lpn_config

`sl_status_t sl_btmesh_lpn_config(uint8_t setting_id, uint32_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|setting_id|Enum [sl_btmesh_lpn_settings_t](sl-btmesh-lpn#sl-btmesh-lpn-settings-t). Identifies the LPN setting to be updated.|
|uint32_t|[in]|value|New value for the given setting|

Configure the parameters for friendship establishment and LPN behavior.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_lpn_init_id 0x00230028`

`#define sl_btmesh_cmd_lpn_deinit_id 0x01230028`

`#define sl_btmesh_cmd_lpn_establish_friendship_id 0x03230028`

`#define sl_btmesh_cmd_lpn_poll_id 0x04230028`

`#define sl_btmesh_cmd_lpn_terminate_friendship_id 0x05230028`

`#define sl_btmesh_cmd_lpn_config_id 0x06230028`

`#define sl_btmesh_rsp_lpn_init_id 0x00230028`

`#define sl_btmesh_rsp_lpn_deinit_id 0x01230028`

`#define sl_btmesh_rsp_lpn_establish_friendship_id 0x03230028`

`#define sl_btmesh_rsp_lpn_poll_id 0x04230028`

`#define sl_btmesh_rsp_lpn_terminate_friendship_id 0x05230028`

`#define sl_btmesh_rsp_lpn_config_id 0x06230028`

#### sl_btmesh_evt_lpn_friendship_established

Indicate that a friendship has been established, received as a response to the [sl_btmesh_lpn_establish_friendship](sl-btmesh-lpn#sl-btmesh-lpn-establish-friendship) command. 

##### Modules

[sl_btmesh_evt_lpn_friendship_established_s](sl-btmesh-evt-lpn-friendship-established-s)

##### Typedefs

###### sl_btmesh_evt_lpn_friendship_established_t

`typedef struct sl_btmesh_evt_lpn_friendship_established_s sl_btmesh_evt_lpn_friendship_established_t`

##### Macros

`#define sl_btmesh_evt_lpn_friendship_established_id 0x002300a8`

**Description**: Identifier of the friendship_established event.

Data structure of the friendship_established event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lpn_friendship_established_s::netkey_index
```

**Details:** Network key index

###### friend_address (heading level 7)

```
uint16_t sl_btmesh_evt_lpn_friendship_established_s::friend_address
```

**Details:** Friend node address

#### sl_btmesh_evt_lpn_friendship_failed

Indicate that the friendship establishment has failed, received as a response to the [sl_btmesh_lpn_establish_friendship](sl-btmesh-lpn#sl-btmesh-lpn-establish-friendship) command. 

##### Modules

[sl_btmesh_evt_lpn_friendship_failed_s](sl-btmesh-evt-lpn-friendship-failed-s)

##### Typedefs

###### sl_btmesh_evt_lpn_friendship_failed_t

`typedef struct sl_btmesh_evt_lpn_friendship_failed_s sl_btmesh_evt_lpn_friendship_failed_t`

##### Macros

`#define sl_btmesh_evt_lpn_friendship_failed_id 0x012300a8`

**Description**: Identifier of the friendship_failed event.

Data structure of the friendship_failed event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lpn_friendship_failed_s::netkey_index
```

**Details:** Network key index

###### reason (heading level 7)

```
uint16_t sl_btmesh_evt_lpn_friendship_failed_s::reason
```

**Details:** Reason for friendship establishment failure

#### sl_btmesh_evt_lpn_friendship_terminated

Indicate that a friendship that was successfully established has been terminated, received as a response to the [sl_btmesh_lpn_terminate_friendship](sl-btmesh-lpn#sl-btmesh-lpn-terminate-friendship) command or when friend not answering to a POLL send by [sl_btmesh_lpn_poll](sl-btmesh-lpn#sl-btmesh-lpn-poll) command. 

##### Modules

[sl_btmesh_evt_lpn_friendship_terminated_s](sl-btmesh-evt-lpn-friendship-terminated-s)

##### Typedefs

###### sl_btmesh_evt_lpn_friendship_terminated_t

`typedef struct sl_btmesh_evt_lpn_friendship_terminated_s sl_btmesh_evt_lpn_friendship_terminated_t`

##### Macros

`#define sl_btmesh_evt_lpn_friendship_terminated_id 0x022300a8`

**Description**: Identifier of the friendship_terminated event.

Data structure of the friendship_terminated event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lpn_friendship_terminated_s::netkey_index
```

**Details:** Network key index

###### reason (heading level 7)

```
uint16_t sl_btmesh_evt_lpn_friendship_terminated_s::reason
```

**Details:** Reason for friendship termination

### Bluetooth Mesh Friend Node API

Bluetooth Mesh Friend Node API. 

These commands and events are for the Friend operation, available in nodes which have the Friend feature. 

#### Modules

[sl_btmesh_evt_friend_friendship_established](sl-btmesh-evt-friend-friendship-established)

[sl_btmesh_evt_friend_friendship_terminated](sl-btmesh-evt-friend-friendship-terminated)

#### Functions

##### sl_btmesh_friend_init

`sl_status_t sl_btmesh_friend_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the Friend mode. The node needs to be provisioned before calling this command. After the Friend mode is initialized, it is ready to accept friend requests from low-power nodes. This call has to be made before calling the other commands in this class.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_friend_deinit

`sl_status_t sl_btmesh_friend_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the Friend functionality. After calling this command, a possible friendship with a Low Power node is terminated and all friendships are terminated. After calling this command, don't call other commands in this class before the Friend mode is [sl_btmesh_friend_init](sl-btmesh-friend#sl-btmesh-friend-init) again.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_friend_init_id 0x00240028`

`#define sl_btmesh_cmd_friend_deinit_id 0x01240028`

`#define sl_btmesh_rsp_friend_init_id 0x00240028`

`#define sl_btmesh_rsp_friend_deinit_id 0x01240028`

#### sl_btmesh_evt_friend_friendship_established

Indicate that a friendship has been established. 

##### Modules

[sl_btmesh_evt_friend_friendship_established_s](sl-btmesh-evt-friend-friendship-established-s)

##### Typedefs

###### sl_btmesh_evt_friend_friendship_established_t

`typedef struct sl_btmesh_evt_friend_friendship_established_s sl_btmesh_evt_friend_friendship_established_t`

##### Macros

`#define sl_btmesh_evt_friend_friendship_established_id 0x002400a8`

**Description**: Identifier of the friendship_established event.

Data structure of the friendship_established event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_friend_friendship_established_s::netkey_index
```

**Details:** Index of the network key used in friendship

###### lpn_address (heading level 7)

```
uint16_t sl_btmesh_evt_friend_friendship_established_s::lpn_address
```

**Details:** LPN node address

#### sl_btmesh_evt_friend_friendship_terminated

Indicate that a friendship that was successfully established has been terminated. 

##### Modules

[sl_btmesh_evt_friend_friendship_terminated_s](sl-btmesh-evt-friend-friendship-terminated-s)

##### Typedefs

###### sl_btmesh_evt_friend_friendship_terminated_t

`typedef struct sl_btmesh_evt_friend_friendship_terminated_s sl_btmesh_evt_friend_friendship_terminated_t`

##### Macros

`#define sl_btmesh_evt_friend_friendship_terminated_id 0x012400a8`

**Description**: Identifier of the friendship_terminated event.

Data structure of the friendship_terminated event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_friend_friendship_terminated_s::netkey_index
```

**Details:** Index of the network key used in friendship

###### lpn_address (heading level 7)

```
uint16_t sl_btmesh_evt_friend_friendship_terminated_s::lpn_address
```

**Details:** LPN node address

###### reason (heading level 7)

```
uint16_t sl_btmesh_evt_friend_friendship_terminated_s::reason
```

**Details:** Reason for friendship termination

### Bluetooth Mesh Configuration Client Model

Bluetooth Mesh Configuration Client Model. 

Bluetooth mesh stack API for the Mesh Configuration Client

Commands in this class configure nodes in the Mesh network, which includes key management, publish and subscribe settings manipulation, and node feature configuration.

Requests to nodes are asynchronous. A handle is assigned to each request that is pending a reply from a node in the network. The handle can be used to query the request status, and to identify the response event from the node. Multiple requests can be made in parallel (as long as they are destined to different nodes; only one pending request per node is allowed).

**Request Management**

- [sl_btmesh_config_client_cancel_request](sl-btmesh-config-client#sl-btmesh-config-client-cancel-request) : Cancel a request
- [sl_btmesh_config_client_get_request_status](sl-btmesh-config-client#sl-btmesh-config-client-get-request-status) : Query current status of a request
- [sl_btmesh_config_client_get_default_timeout](sl-btmesh-config-client#sl-btmesh-config-client-get-default-timeout) : Get default request timeout
- [sl_btmesh_config_client_set_default_timeout](sl-btmesh-config-client#sl-btmesh-config-client-set-default-timeout) : Set default request timeout

**Key and Mesh Network Management**

- [sl_btmesh_config_client_add_netkey](sl-btmesh-config-client#sl-btmesh-config-client-add-netkey) : Deploy a network key to a node
- [sl_btmesh_config_client_remove_netkey](sl-btmesh-config-client#sl-btmesh-config-client-remove-netkey) : Remove a network key from a node
- [sl_btmesh_config_client_list_netkeys](sl-btmesh-config-client#sl-btmesh-config-client-list-netkeys) : List network keys on a node
- [sl_btmesh_config_client_add_appkey](sl-btmesh-config-client#sl-btmesh-config-client-add-appkey) : Deploy an application key to a node
- [sl_btmesh_config_client_remove_appkey](sl-btmesh-config-client#sl-btmesh-config-client-remove-appkey) : Remove an application key from a node
- [sl_btmesh_config_client_list_appkeys](sl-btmesh-config-client#sl-btmesh-config-client-list-appkeys) : List application keys bound to a network key on a node

**Node Configuration**

- [sl_btmesh_config_client_get_dcd](sl-btmesh-config-client#sl-btmesh-config-client-get-dcd) : Get device composition data of a node
- [sl_btmesh_config_client_reset_node](sl-btmesh-config-client#sl-btmesh-config-client-reset-node) : Reset a node
- [sl_btmesh_config_client_get_default_ttl](sl-btmesh-config-client#sl-btmesh-config-client-get-default-ttl) : Get node default TTL state value
- [sl_btmesh_config_client_set_default_ttl](sl-btmesh-config-client#sl-btmesh-config-client-set-default-ttl) : Set node default TTL state value
- [sl_btmesh_config_client_get_beacon](sl-btmesh-config-client#sl-btmesh-config-client-get-beacon) : Get node secure network beacon state value
- [sl_btmesh_config_client_set_beacon](sl-btmesh-config-client#sl-btmesh-config-client-set-beacon) : Set node secure network beacon state value
- [sl_btmesh_config_client_get_identity](sl-btmesh-config-client#sl-btmesh-config-client-get-identity) : Get node identity advertising state value
- [sl_btmesh_config_client_set_identity](sl-btmesh-config-client#sl-btmesh-config-client-set-identity) : Set node identity advertising state value
- [sl_btmesh_config_client_get_friend](sl-btmesh-config-client#sl-btmesh-config-client-get-friend) : Get node friend state value
- [sl_btmesh_config_client_set_friend](sl-btmesh-config-client#sl-btmesh-config-client-set-friend) : Set node friend state value
- [sl_btmesh_config_client_get_lpn_polltimeout](sl-btmesh-config-client#sl-btmesh-config-client-get-lpn-polltimeout) : Get node LPN poll timeout state value
- [sl_btmesh_config_client_get_gatt_proxy](sl-btmesh-config-client#sl-btmesh-config-client-get-gatt-proxy) : Get node GATT proxy state value
- [sl_btmesh_config_client_set_gatt_proxy](sl-btmesh-config-client#sl-btmesh-config-client-set-gatt-proxy) : Set node GATT proxy state value
- [sl_btmesh_config_client_get_relay](sl-btmesh-config-client#sl-btmesh-config-client-get-relay) : Get node relay state value
- [sl_btmesh_config_client_set_relay](sl-btmesh-config-client#sl-btmesh-config-client-set-relay) : Set node relay state value
- [sl_btmesh_config_client_get_network_transmit](sl-btmesh-config-client#sl-btmesh-config-client-get-network-transmit) : Get node network transmit state value
- [sl_btmesh_config_client_set_network_transmit](sl-btmesh-config-client#sl-btmesh-config-client-set-network-transmit) : Set node network transmit state value

**Model Configuration**

- [sl_btmesh_config_client_bind_model](sl-btmesh-config-client#sl-btmesh-config-client-bind-model) : Bind a model to an application key
- [sl_btmesh_config_client_unbind_model](sl-btmesh-config-client#sl-btmesh-config-client-unbind-model) : Remove a model to application key binding
- [sl_btmesh_config_client_list_bindings](sl-btmesh-config-client#sl-btmesh-config-client-list-bindings) : List model to application key bindings on a node
- [sl_btmesh_config_client_add_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-add-model-sub) : Add a subscription address to a model
- [sl_btmesh_config_client_add_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-add-model-sub-va) : Add a virtual subscription address to a model
- [sl_btmesh_config_client_remove_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-remove-model-sub) : Remove a subscription address from a model
- [sl_btmesh_config_client_remove_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-remove-model-sub-va) : Remove a virtual subscription address from a model
- [sl_btmesh_config_client_set_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-set-model-sub) : Overwrite the subscription list of a model with an address
- [sl_btmesh_config_client_set_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-set-model-sub-va) : Overwrite the subscription list of a model with a virtual address
- [sl_btmesh_config_client_clear_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-clear-model-sub) : Clear the subscription list of a model
- [sl_btmesh_config_client_list_subs](sl-btmesh-config-client#sl-btmesh-config-client-list-subs) : Get the subscription list of a model
- [sl_btmesh_config_client_get_model_pub](sl-btmesh-config-client#sl-btmesh-config-client-get-model-pub) : Get a model's publication parameters
- [sl_btmesh_config_client_set_model_pub](sl-btmesh-config-client#sl-btmesh-config-client-set-model-pub) : Set a model's publication parameters

**Heartbeat**

- [sl_btmesh_config_client_get_heartbeat_pub](sl-btmesh-config-client#sl-btmesh-config-client-get-heartbeat-pub) : Get node heartbeat publication settings
- [sl_btmesh_config_client_set_heartbeat_pub](sl-btmesh-config-client#sl-btmesh-config-client-set-heartbeat-pub) : Set node heartbeat publication settings
- [sl_btmesh_config_client_get_heartbeat_sub](sl-btmesh-config-client#sl-btmesh-config-client-get-heartbeat-sub) : Get node heartbeat subscription settings
- [sl_btmesh_config_client_set_heartbeat_sub](sl-btmesh-config-client#sl-btmesh-config-client-set-heartbeat-sub) : Set node heartbeat subscription settings

#### Modules

[sl_btmesh_evt_config_client_request_modified](sl-btmesh-evt-config-client-request-modified)

[sl_btmesh_evt_config_client_netkey_status](sl-btmesh-evt-config-client-netkey-status)

[sl_btmesh_evt_config_client_netkey_list](sl-btmesh-evt-config-client-netkey-list)

[sl_btmesh_evt_config_client_netkey_list_end](sl-btmesh-evt-config-client-netkey-list-end)

[sl_btmesh_evt_config_client_appkey_status](sl-btmesh-evt-config-client-appkey-status)

[sl_btmesh_evt_config_client_appkey_list](sl-btmesh-evt-config-client-appkey-list)

[sl_btmesh_evt_config_client_appkey_list_end](sl-btmesh-evt-config-client-appkey-list-end)

[sl_btmesh_evt_config_client_binding_status](sl-btmesh-evt-config-client-binding-status)

[sl_btmesh_evt_config_client_bindings_list](sl-btmesh-evt-config-client-bindings-list)

[sl_btmesh_evt_config_client_bindings_list_end](sl-btmesh-evt-config-client-bindings-list-end)

[sl_btmesh_evt_config_client_model_pub_status](sl-btmesh-evt-config-client-model-pub-status)

[sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

[sl_btmesh_evt_config_client_subs_list](sl-btmesh-evt-config-client-subs-list)

[sl_btmesh_evt_config_client_subs_list_end](sl-btmesh-evt-config-client-subs-list-end)

[sl_btmesh_evt_config_client_heartbeat_pub_status](sl-btmesh-evt-config-client-heartbeat-pub-status)

[sl_btmesh_evt_config_client_heartbeat_sub_status](sl-btmesh-evt-config-client-heartbeat-sub-status)

[sl_btmesh_evt_config_client_beacon_status](sl-btmesh-evt-config-client-beacon-status)

[sl_btmesh_evt_config_client_default_ttl_status](sl-btmesh-evt-config-client-default-ttl-status)

[sl_btmesh_evt_config_client_gatt_proxy_status](sl-btmesh-evt-config-client-gatt-proxy-status)

[sl_btmesh_evt_config_client_relay_status](sl-btmesh-evt-config-client-relay-status)

[sl_btmesh_evt_config_client_network_transmit_status](sl-btmesh-evt-config-client-network-transmit-status)

[sl_btmesh_evt_config_client_identity_status](sl-btmesh-evt-config-client-identity-status)

[sl_btmesh_evt_config_client_friend_status](sl-btmesh-evt-config-client-friend-status)

[sl_btmesh_evt_config_client_key_refresh_phase_status](sl-btmesh-evt-config-client-key-refresh-phase-status)

[sl_btmesh_evt_config_client_lpn_polltimeout_status](sl-btmesh-evt-config-client-lpn-polltimeout-status)

[sl_btmesh_evt_config_client_dcd_data](sl-btmesh-evt-config-client-dcd-data)

[sl_btmesh_evt_config_client_dcd_data_end](sl-btmesh-evt-config-client-dcd-data-end)

[sl_btmesh_evt_config_client_reset_status](sl-btmesh-evt-config-client-reset-status)

[sl_btmesh_evt_config_client_obo_ack_received](sl-btmesh-evt-config-client-obo-ack-received)

#### Functions

##### sl_btmesh_config_client_cancel_request

`sl_status_t sl_btmesh_config_client_cancel_request(uint32_t handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|handle|Request handle|

Cancel an ongoing request releasing resources allocated at the Configuration Client. Note that this call does no undo any setting a node may have made if it had received the request already.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_config_client_get_request_status

`sl_status_t sl_btmesh_config_client_get_request_status(uint32_t handle, uint16_t *server_address, uint16_t *opcode, uint32_t *age_ms, uint32_t *remaining_ms, uint8_t *friend_acked)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|handle|Request handle|
|uint16_t *|[out]|server_address|Address of the Configuration Server|
|uint16_t *|[out]|opcode|Message opcode used in the request. Opcodes are defined in the Bluetooth mesh stack 1.0 specification.|
|uint32_t *|[out]|age_ms|Time in milliseconds that the request has been pending|
|uint32_t *|[out]|remaining_ms|Time in milliseconds before the request times out. Note that timeout may be adjusted if it's determined that the request is destined to an LPN, which may respond very slowly.|
|uint8_t *|[out]|friend_acked|If non-zero, response has been acknowledged by a Friend node, so it is destined to an LPN and may take a long time to complete.|

Get the status of a pending request.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_config_client_get_default_timeout

`sl_status_t sl_btmesh_config_client_get_default_timeout(uint32_t *timeout_ms, uint32_t *lpn_timeout_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *|[out]|timeout_ms|Timeout in milliseconds. Default timeout is 5 s (5000 ms).|
|uint32_t *|[out]|lpn_timeout_ms|Timeout in milliseconds when communicating with an LPN node. Default LPN timeout is 120 s (120000 ms).|

Get the default timeout for the configuration client requests. If there is no response when the timeout expires, a configuration request is considered to have failed and an event with an error result will be generated. Note that, if the Bluetooth mesh stack notices the request is destined to an LPN by receiving an on-behalf-of acknowledgment from a Friend node, the timeout in use will be changed to the LPN default timeout.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_config_client_set_default_timeout

`sl_status_t sl_btmesh_config_client_set_default_timeout(uint32_t timeout_ms, uint32_t lpn_timeout_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|timeout_ms|Timeout in milliseconds. Default timeout is 5 s (5000 ms).|
|uint32_t|[in]|lpn_timeout_ms|Timeout in milliseconds when communicating with an LPN node. Default LPN timeout is 120 s (120000 ms).|

Set the default timeout for the configuration client requests.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_config_client_add_netkey

`sl_status_t sl_btmesh_config_client_add_netkey(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Index of the network key to add|
|uint32_t *|[out]|handle|Request handle|

Add a network key to a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_netkey_status](sl-btmesh-evt-config-client-netkey-status)

##### sl_btmesh_config_client_remove_netkey

`sl_status_t sl_btmesh_config_client_remove_netkey(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Index of the network key to remove|
|uint32_t *|[out]|handle|Request handle|

Remove a network key from a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_netkey_status](sl-btmesh-evt-config-client-netkey-status)

##### sl_btmesh_config_client_list_netkeys

`sl_status_t sl_btmesh_config_client_list_netkeys(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

List the network keys on a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_netkey_list](sl-btmesh-evt-config-client-netkey-list)
- [sl_btmesh_evt_config_client_netkey_list_end](sl-btmesh-evt-config-client-netkey-list-end)

##### sl_btmesh_config_client_add_appkey

`sl_status_t sl_btmesh_config_client_add_appkey(uint16_t enc_netkey_index, uint16_t server_address, uint16_t appkey_index, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|appkey_index|Index of the application key to add|
|uint16_t|[in]|netkey_index|Index of the network key to bind the application key to on the node. Note that this may be different from the binding on other nodes or on the Configuration Client if desired.|
|uint32_t *|[out]|handle|Request handle|

Add an application key to a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_appkey_status](sl-btmesh-evt-config-client-appkey-status)

##### sl_btmesh_config_client_remove_appkey

`sl_status_t sl_btmesh_config_client_remove_appkey(uint16_t enc_netkey_index, uint16_t server_address, uint16_t appkey_index, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|appkey_index|Index of the application key to remove|
|uint16_t|[in]|netkey_index|Index of the network key bound to the application key to on the node. Note that this may be different from the binding on other nodes or on the Configuration Client.|
|uint32_t *|[out]|handle|Request handle|

Remove an application key from a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_appkey_status](sl-btmesh-evt-config-client-appkey-status)

##### sl_btmesh_config_client_list_appkeys

`sl_status_t sl_btmesh_config_client_list_appkeys(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Network key index for the key used as the query parameter. The result contains the indices of the application keys bound to this network key on the node.|
|uint32_t *|[out]|handle|Request handle|

List the application keys on a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_appkey_list](sl-btmesh-evt-config-client-appkey-list)
- [sl_btmesh_evt_config_client_appkey_list_end](sl-btmesh-evt-config-client-appkey-list-end)

##### sl_btmesh_config_client_bind_model

`sl_status_t sl_btmesh_config_client_bind_model(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t appkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint16_t|[in]|appkey_index|Index of the application key to bind to the model|
|uint32_t *|[out]|handle|Request handle|

Bind an application key to a model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_binding_status](sl-btmesh-evt-config-client-binding-status)

##### sl_btmesh_config_client_unbind_model

`sl_status_t sl_btmesh_config_client_unbind_model(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t appkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint16_t|[in]|appkey_index|Index of the application key to unbind from the model|
|uint32_t *|[out]|handle|Request handle|

Unbind an application key from a model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_binding_status](sl-btmesh-evt-config-client-binding-status)

##### sl_btmesh_config_client_list_bindings

`sl_status_t sl_btmesh_config_client_list_bindings(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be queried resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to query. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to query|
|uint32_t *|[out]|handle|Request handle|

List application key bindings of a model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_bindings_list](sl-btmesh-evt-config-client-bindings-list)
- [sl_btmesh_evt_config_client_bindings_list_end](sl-btmesh-evt-config-client-bindings-list-end)

##### sl_btmesh_config_client_get_model_pub

`sl_status_t sl_btmesh_config_client_get_model_pub(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be queried resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to query. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to query|
|uint32_t *|[out]|handle|Request handle|

Get the model publication state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_pub_status](sl-btmesh-evt-config-client-model-pub-status)

##### sl_btmesh_config_client_set_model_pub

`sl_status_t sl_btmesh_config_client_set_model_pub(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t address, uint16_t appkey_index, uint8_t credentials, uint8_t ttl, uint32_t period_ms, uint8_t retransmit_count, uint16_t retransmit_interval_ms, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint16_t|[in]|address|The address to publish to. It can be a unicast address, a virtual address, or a group address. It can also be the unassigned address to stop the model from publishing.|
|uint16_t|[in]|appkey_index|The application key index to use for the published messages.|
|uint8_t|[in]|credentials|Friendship credential flag. If zero, publication is done using normal credentials. If one, it is done with friendship credentials, meaning only the friend can decrypt the published message and relay it forward using the normal credentials. The default value is 0.|
|uint8_t|[in]|ttl|Publication time-to-live value. Valid values: range[0 - 127] and 255.|
|uint32_t|[in]|period_ms|Publication period in milliseconds. Note that the resolution of the publication period is limited by the specification to 100 ms up to a period of 6.3 s, 1 s up to a period of 63 s, 10 s up to a period of 630 s, and 10 minutes above that. Maximum period allowed is 630 minutes.|
|uint8_t|[in]|retransmit_count|Publication retransmission count. Valid values range from 0 to 7.|
|uint16_t|[in]|retransmit_interval_ms|Publication retransmission interval in millisecond units. The range of value is 50 to 1600 ms, and the resolution of the value is 50 milliseconds.|
|uint32_t *|[out]|handle|Request handle|

Set the model publication state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_pub_status](sl-btmesh-evt-config-client-model-pub-status)

##### sl_btmesh_config_client_set_model_pub_va

`sl_status_t sl_btmesh_config_client_set_model_pub_va(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uuid_128 address, uint16_t appkey_index, uint8_t credentials, uint8_t ttl, uint32_t period_ms, uint8_t retransmit_count, uint16_t retransmit_interval_ms, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|[uuid_128](uuid-128)|[in]|address|The Label UUID (full virtual address) to publish to|
|uint16_t|[in]|appkey_index|The application key index to use for the published messages|
|uint8_t|[in]|credentials|Friendship credential flag. If zero, publication is done using normal credentials. If one, it is done with friendship credentials, meaning only the friend can decrypt the published message and relay it forward using the normal credentials. The default value is 0.|
|uint8_t|[in]|ttl|Publication time-to-live value. Valid values: range[0 - 127] and 255.|
|uint32_t|[in]|period_ms|Publication period in milliseconds. Note that the resolution of the publication period is limited by the specification to 100 ms up to a period of 6.3 s, 1 s up to a period of 63 s, 10 s up to a period of 630 s, and 10 minutes above that. Maximum period allowed is 630 minutes.|
|uint8_t|[in]|retransmit_count|Publication retransmission count. Valid values range from 0 to 7.|
|uint16_t|[in]|retransmit_interval_ms|Publication retransmission interval in millisecond units. The range of value is 50 to 1600 ms. The resolution of the value is 50 milliseconds.|
|uint32_t *|[out]|handle|Request handle|

Set the model publication state with a full virtual publication address.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_pub_status](sl-btmesh-evt-config-client-model-pub-status)

##### sl_btmesh_config_client_add_model_sub

`sl_status_t sl_btmesh_config_client_add_model_sub(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint16_t|[in]|sub_address|The address to add to the subscription list. Note that the address has to be a group address.|
|uint32_t *|[out]|handle|Request handle|

Add an address to the model subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_add_model_sub_va

`sl_status_t sl_btmesh_config_client_add_model_sub_va(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uuid_128 sub_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|[uuid_128](uuid-128)|[in]|sub_address|The full virtual address to add to the subscription list|
|uint32_t *|[out]|handle|Request handle|

Add a Label UUID (full virtual address) to the model subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_remove_model_sub

`sl_status_t sl_btmesh_config_client_remove_model_sub(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint16_t|[in]|sub_address|The address to remove from the subscription list|
|uint32_t *|[out]|handle|Request handle|

Remove an address from the model subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_remove_model_sub_va

`sl_status_t sl_btmesh_config_client_remove_model_sub_va(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uuid_128 sub_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|[uuid_128](uuid-128)|[in]|sub_address|The full virtual address to remove from the subscription list|
|uint32_t *|[out]|handle|Request handle|

Remove a Label UUID (full virtual address) from the model subscription list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_set_model_sub

`sl_status_t sl_btmesh_config_client_set_model_sub(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint16_t|[in]|sub_address|The address to set as the subscription list|
|uint32_t *|[out]|handle|Request handle|

Set (overwrite) model subscription address list to a single address.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_set_model_sub_va

`sl_status_t sl_btmesh_config_client_set_model_sub_va(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uuid_128 sub_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|[uuid_128](uuid-128)|[in]|sub_address|The full virtual address to set as the subscription list|
|uint32_t *|[out]|handle|Request handle|

Set (overwrite) model subscription address list to a single virtual address.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_clear_model_sub

`sl_status_t sl_btmesh_config_client_clear_model_sub(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be configured resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to configure. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to configure|
|uint32_t *|[out]|handle|Request handle|

Clear (empty) the model subscription address list.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_model_sub_status](sl-btmesh-evt-config-client-model-sub-status)

##### sl_btmesh_config_client_list_subs

`sl_status_t sl_btmesh_config_client_list_subs(uint16_t enc_netkey_index, uint16_t server_address, uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|elem_index|Index of the element where the model, which is about to be queried resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model to query. Use 0xFFFF for Bluetooth SIG models.|
|uint16_t|[in]|model_id|Model ID for the model to query|
|uint32_t *|[out]|handle|Request handle|

Get the subscription address list of a model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_subs_list](sl-btmesh-evt-config-client-subs-list)
- [sl_btmesh_evt_config_client_subs_list_end](sl-btmesh-evt-config-client-subs-list-end)

##### sl_btmesh_config_client_get_heartbeat_pub

`sl_status_t sl_btmesh_config_client_get_heartbeat_pub(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get the heartbeat publication state of a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_heartbeat_pub_status](sl-btmesh-evt-config-client-heartbeat-pub-status)

##### sl_btmesh_config_client_set_heartbeat_pub

`sl_status_t sl_btmesh_config_client_set_heartbeat_pub(uint16_t enc_netkey_index, uint16_t server_address, uint16_t destination_address, uint16_t netkey_index, uint8_t count_log, uint8_t period_log, uint8_t ttl, uint16_t features, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|destination_address|Heartbeat publication destination address. The address can't be a virtual address. Note that it can be the unassigned address, in which case the heartbeat publishing is disabled.|
|uint16_t|[in]|netkey_index|Index of the network key used to encrypt heartbeat messages|
|uint8_t|[in]|count_log|Heartbeat publication count logarithm-of-2 setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not sent<br/>- **0x01 .. 0x11:** Node will send 2^(n-1) heartbeat messages<br/>- **0x12 .. 0xfe:** Prohibited<br/>- **0xff:** Hearbeat messages are sent indefinitely|
|uint8_t|[in]|period_log|Heartbeat publication period logarithm-of-2 setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not sent<br/>- **0x01 .. 0x11:** Node will send a heartbeat message every 2^(n-1) seconds<br/>- **0x12 .. 0xff:** Prohibited|
|uint8_t|[in]|ttl|Time-to-live value for heartbeat messages|
|uint16_t|[in]|features|Heartbeat trigger setting. For bits set in the bitmask, reconfiguration of the node feature associated with the bit will result in the node emitting a heartbeat message. Valid values are as follows:<br/><br/>- **Bit 0:** Relay feature<br/>- **Bit 1:** Proxy feature<br/>- **Bit 2:** Friend feature<br/>- **Bit 3:** Low power feature<br/><br/>Remaining bits are reserved for future use.|
|uint32_t *|[out]|handle|Request handle|

Set the heartbeat publication state of a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_heartbeat_pub_status](sl-btmesh-evt-config-client-heartbeat-pub-status)

##### sl_btmesh_config_client_get_heartbeat_sub

`sl_status_t sl_btmesh_config_client_get_heartbeat_sub(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get the heartbeat subscription state of a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_heartbeat_sub_status](sl-btmesh-evt-config-client-heartbeat-sub-status)

##### sl_btmesh_config_client_set_heartbeat_sub

`sl_status_t sl_btmesh_config_client_set_heartbeat_sub(uint16_t enc_netkey_index, uint16_t server_address, uint16_t source_address, uint16_t destination_address, uint8_t period_log, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|source_address|Source address for heartbeat messages, which must be either a unicast address or the unassigned address, in which case heartbeat messages are not processed.|
|uint16_t|[in]|destination_address|Destination address for heartbeat messages. The address must be either the unicast address of the primary element of the node, a group address, or the unassigned address. If it is the unassigned address, heartbeat messages are not processed.|
|uint8_t|[in]|period_log|Heartbeat subscription period logarithm-of-2 setting. Valid values are as follows:<br/><br/>- **0x00:** Heartbeat messages are not received<br/>- **0x01 .. 0x11:** Node will receive heartbeat messages for 2^(n-1) seconds<br/>- **0x12 .. 0xff:** Prohibited|
|uint32_t *|[out]|handle|Request handle|

Set the heartbeat subscription state of a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_heartbeat_sub_status](sl-btmesh-evt-config-client-heartbeat-sub-status)

##### sl_btmesh_config_client_get_beacon

`sl_status_t sl_btmesh_config_client_get_beacon(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node secure network beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_beacon_status](sl-btmesh-evt-config-client-beacon-status)

##### sl_btmesh_config_client_set_beacon

`sl_status_t sl_btmesh_config_client_set_beacon(uint16_t enc_netkey_index, uint16_t server_address, uint8_t value, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|value|Secure network beacon value to set. Valid values are:<br/><br/>- 0: Node is not broadcasting secure network beacons<br/>- 1: Node is broadcasting secure network beacons|
|uint32_t *|[out]|handle|Request handle|

Set node secure network beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_beacon_status](sl-btmesh-evt-config-client-beacon-status)

##### sl_btmesh_config_client_get_default_ttl

`sl_status_t sl_btmesh_config_client_get_default_ttl(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node default TTL state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_default_ttl_status](sl-btmesh-evt-config-client-default-ttl-status)

##### sl_btmesh_config_client_set_default_ttl

`sl_status_t sl_btmesh_config_client_set_default_ttl(uint16_t enc_netkey_index, uint16_t server_address, uint8_t value, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|value|Default TTL value. Valid value range is from 2 to 127 for relayed PDUs, and 0 to indicate non-relayed PDUs|
|uint32_t *|[out]|handle|Request handle|

Set node default TTL state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_default_ttl_status](sl-btmesh-evt-config-client-default-ttl-status)

##### sl_btmesh_config_client_get_gatt_proxy

`sl_status_t sl_btmesh_config_client_get_gatt_proxy(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node GATT proxy state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_gatt_proxy_status](sl-btmesh-evt-config-client-gatt-proxy-status)

##### sl_btmesh_config_client_set_gatt_proxy

`sl_status_t sl_btmesh_config_client_set_gatt_proxy(uint16_t enc_netkey_index, uint16_t server_address, uint8_t value, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|value|GATT proxy value to set. Valid values are:<br/><br/>- 0: Proxy feature is disabled<br/>- 1: Proxy feature is enabled|
|uint32_t *|[out]|handle|Request handle|

Set node GATT proxy state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_gatt_proxy_status](sl-btmesh-evt-config-client-gatt-proxy-status)

##### sl_btmesh_config_client_get_relay

`sl_status_t sl_btmesh_config_client_get_relay(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node relay state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_relay_status](sl-btmesh-evt-config-client-relay-status)

##### sl_btmesh_config_client_set_relay

`sl_status_t sl_btmesh_config_client_set_relay(uint16_t enc_netkey_index, uint16_t server_address, uint8_t value, uint8_t retransmit_count, uint16_t retransmit_interval_ms, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|value|Relay value to set. Valid values are:<br/><br/>- 0: Relay feature is disabled<br/>- 1: Relay feature is enabled|
|uint8_t|[in]|retransmit_count|Relay retransmit count. Valid values range from 0 to 7; default value is 0 (no retransmissions).|
|uint16_t|[in]|retransmit_interval_ms|Relay retransmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value is ignored if the retransmission count is set to zero.|
|uint32_t *|[out]|handle|Request handle|

Set node relay state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_relay_status](sl-btmesh-evt-config-client-relay-status)

##### sl_btmesh_config_client_get_network_transmit

`sl_status_t sl_btmesh_config_client_get_network_transmit(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node network transmit state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_network_transmit_status](sl-btmesh-evt-config-client-network-transmit-status)

##### sl_btmesh_config_client_set_network_transmit

`sl_status_t sl_btmesh_config_client_set_network_transmit(uint16_t enc_netkey_index, uint16_t server_address, uint8_t transmit_count, uint16_t transmit_interval_ms, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|transmit_count|Network transmit count. Valid values range from 1 to 8; default value is 1 (single transmission; no retransmissions).|
|uint16_t|[in]|transmit_interval_ms|Network transmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value is ignored if the transmission count is set to one.|
|uint32_t *|[out]|handle|Request handle|

Set node network transmit state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_network_transmit_status](sl-btmesh-evt-config-client-network-transmit-status)

##### sl_btmesh_config_client_get_identity

`sl_status_t sl_btmesh_config_client_get_identity(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Network key index for which the state is queried|
|uint32_t *|[out]|handle|Request handle|

Get node identity state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_identity_status](sl-btmesh-evt-config-client-identity-status)

##### sl_btmesh_config_client_set_identity

`sl_status_t sl_btmesh_config_client_set_identity(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint8_t value, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Network key index for which the state is configured|
|uint8_t|[in]|value|Identity value to set. Valid values are:<br/><br/>- 0: Node identity advertising is disabled<br/>- 1: Node identity advertising is enabled|
|uint32_t *|[out]|handle|Request handle|

Set node identity state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_identity_status](sl-btmesh-evt-config-client-identity-status)

##### sl_btmesh_config_client_get_friend

`sl_status_t sl_btmesh_config_client_get_friend(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node friend state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_friend_status](sl-btmesh-evt-config-client-friend-status)

##### sl_btmesh_config_client_set_friend

`sl_status_t sl_btmesh_config_client_set_friend(uint16_t enc_netkey_index, uint16_t server_address, uint8_t value, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|value|Friend value to set. Valid values are:<br/><br/>- 0: Friend feature is not enabled<br/>- 1: Friend feature is enabled|
|uint32_t *|[out]|handle|Request handle|

Set node friend state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_friend_status](sl-btmesh-evt-config-client-friend-status)

##### sl_btmesh_config_client_get_key_refresh_phase

`sl_status_t sl_btmesh_config_client_get_key_refresh_phase(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Network key index for which the state is queried|
|uint32_t *|[out]|handle|Request handle|

Get node key refresh phase state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_key_refresh_phase_status](sl-btmesh-evt-config-client-key-refresh-phase-status)

##### sl_btmesh_config_client_get_lpn_polltimeout

`sl_status_t sl_btmesh_config_client_get_lpn_polltimeout(uint16_t enc_netkey_index, uint16_t server_address, uint16_t lpn_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|lpn_address|LPN address|
|uint32_t *|[out]|handle|Request handle|

Get the LPN poll timeout from a Friend node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_lpn_polltimeout_status](sl-btmesh-evt-config-client-lpn-polltimeout-status)

##### sl_btmesh_config_client_get_dcd

`sl_status_t sl_btmesh_config_client_get_dcd(uint16_t enc_netkey_index, uint16_t server_address, uint8_t page, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|page|Composition data page to query|
|uint32_t *|[out]|handle|Request handle|

Get composition data of a device.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_dcd_data](sl-btmesh-evt-config-client-dcd-data)
- [sl_btmesh_evt_config_client_dcd_data_end](sl-btmesh-evt-config-client-dcd-data-end)

##### sl_btmesh_config_client_reset_node

`sl_status_t sl_btmesh_config_client_reset_node(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Request a node to unprovision itself. Use this function when a node is removed from the network.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_config_client_reset_status](sl-btmesh-evt-config-client-reset-status)

##### sl_btmesh_config_client_set_request_timeout_for_node

`sl_status_t sl_btmesh_config_client_set_request_timeout_for_node(uint16_t lpn_address, uint16_t timeout_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lpn_address|Destination LPN node primary element address for which the timeout is to be set.|
|uint16_t|[in]|timeout_ms|Timeout in milliseconds.|

Set request timeout for a specific node. Typically low power nodes have longer latencies and default timeout may not be sufficient.

Typically this command is issued after receiving a [sl_btmesh_evt_config_client_obo_ack_received](sl-btmesh-evt-config-client-obo-ack-received) event indicating that a message has been placed in the Friend Queue. To get an estimate for the needed timeout, sending a [sl_btmesh_config_client_get_lpn_polltimeout](sl-btmesh-config-client#sl-btmesh-config-client-get-lpn-polltimeout) request to the Friend is recommended.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_config_client_prepare_key_refresh

`sl_status_t sl_btmesh_config_client_prepare_key_refresh(aes_key_128 net_key, size_t app_keys_len, const uint8_t *app_keys)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[aes_key_128](aes-key-128)|[in]|net_key|New net key|
|size_t|[in]|app_keys_len|Length of data in `app_keys`|
|const uint8_t *|[in]|app_keys|list of new application keys, 16-bytes each|

Prepare the key refresh by feeding the new network key and all needed application keys. The function can be called multiple times to include more application keys. The network key must be the same in all calls. If the network key is changed, the network key from the 1st command is used. Sending application key data with length zero results in all initialization data being forgotten unless this is done in the first prepare command i.e., trying to update only the network key. Also starting the key refresh procedure results in all the preparation data being forgotten.

This command is needed if an application key is bound to different network key in some of the nodes. Otherwise it recommended to use [sl_btmesh_prov_start_key_refresh](sl-btmesh-prov#sl-btmesh-prov-start-key-refresh) procedure directly which takes care of the key generation.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_config_client_cancel_request_id 0x00270028`

`#define sl_btmesh_cmd_config_client_get_request_status_id 0x01270028`

`#define sl_btmesh_cmd_config_client_get_default_timeout_id 0x2e270028`

`#define sl_btmesh_cmd_config_client_set_default_timeout_id 0x2f270028`

`#define sl_btmesh_cmd_config_client_add_netkey_id 0x02270028`

`#define sl_btmesh_cmd_config_client_remove_netkey_id 0x03270028`

`#define sl_btmesh_cmd_config_client_list_netkeys_id 0x04270028`

`#define sl_btmesh_cmd_config_client_add_appkey_id 0x05270028`

`#define sl_btmesh_cmd_config_client_remove_appkey_id 0x06270028`

`#define sl_btmesh_cmd_config_client_list_appkeys_id 0x07270028`

`#define sl_btmesh_cmd_config_client_bind_model_id 0x08270028`

`#define sl_btmesh_cmd_config_client_unbind_model_id 0x09270028`

`#define sl_btmesh_cmd_config_client_list_bindings_id 0x0a270028`

`#define sl_btmesh_cmd_config_client_get_model_pub_id 0x0b270028`

`#define sl_btmesh_cmd_config_client_set_model_pub_id 0x0c270028`

`#define sl_btmesh_cmd_config_client_set_model_pub_va_id 0x0d270028`

`#define sl_btmesh_cmd_config_client_add_model_sub_id 0x0e270028`

`#define sl_btmesh_cmd_config_client_add_model_sub_va_id 0x0f270028`

`#define sl_btmesh_cmd_config_client_remove_model_sub_id 0x10270028`

`#define sl_btmesh_cmd_config_client_remove_model_sub_va_id 0x11270028`

`#define sl_btmesh_cmd_config_client_set_model_sub_id 0x12270028`

`#define sl_btmesh_cmd_config_client_set_model_sub_va_id 0x13270028`

`#define sl_btmesh_cmd_config_client_clear_model_sub_id 0x14270028`

`#define sl_btmesh_cmd_config_client_list_subs_id 0x15270028`

`#define sl_btmesh_cmd_config_client_get_heartbeat_pub_id 0x16270028`

`#define sl_btmesh_cmd_config_client_set_heartbeat_pub_id 0x17270028`

`#define sl_btmesh_cmd_config_client_get_heartbeat_sub_id 0x19270028`

`#define sl_btmesh_cmd_config_client_set_heartbeat_sub_id 0x1a270028`

`#define sl_btmesh_cmd_config_client_get_beacon_id 0x1b270028`

`#define sl_btmesh_cmd_config_client_set_beacon_id 0x1c270028`

`#define sl_btmesh_cmd_config_client_get_default_ttl_id 0x1d270028`

`#define sl_btmesh_cmd_config_client_set_default_ttl_id 0x1e270028`

`#define sl_btmesh_cmd_config_client_get_gatt_proxy_id 0x1f270028`

`#define sl_btmesh_cmd_config_client_set_gatt_proxy_id 0x20270028`

`#define sl_btmesh_cmd_config_client_get_relay_id 0x21270028`

`#define sl_btmesh_cmd_config_client_set_relay_id 0x22270028`

`#define sl_btmesh_cmd_config_client_get_network_transmit_id 0x23270028`

`#define sl_btmesh_cmd_config_client_set_network_transmit_id 0x24270028`

`#define sl_btmesh_cmd_config_client_get_identity_id 0x25270028`

`#define sl_btmesh_cmd_config_client_set_identity_id 0x26270028`

`#define sl_btmesh_cmd_config_client_get_friend_id 0x27270028`

`#define sl_btmesh_cmd_config_client_set_friend_id 0x28270028`

`#define sl_btmesh_cmd_config_client_get_key_refresh_phase_id 0x29270028`

`#define sl_btmesh_cmd_config_client_get_lpn_polltimeout_id 0x2b270028`

`#define sl_btmesh_cmd_config_client_get_dcd_id 0x2c270028`

`#define sl_btmesh_cmd_config_client_reset_node_id 0x2d270028`

`#define sl_btmesh_cmd_config_client_set_request_timeout_for_node_id 0x30270028`

`#define sl_btmesh_cmd_config_client_prepare_key_refresh_id 0x31270028`

`#define sl_btmesh_rsp_config_client_cancel_request_id 0x00270028`

`#define sl_btmesh_rsp_config_client_get_request_status_id 0x01270028`

`#define sl_btmesh_rsp_config_client_get_default_timeout_id 0x2e270028`

`#define sl_btmesh_rsp_config_client_set_default_timeout_id 0x2f270028`

`#define sl_btmesh_rsp_config_client_add_netkey_id 0x02270028`

`#define sl_btmesh_rsp_config_client_remove_netkey_id 0x03270028`

`#define sl_btmesh_rsp_config_client_list_netkeys_id 0x04270028`

`#define sl_btmesh_rsp_config_client_add_appkey_id 0x05270028`

`#define sl_btmesh_rsp_config_client_remove_appkey_id 0x06270028`

`#define sl_btmesh_rsp_config_client_list_appkeys_id 0x07270028`

`#define sl_btmesh_rsp_config_client_bind_model_id 0x08270028`

`#define sl_btmesh_rsp_config_client_unbind_model_id 0x09270028`

`#define sl_btmesh_rsp_config_client_list_bindings_id 0x0a270028`

`#define sl_btmesh_rsp_config_client_get_model_pub_id 0x0b270028`

`#define sl_btmesh_rsp_config_client_set_model_pub_id 0x0c270028`

`#define sl_btmesh_rsp_config_client_set_model_pub_va_id 0x0d270028`

`#define sl_btmesh_rsp_config_client_add_model_sub_id 0x0e270028`

`#define sl_btmesh_rsp_config_client_add_model_sub_va_id 0x0f270028`

`#define sl_btmesh_rsp_config_client_remove_model_sub_id 0x10270028`

`#define sl_btmesh_rsp_config_client_remove_model_sub_va_id 0x11270028`

`#define sl_btmesh_rsp_config_client_set_model_sub_id 0x12270028`

`#define sl_btmesh_rsp_config_client_set_model_sub_va_id 0x13270028`

`#define sl_btmesh_rsp_config_client_clear_model_sub_id 0x14270028`

`#define sl_btmesh_rsp_config_client_list_subs_id 0x15270028`

`#define sl_btmesh_rsp_config_client_get_heartbeat_pub_id 0x16270028`

`#define sl_btmesh_rsp_config_client_set_heartbeat_pub_id 0x17270028`

`#define sl_btmesh_rsp_config_client_get_heartbeat_sub_id 0x19270028`

`#define sl_btmesh_rsp_config_client_set_heartbeat_sub_id 0x1a270028`

`#define sl_btmesh_rsp_config_client_get_beacon_id 0x1b270028`

`#define sl_btmesh_rsp_config_client_set_beacon_id 0x1c270028`

`#define sl_btmesh_rsp_config_client_get_default_ttl_id 0x1d270028`

`#define sl_btmesh_rsp_config_client_set_default_ttl_id 0x1e270028`

`#define sl_btmesh_rsp_config_client_get_gatt_proxy_id 0x1f270028`

`#define sl_btmesh_rsp_config_client_set_gatt_proxy_id 0x20270028`

`#define sl_btmesh_rsp_config_client_get_relay_id 0x21270028`

`#define sl_btmesh_rsp_config_client_set_relay_id 0x22270028`

`#define sl_btmesh_rsp_config_client_get_network_transmit_id 0x23270028`

`#define sl_btmesh_rsp_config_client_set_network_transmit_id 0x24270028`

`#define sl_btmesh_rsp_config_client_get_identity_id 0x25270028`

`#define sl_btmesh_rsp_config_client_set_identity_id 0x26270028`

`#define sl_btmesh_rsp_config_client_get_friend_id 0x27270028`

`#define sl_btmesh_rsp_config_client_set_friend_id 0x28270028`

`#define sl_btmesh_rsp_config_client_get_key_refresh_phase_id 0x29270028`

`#define sl_btmesh_rsp_config_client_get_lpn_polltimeout_id 0x2b270028`

`#define sl_btmesh_rsp_config_client_get_dcd_id 0x2c270028`

`#define sl_btmesh_rsp_config_client_reset_node_id 0x2d270028`

`#define sl_btmesh_rsp_config_client_set_request_timeout_for_node_id 0x30270028`

`#define sl_btmesh_rsp_config_client_prepare_key_refresh_id 0x31270028`

#### sl_btmesh_evt_config_client_request_modified

Pending request parameters have been updated. 

The application may call [sl_btmesh_config_client_get_request_status](sl-btmesh-config-client#sl-btmesh-config-client-get-request-status) to retrieve the current status of the request. This event is generated when the timeout of a request is extended because the request is acknowledged by a Friend node on behalf of the LPN, which is the destination of the request. 

##### Modules

[sl_btmesh_evt_config_client_request_modified_s](sl-btmesh-evt-config-client-request-modified-s)

##### Typedefs

###### sl_btmesh_evt_config_client_request_modified_t

`typedef struct sl_btmesh_evt_config_client_request_modified_s sl_btmesh_evt_config_client_request_modified_t`

##### Macros

`#define sl_btmesh_evt_config_client_request_modified_id 0x002700a8`

**Description**: Identifier of the request_modified event.

Data structure of the request_modified event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_request_modified_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_netkey_status

This event is created when a response for an [sl_btmesh_config_client_add_netkey](sl-btmesh-config-client#sl-btmesh-config-client-add-netkey) or a [sl_btmesh_config_client_remove_netkey](sl-btmesh-config-client#sl-btmesh-config-client-remove-netkey) request is received, or the request times out. 

##### Modules

[sl_btmesh_evt_config_client_netkey_status_s](sl-btmesh-evt-config-client-netkey-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_netkey_status_t

`typedef struct sl_btmesh_evt_config_client_netkey_status_s sl_btmesh_evt_config_client_netkey_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_netkey_status_id 0x012700a8`

**Description**: Identifier of the netkey_status event.

Data structure of the netkey_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_netkey_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_netkey_status_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_netkey_list

This event contains a list of key indices for network keys that are present on a node. 

The list is requested using the [sl_btmesh_config_client_list_netkeys](sl-btmesh-config-client#sl-btmesh-config-client-list-netkeys) command. More than one event may be generated. List contents are terminated by a [sl_btmesh_evt_config_client_netkey_list_end](sl-btmesh-evt-config-client-netkey-list-end) event. 

##### Modules

[sl_btmesh_evt_config_client_netkey_list_s](sl-btmesh-evt-config-client-netkey-list-s)

##### Typedefs

###### sl_btmesh_evt_config_client_netkey_list_t

`typedef struct sl_btmesh_evt_config_client_netkey_list_s sl_btmesh_evt_config_client_netkey_list_t`

##### Macros

`#define sl_btmesh_evt_config_client_netkey_list_id 0x022700a8`

**Description**: Identifier of the netkey_list event.

Data structure of the netkey_list event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_netkey_list_s::handle
```

**Details:** Request handle

###### netkey_indices (heading level 7)

```
uint8array sl_btmesh_evt_config_client_netkey_list_s::netkey_indices
```

**Details:** List of network key indices, two bytes per entry

#### sl_btmesh_evt_config_client_netkey_list_end

Terminating event for network key index list. 

##### Modules

[sl_btmesh_evt_config_client_netkey_list_end_s](sl-btmesh-evt-config-client-netkey-list-end-s)

##### Typedefs

###### sl_btmesh_evt_config_client_netkey_list_end_t

`typedef struct sl_btmesh_evt_config_client_netkey_list_end_s sl_btmesh_evt_config_client_netkey_list_end_t`

##### Macros

`#define sl_btmesh_evt_config_client_netkey_list_end_id 0x032700a8`

**Description**: Identifier of the netkey_list_end event.

Data structure of the netkey_list_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_netkey_list_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_netkey_list_end_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_appkey_status

This event is created when a response for an [sl_btmesh_config_client_add_appkey](sl-btmesh-config-client#sl-btmesh-config-client-add-appkey) or a [sl_btmesh_config_client_remove_appkey](sl-btmesh-config-client#sl-btmesh-config-client-remove-appkey) request is received or the request times out. 

##### Modules

[sl_btmesh_evt_config_client_appkey_status_s](sl-btmesh-evt-config-client-appkey-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_appkey_status_t

`typedef struct sl_btmesh_evt_config_client_appkey_status_s sl_btmesh_evt_config_client_appkey_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_appkey_status_id 0x042700a8`

**Description**: Identifier of the appkey_status event.

Data structure of the appkey_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_appkey_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_appkey_status_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_appkey_list

This event contains a list of key indices for application keys that are present on a node and are bound to the network key specified in the request. 

The list is requested using the [sl_btmesh_config_client_list_appkeys](sl-btmesh-config-client#sl-btmesh-config-client-list-appkeys) command. More than one event may be generated. List contents are terminated by a [sl_btmesh_evt_config_client_appkey_list_end](sl-btmesh-evt-config-client-appkey-list-end) event. 

##### Modules

[sl_btmesh_evt_config_client_appkey_list_s](sl-btmesh-evt-config-client-appkey-list-s)

##### Typedefs

###### sl_btmesh_evt_config_client_appkey_list_t

`typedef struct sl_btmesh_evt_config_client_appkey_list_s sl_btmesh_evt_config_client_appkey_list_t`

##### Macros

`#define sl_btmesh_evt_config_client_appkey_list_id 0x052700a8`

**Description**: Identifier of the appkey_list event.

Data structure of the appkey_list event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_appkey_list_s::handle
```

**Details:** Request handle

###### appkey_indices (heading level 7)

```
uint8array sl_btmesh_evt_config_client_appkey_list_s::appkey_indices
```

**Details:** List of application key indices, two bytes per entry

#### sl_btmesh_evt_config_client_appkey_list_end

Terminating event for application key index list. 

##### Modules

[sl_btmesh_evt_config_client_appkey_list_end_s](sl-btmesh-evt-config-client-appkey-list-end-s)

##### Typedefs

###### sl_btmesh_evt_config_client_appkey_list_end_t

`typedef struct sl_btmesh_evt_config_client_appkey_list_end_s sl_btmesh_evt_config_client_appkey_list_end_t`

##### Macros

`#define sl_btmesh_evt_config_client_appkey_list_end_id 0x062700a8`

**Description**: Identifier of the appkey_list_end event.

Data structure of the appkey_list_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_appkey_list_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_appkey_list_end_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_binding_status

Status event for [sl_btmesh_config_client_bind_model](sl-btmesh-config-client#sl-btmesh-config-client-bind-model) and [sl_btmesh_config_client_unbind_model](sl-btmesh-config-client#sl-btmesh-config-client-unbind-model) application keys and models. 

##### Modules

[sl_btmesh_evt_config_client_binding_status_s](sl-btmesh-evt-config-client-binding-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_binding_status_t

`typedef struct sl_btmesh_evt_config_client_binding_status_s sl_btmesh_evt_config_client_binding_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_binding_status_id 0x072700a8`

**Description**: Identifier of the binding_status event.

Data structure of the binding_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_binding_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_binding_status_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_bindings_list

This event contains a list of key indices for the application keys which are bound to a model. 

The list is requested using the [sl_btmesh_config_client_list_bindings](sl-btmesh-config-client#sl-btmesh-config-client-list-bindings) command. More than one such event may be generated; the list contents are terminated by a [sl_btmesh_evt_config_client_bindings_list_end](sl-btmesh-evt-config-client-bindings-list-end) event. 

##### Modules

[sl_btmesh_evt_config_client_bindings_list_s](sl-btmesh-evt-config-client-bindings-list-s)

##### Typedefs

###### sl_btmesh_evt_config_client_bindings_list_t

`typedef struct sl_btmesh_evt_config_client_bindings_list_s sl_btmesh_evt_config_client_bindings_list_t`

##### Macros

`#define sl_btmesh_evt_config_client_bindings_list_id 0x082700a8`

**Description**: Identifier of the bindings_list event.

Data structure of the bindings_list event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_bindings_list_s::handle
```

**Details:** Request handle

###### appkey_indices (heading level 7)

```
uint8array sl_btmesh_evt_config_client_bindings_list_s::appkey_indices
```

**Details:** List of application key indices, two bytes per entry

#### sl_btmesh_evt_config_client_bindings_list_end

Terminating event for model-application key bindings list. 

##### Modules

[sl_btmesh_evt_config_client_bindings_list_end_s](sl-btmesh-evt-config-client-bindings-list-end-s)

##### Typedefs

###### sl_btmesh_evt_config_client_bindings_list_end_t

`typedef struct sl_btmesh_evt_config_client_bindings_list_end_s sl_btmesh_evt_config_client_bindings_list_end_t`

##### Macros

`#define sl_btmesh_evt_config_client_bindings_list_end_id 0x092700a8`

**Description**: Identifier of the bindings_list_end event.

Data structure of the bindings_list_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_bindings_list_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_bindings_list_end_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_model_pub_status

Status event for [sl_btmesh_config_client_get_model_pub](sl-btmesh-config-client#sl-btmesh-config-client-get-model-pub), [sl_btmesh_config_client_set_model_pub](sl-btmesh-config-client#sl-btmesh-config-client-set-model-pub), [sl_btmesh_config_client_set_model_pub_va](sl-btmesh-config-client#sl-btmesh-config-client-set-model-pub-va) commands. 

##### Modules

[sl_btmesh_evt_config_client_model_pub_status_s](sl-btmesh-evt-config-client-model-pub-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_model_pub_status_t

`typedef struct sl_btmesh_evt_config_client_model_pub_status_s sl_btmesh_evt_config_client_model_pub_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_model_pub_status_id 0x0a2700a8`

**Description**: Identifier of the model_pub_status event.

Data structure of the model_pub_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_model_pub_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_model_pub_status_s::handle
```

**Details:** Request handle

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_model_pub_status_s::address
```

**Details:** The address to publish to. If this address is the unassigned address, the model is prevented from publishing. Note that, if state contains a Label UUID (full virtual address), the corresponding virtual address hash is returned in this parameter.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_model_pub_status_s::appkey_index
```

**Details:** The application key index used for the published messages

###### credentials (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_model_pub_status_s::credentials
```

**Details:** Friendship credentials flag

###### ttl (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_model_pub_status_s::ttl
```

**Details:** Publication time-to-live value

###### period_ms (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_model_pub_status_s::period_ms
```

**Details:** Publication period in milliseconds

###### retransmit_count (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_model_pub_status_s::retransmit_count
```

**Details:** Publication retransmission count

###### retransmit_interval_ms (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_model_pub_status_s::retransmit_interval_ms
```

**Details:** Publication retransmission interval in milliseconds

#### sl_btmesh_evt_config_client_model_sub_status

Status event for [sl_btmesh_config_client_add_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-add-model-sub) : add subscription address, [sl_btmesh_config_client_add_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-add-model-sub-va) : add subscription virtual address, [sl_btmesh_config_client_remove_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-remove-model-sub) : remove subscription address, [sl_btmesh_config_client_remove_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-remove-model-sub-va) : remove subscription virtual address, [sl_btmesh_config_client_set_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-set-model-sub) : set subscription address, [sl_btmesh_config_client_set_model_sub_va](sl-btmesh-config-client#sl-btmesh-config-client-set-model-sub-va) : set subscription virtual address, and [sl_btmesh_config_client_clear_model_sub](sl-btmesh-config-client#sl-btmesh-config-client-clear-model-sub) : clear subscription address list commands. 

##### Modules

[sl_btmesh_evt_config_client_model_sub_status_s](sl-btmesh-evt-config-client-model-sub-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_model_sub_status_t

`typedef struct sl_btmesh_evt_config_client_model_sub_status_s sl_btmesh_evt_config_client_model_sub_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_model_sub_status_id 0x0b2700a8`

**Description**: Identifier of the model_sub_status event.

Data structure of the model_sub_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_model_sub_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_model_sub_status_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_subs_list

This event contains a list of addresses that the queried model subscribes to. 

The list is requested using the [sl_btmesh_config_client_list_subs](sl-btmesh-config-client#sl-btmesh-config-client-list-subs) command. More than one event may be generated. List contents are terminated by a [sl_btmesh_evt_config_client_subs_list_end](sl-btmesh-evt-config-client-subs-list-end) event. Note that, if the subscription address list entry is a Label UUID (full virtual address), the corresponding virtual address hash is returned in this event. 

##### Modules

[sl_btmesh_evt_config_client_subs_list_s](sl-btmesh-evt-config-client-subs-list-s)

##### Typedefs

###### sl_btmesh_evt_config_client_subs_list_t

`typedef struct sl_btmesh_evt_config_client_subs_list_s sl_btmesh_evt_config_client_subs_list_t`

##### Macros

`#define sl_btmesh_evt_config_client_subs_list_id 0x0c2700a8`

**Description**: Identifier of the subs_list event.

Data structure of the subs_list event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_subs_list_s::handle
```

**Details:** Request handle

###### addresses (heading level 7)

```
uint8array sl_btmesh_evt_config_client_subs_list_s::addresses
```

**Details:** List of subscription addresses, two bytes per entry

#### sl_btmesh_evt_config_client_subs_list_end

Terminating event for model subscription list. 

##### Modules

[sl_btmesh_evt_config_client_subs_list_end_s](sl-btmesh-evt-config-client-subs-list-end-s)

##### Typedefs

###### sl_btmesh_evt_config_client_subs_list_end_t

`typedef struct sl_btmesh_evt_config_client_subs_list_end_s sl_btmesh_evt_config_client_subs_list_end_t`

##### Macros

`#define sl_btmesh_evt_config_client_subs_list_end_id 0x0d2700a8`

**Description**: Identifier of the subs_list_end event.

Data structure of the subs_list_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_subs_list_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_subs_list_end_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_heartbeat_pub_status

Status event for [sl_btmesh_config_client_get_heartbeat_pub](sl-btmesh-config-client#sl-btmesh-config-client-get-heartbeat-pub) and [sl_btmesh_config_client_set_heartbeat_pub](sl-btmesh-config-client#sl-btmesh-config-client-set-heartbeat-pub) commands. 

##### Modules

[sl_btmesh_evt_config_client_heartbeat_pub_status_s](sl-btmesh-evt-config-client-heartbeat-pub-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_heartbeat_pub_status_t

`typedef struct sl_btmesh_evt_config_client_heartbeat_pub_status_s sl_btmesh_evt_config_client_heartbeat_pub_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_heartbeat_pub_status_id 0x0e2700a8`

**Description**: Identifier of the heartbeat_pub_status event.

Data structure of the heartbeat_pub_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::handle
```

**Details:** Request handle

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::destination_address
```

**Details:** Heartbeat publication destination address.

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::netkey_index
```

**Details:** Index of the network key used to encrypt heartbeat messages

###### count_log (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::count_log
```

**Details:** Heartbeat publication count logarithm-of-2 setting

###### period_log (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::period_log
```

**Details:** Heartbeat publication period logarithm-of-2 setting

###### ttl (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::ttl
```

**Details:** Time-to-live value for heartbeat messages

###### features (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_pub_status_s::features
```

**Details:** Heartbeat trigger setting

#### sl_btmesh_evt_config_client_heartbeat_sub_status

Status event for [sl_btmesh_config_client_get_heartbeat_sub](sl-btmesh-config-client#sl-btmesh-config-client-get-heartbeat-sub) and [sl_btmesh_config_client_set_heartbeat_sub](sl-btmesh-config-client#sl-btmesh-config-client-set-heartbeat-sub) commands. 

##### Modules

[sl_btmesh_evt_config_client_heartbeat_sub_status_s](sl-btmesh-evt-config-client-heartbeat-sub-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_heartbeat_sub_status_t

`typedef struct sl_btmesh_evt_config_client_heartbeat_sub_status_s sl_btmesh_evt_config_client_heartbeat_sub_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_heartbeat_sub_status_id 0x0f2700a8`

**Description**: Identifier of the heartbeat_sub_status event.

Data structure of the heartbeat_sub_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::handle
```

**Details:** Request handle

###### source_address (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::source_address
```

**Details:** Source address for heartbeat messages

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::destination_address
```

**Details:** Destination address for heartbeat messages

###### period_log (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::period_log
```

**Details:** Heartbeat subscription remaining period logarithm-of-2 value

###### count_log (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::count_log
```

**Details:** Received heartbeat message count logarithm-of-2 value

###### min_hops (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::min_hops
```

**Details:** Minimum hop value seen in received heartbeat messages

###### max_hops (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_heartbeat_sub_status_s::max_hops
```

**Details:** Minimum hop value seen in received heartbeat messages

#### sl_btmesh_evt_config_client_beacon_status

Status event for [sl_btmesh_config_client_get_beacon](sl-btmesh-config-client#sl-btmesh-config-client-get-beacon) and [sl_btmesh_config_client_set_beacon](sl-btmesh-config-client#sl-btmesh-config-client-set-beacon) commands. 

##### Modules

[sl_btmesh_evt_config_client_beacon_status_s](sl-btmesh-evt-config-client-beacon-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_beacon_status_t

`typedef struct sl_btmesh_evt_config_client_beacon_status_s sl_btmesh_evt_config_client_beacon_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_beacon_status_id 0x102700a8`

**Description**: Identifier of the beacon_status event.

Data structure of the beacon_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_beacon_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_beacon_status_s::handle
```

**Details:** Request handle

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_beacon_status_s::value
```

**Details:** Secure network beacon state of the node. Valid values are:

- 0: Node is not broadcasting secure network beacons
- 1: Node is broadcasting secure network beacons

#### sl_btmesh_evt_config_client_default_ttl_status

Status event for [sl_btmesh_config_client_get_default_ttl](sl-btmesh-config-client#sl-btmesh-config-client-get-default-ttl) and [sl_btmesh_config_client_set_default_ttl](sl-btmesh-config-client#sl-btmesh-config-client-set-default-ttl) commands. 

##### Modules

[sl_btmesh_evt_config_client_default_ttl_status_s](sl-btmesh-evt-config-client-default-ttl-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_default_ttl_status_t

`typedef struct sl_btmesh_evt_config_client_default_ttl_status_s sl_btmesh_evt_config_client_default_ttl_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_default_ttl_status_id 0x112700a8`

**Description**: Identifier of the default_ttl_status event.

Data structure of the default_ttl_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_default_ttl_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_default_ttl_status_s::handle
```

**Details:** Request handle

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_default_ttl_status_s::value
```

**Details:** Default TTL value. Valid value range is from 2 to 127 for relayed PDUs, and 0 to indicate non-relayed PDUs.

#### sl_btmesh_evt_config_client_gatt_proxy_status

Status event for [sl_btmesh_config_client_get_gatt_proxy](sl-btmesh-config-client#sl-btmesh-config-client-get-gatt-proxy) and [sl_btmesh_config_client_set_gatt_proxy](sl-btmesh-config-client#sl-btmesh-config-client-set-gatt-proxy) commands. 

##### Modules

[sl_btmesh_evt_config_client_gatt_proxy_status_s](sl-btmesh-evt-config-client-gatt-proxy-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_gatt_proxy_status_t

`typedef struct sl_btmesh_evt_config_client_gatt_proxy_status_s sl_btmesh_evt_config_client_gatt_proxy_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_gatt_proxy_status_id 0x122700a8`

**Description**: Identifier of the gatt_proxy_status event.

Data structure of the gatt_proxy_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_gatt_proxy_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_gatt_proxy_status_s::handle
```

**Details:** Request handle

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_gatt_proxy_status_s::value
```

**Details:** GATT proxy value of the node. Valid values are:

- 0: GATT proxy feature is disabled
- 1: GATT proxy feature is enabled
- 2: GATT proxy feature is not supported

#### sl_btmesh_evt_config_client_relay_status

Status event for [sl_btmesh_config_client_get_relay](sl-btmesh-config-client#sl-btmesh-config-client-get-relay) and [sl_btmesh_config_client_set_relay](sl-btmesh-config-client#sl-btmesh-config-client-set-relay) commands. 

##### Modules

[sl_btmesh_evt_config_client_relay_status_s](sl-btmesh-evt-config-client-relay-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_relay_status_t

`typedef struct sl_btmesh_evt_config_client_relay_status_s sl_btmesh_evt_config_client_relay_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_relay_status_id 0x132700a8`

**Description**: Identifier of the relay_status event.

Data structure of the relay_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_relay_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_relay_status_s::handle
```

**Details:** Request handle

###### relay (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_relay_status_s::relay
```

**Details:** Relay state of the node. Valid values are as follows:

- 0: Relaying disabled
- 1: Relaying enabled
- 2: Relaying not supported

###### retransmit_count (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_relay_status_s::retransmit_count
```

**Details:** Relay retransmit count. Valid values range from 0 to 7; default value is 0 (no retransmissions).

###### retransmit_interval_ms (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_relay_status_s::retransmit_interval_ms
```

**Details:** Relay retransmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value will be zero if the retransmission count is zero.

#### sl_btmesh_evt_config_client_network_transmit_status

Status event for [sl_btmesh_config_client_get_network_transmit](sl-btmesh-config-client#sl-btmesh-config-client-get-network-transmit) and [sl_btmesh_config_client_set_network_transmit](sl-btmesh-config-client#sl-btmesh-config-client-set-network-transmit) commands. 

##### Modules

[sl_btmesh_evt_config_client_network_transmit_status_s](sl-btmesh-evt-config-client-network-transmit-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_network_transmit_status_t

`typedef struct sl_btmesh_evt_config_client_network_transmit_status_s sl_btmesh_evt_config_client_network_transmit_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_network_transmit_status_id 0x142700a8`

**Description**: Identifier of the network_transmit_status event.

Data structure of the network_transmit_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_network_transmit_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_network_transmit_status_s::handle
```

**Details:** Request handle

###### transmit_count (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_network_transmit_status_s::transmit_count
```

**Details:** Network transmit count. Valid values range from 1 to 8; default value is 1 (single transmission; no retransmissions).

###### transmit_interval_ms (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_network_transmit_status_s::transmit_interval_ms
```

**Details:** Network transmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value will be zero if the transmission count is set to one.

#### sl_btmesh_evt_config_client_identity_status

Status event for [sl_btmesh_config_client_get_identity](sl-btmesh-config-client#sl-btmesh-config-client-get-identity) and [sl_btmesh_config_client_set_identity](sl-btmesh-config-client#sl-btmesh-config-client-set-identity) commands. 

##### Modules

[sl_btmesh_evt_config_client_identity_status_s](sl-btmesh-evt-config-client-identity-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_identity_status_t

`typedef struct sl_btmesh_evt_config_client_identity_status_s sl_btmesh_evt_config_client_identity_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_identity_status_id 0x152700a8`

**Description**: Identifier of the identity_status event.

Data structure of the identity_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_identity_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_identity_status_s::handle
```

**Details:** Request handle

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_identity_status_s::value
```

**Details:** Identity state of the node for the used network index. Valid values are as follows:

- 0: Node identity advertising is disabled
- 1: Node identity advertising is enabled
- 2: Node identity advertising is not supported

#### sl_btmesh_evt_config_client_friend_status

Status event for [sl_btmesh_config_client_get_friend](sl-btmesh-config-client#sl-btmesh-config-client-get-friend) and [sl_btmesh_config_client_set_friend](sl-btmesh-config-client#sl-btmesh-config-client-set-friend) commands. 

##### Modules

[sl_btmesh_evt_config_client_friend_status_s](sl-btmesh-evt-config-client-friend-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_friend_status_t

`typedef struct sl_btmesh_evt_config_client_friend_status_s sl_btmesh_evt_config_client_friend_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_friend_status_id 0x162700a8`

**Description**: Identifier of the friend_status event.

Data structure of the friend_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_friend_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_friend_status_s::handle
```

**Details:** Request handle

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_friend_status_s::value
```

**Details:** Friend value to set. Valid values are:

- 0: Friend feature is not enabled
- 1: Friend feature is enabled
- 2: Friend feature is not supported

#### sl_btmesh_evt_config_client_key_refresh_phase_status

Status event for [sl_btmesh_config_client_get_key_refresh_phase](sl-btmesh-config-client#sl-btmesh-config-client-get-key-refresh-phase) command. 

##### Modules

[sl_btmesh_evt_config_client_key_refresh_phase_status_s](sl-btmesh-evt-config-client-key-refresh-phase-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_key_refresh_phase_status_t

`typedef struct sl_btmesh_evt_config_client_key_refresh_phase_status_s sl_btmesh_evt_config_client_key_refresh_phase_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_key_refresh_phase_status_id 0x172700a8`

**Description**: Identifier of the key_refresh_phase_status event.

Data structure of the key_refresh_phase_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_key_refresh_phase_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_key_refresh_phase_status_s::handle
```

**Details:** Request handle

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_key_refresh_phase_status_s::netkey_index
```

**Details:** Network key index for which the state applies

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_key_refresh_phase_status_s::value
```

**Details:** Key refresh phase state of the node for the given network key. Valid values are:

- 0: Normal operation
- 1: First phase of key refresh procedure
- 2: Second phase of key refresh procedure

#### sl_btmesh_evt_config_client_lpn_polltimeout_status

Status event for [sl_btmesh_config_client_get_lpn_polltimeout](sl-btmesh-config-client#sl-btmesh-config-client-get-lpn-polltimeout) command. 

##### Modules

[sl_btmesh_evt_config_client_lpn_polltimeout_status_s](sl-btmesh-evt-config-client-lpn-polltimeout-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_lpn_polltimeout_status_t

`typedef struct sl_btmesh_evt_config_client_lpn_polltimeout_status_s sl_btmesh_evt_config_client_lpn_polltimeout_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_lpn_polltimeout_status_id 0x182700a8`

**Description**: Identifier of the lpn_polltimeout_status event.

Data structure of the lpn_polltimeout_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_lpn_polltimeout_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_lpn_polltimeout_status_s::handle
```

**Details:** Request handle

###### poll_timeout_ms (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_lpn_polltimeout_status_s::poll_timeout_ms
```

**Details:** Poll timeout value, in milliseconds, for the specified LPN. The value reported is zero if the queried Friend does not have an ongoing friendship with the specified LPN.

#### sl_btmesh_evt_config_client_dcd_data

Event reporting queried composition data page contents. 

The contents are requested using the [sl_btmesh_config_client_get_dcd](sl-btmesh-config-client#sl-btmesh-config-client-get-dcd) command. More than one event may be generated. Page contents are terminated by a [sl_btmesh_evt_config_client_dcd_data_end](sl-btmesh-evt-config-client-dcd-data-end) event. Note that the interpretation of the received data is page-specific. Page 0 contains the element and model layout of the node. 

##### Modules

[sl_btmesh_evt_config_client_dcd_data_s](sl-btmesh-evt-config-client-dcd-data-s)

##### Typedefs

###### sl_btmesh_evt_config_client_dcd_data_t

`typedef struct sl_btmesh_evt_config_client_dcd_data_s sl_btmesh_evt_config_client_dcd_data_t`

##### Macros

`#define sl_btmesh_evt_config_client_dcd_data_id 0x192700a8`

**Description**: Identifier of the dcd_data event.

Data structure of the dcd_data event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_dcd_data_s::handle
```

**Details:** Request handle

###### page (heading level 7)

```
uint8_t sl_btmesh_evt_config_client_dcd_data_s::page
```

**Details:** Composition data page containing data

###### data (heading level 7)

```
uint8array sl_btmesh_evt_config_client_dcd_data_s::data
```

**Details:** Composition data page contents

#### sl_btmesh_evt_config_client_dcd_data_end

Terminating event for node composition data. 

##### Modules

[sl_btmesh_evt_config_client_dcd_data_end_s](sl-btmesh-evt-config-client-dcd-data-end-s)

##### Typedefs

###### sl_btmesh_evt_config_client_dcd_data_end_t

`typedef struct sl_btmesh_evt_config_client_dcd_data_end_s sl_btmesh_evt_config_client_dcd_data_end_t`

##### Macros

`#define sl_btmesh_evt_config_client_dcd_data_end_id 0x1a2700a8`

**Description**: Identifier of the dcd_data_end event.

Data structure of the dcd_data_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_dcd_data_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_dcd_data_end_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_reset_status

Indicate a node has received a [sl_btmesh_config_client_reset_node](sl-btmesh-config-client#sl-btmesh-config-client-reset-node). 

##### Modules

[sl_btmesh_evt_config_client_reset_status_s](sl-btmesh-evt-config-client-reset-status-s)

##### Typedefs

###### sl_btmesh_evt_config_client_reset_status_t

`typedef struct sl_btmesh_evt_config_client_reset_status_s sl_btmesh_evt_config_client_reset_status_t`

##### Macros

`#define sl_btmesh_evt_config_client_reset_status_id 0x1b2700a8`

**Description**: Identifier of the reset_status event.

Data structure of the reset_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_reset_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_config_client_reset_status_s::handle
```

**Details:** Request handle

#### sl_btmesh_evt_config_client_obo_ack_received

Node received a transport layer Ack from a friend node , indicating that the message has been placed in the Friend Queue. 

##### Modules

[sl_btmesh_evt_config_client_obo_ack_received_s](sl-btmesh-evt-config-client-obo-ack-received-s)

##### Typedefs

###### sl_btmesh_evt_config_client_obo_ack_received_t

`typedef struct sl_btmesh_evt_config_client_obo_ack_received_s sl_btmesh_evt_config_client_obo_ack_received_t`

##### Macros

`#define sl_btmesh_evt_config_client_obo_ack_received_id 0x1c2700a8`

**Description**: Identifier of the obo_ack_received event.

Data structure of the obo_ack_received event. 

###### Public Attributes

###### lpn_addr (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_obo_ack_received_s::lpn_addr
```

**Details:** Address of Friend node.

###### friend_addr (heading level 7)

```
uint16_t sl_btmesh_evt_config_client_obo_ack_received_s::friend_addr
```

**Details:** Address of Friend node.

### Bluetooth Mesh BLOB Transfer Client Model

Bluetooth Mesh BLOB Transfer Client Model. 

The Bluetooth Mesh BLOB Transfer (MBT) Client model is used to transfer binary large objects (BLOBs) over a Bluetooth Mesh network. An MBT Client can transfer a BLOB to one or more MBT Servers, either unicasting or multicasting depending on the situation.

There are two different modes in which the transfer may be performed: Push BLOB Transfer mode and Pull BLOB Transfer mode. The MBT Client selects the transfer mode based on the capabilities supported by the servers. The Pull BLOB Transfer mode is typically used only if some of the MBT Servers are Low Power Nodes. The MBT Client API usage flow is identical in both transfer modes.

The MBT Client model is normally used as a transport in a higher-layer model, e.g., the Firmware Update models. Please refer to the documentation of such a model for more information on how to interact with the MBT Client API in that context.

MBT Client command, which generates and sends a message to MBT Server, could fail with SL_STATUS_BUSY or SL_STATUS_NO_MORE_RESOURCE return value. SL_STATUS_BUSY return value implies underlying Tx-processing pipeline is full and can't currently accept new Tx-messages. SL_STATUS_NO_MORE_RESOURCE implies memory resources required for generating the required message are not currently available. In both of the above cases application should reissue the command at later time. Depending of the exact case [sl_btmesh_evt_mbt_client_tx_complete](sl-btmesh-evt-mbt-client-tx-complete) could be used for timing the command retry.

If the command failed, then no [sl_btmesh_evt_mbt_client_tx_complete](sl-btmesh-evt-mbt-client-tx-complete) is going to be emitted and the app's retry timer could be started immediately after receiving the error. In a successful case, the retry timer should never be started before receiving this event as the application might retry before the previous message is sent out to all recipients. 

#### Modules

[sl_btmesh_evt_mbt_client_server_information_status](sl-btmesh-evt-mbt-client-server-information-status)

[sl_btmesh_evt_mbt_client_query_information_complete](sl-btmesh-evt-mbt-client-query-information-complete)

[sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status)

[sl_btmesh_evt_mbt_client_start_transfer_complete](sl-btmesh-evt-mbt-client-start-transfer-complete)

[sl_btmesh_evt_mbt_client_server_block_status](sl-btmesh-evt-mbt-client-server-block-status)

[sl_btmesh_evt_mbt_client_start_block_complete](sl-btmesh-evt-mbt-client-start-block-complete)

[sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request)

[sl_btmesh_evt_mbt_client_server_partial_block_report](sl-btmesh-evt-mbt-client-server-partial-block-report)

[sl_btmesh_evt_mbt_client_send_chunks_complete](sl-btmesh-evt-mbt-client-send-chunks-complete)

[sl_btmesh_evt_mbt_client_query_block_status_complete](sl-btmesh-evt-mbt-client-query-block-status-complete)

[sl_btmesh_evt_mbt_client_tx_complete](sl-btmesh-evt-mbt-client-tx-complete)

[sl_btmesh_evt_mbt_client_server_failed](sl-btmesh-evt-mbt-client-server-failed)

[sl_btmesh_evt_mbt_client_transfer_complete](sl-btmesh-evt-mbt-client-transfer-complete)

#### Enumerations

##### sl_btmesh_mbt_client_server_status_t

```
enum sl_btmesh_mbt_client_server_status_t {
    sl_btmesh_mbt_client_server_status_done = 0x0
    sl_btmesh_mbt_client_server_status_in_progress = 0x1
    sl_btmesh_mbt_client_server_status_error = 0x2
    sl_btmesh_mbt_client_server_status_successfully_complete = 0x3
}
```

**Description:**

The MBT Server Status.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_mbt_client_server_status_done|(0x0) Current procedure is done.|
|sl_btmesh_mbt_client_server_status_in_progress|(0x1) Current procedure is in progress.|
|sl_btmesh_mbt_client_server_status_error|(0x2) MBT Server has failed, and is no longer part of the transfer.|
|sl_btmesh_mbt_client_server_status_successfully_complete|(0x3) Transfer successfully complete, server has reported to have received all the blocks of the BLOB successfully.|

##### sl_btmesh_mbt_client_transfer_mode_t

```
enum sl_btmesh_mbt_client_transfer_mode_t {
    sl_btmesh_mbt_client_mbt_transfer_mode_none = 0x0
    sl_btmesh_mbt_client_mbt_transfer_mode_push = 0x1
    sl_btmesh_mbt_client_mbt_transfer_mode_pull = 0x2
    sl_btmesh_mbt_client_mbt_transfer_mode_both = 0x3
}
```

**Description:**

The MBT Transfer modes.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_mbt_client_mbt_transfer_mode_none|(0x0) No BLOB Transfer mode.|
|sl_btmesh_mbt_client_mbt_transfer_mode_push|(0x1) Push BLOB Transfer mode (client-driven).|
|sl_btmesh_mbt_client_mbt_transfer_mode_pull|(0x2) Pull BLOB Transfer mode (server-driven).|
|sl_btmesh_mbt_client_mbt_transfer_mode_both|(0x3) Push and Pull BLOB Transfer modes.|

#### Functions

##### sl_btmesh_mbt_client_init

`sl_status_t sl_btmesh_mbt_client_init(uint16_t elem_index, uint16_t max_servers, uint16_t max_blocks, uint16_t max_chunks_per_block)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint16_t|[in]|max_servers|The maximum number of servers supported simultaneously. Maximum supported value is 1008.|
|uint16_t|[in]|max_blocks|The maximum number of blocks into which a BLOB can be broken down. Maximum supported value is 1888.|
|uint16_t|[in]|max_chunks_per_block|The maximum number of chunks into which a block can be broken down. Maximum supported value is 2000.|

Initialize the MBT Client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_deinit

`sl_status_t sl_btmesh_mbt_client_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|

De-initializes the MBT Client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_setup

`sl_status_t sl_btmesh_mbt_client_setup(uint16_t elem_index, sl_bt_uuid_64_t blob_id, uint32_t blob_size, uint16_t appkey_index, uint8_t ttl, uint16_t timeout_base, uint8_t supported_transfer_modes, uint16_t group_address, uuid_128 virtual_address, uint16_t multicast_threshold, size_t servers_len, const uint8_t *servers)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t)|[in]|blob_id|The ID of the BLOB.|
|uint32_t|[in]|blob_size|The size of the BLOB.|
|uint16_t|[in]|appkey_index|Application key index to use for communicating with the servers.|
|uint8_t|[in]|ttl|The time-to-live value to use when communicating with the servers. Valid values: 0, range:[2-127] and 255.|
|uint16_t|[in]|timeout_base|If a Server does not respond within time frame of: (10000 * (timeout_base + 2)) + (100 * ttl) in units of ms, it will be marked as inactive.|
|uint8_t|[in]|supported_transfer_modes|A bitfield of supported transfer modes. At least one must be supported. If multiple transfer modes are supported by both the client and servers, Push mode will be preferred.<br/><br/>- Bit 0: Push BLOB Transfer mode<br/>- Bit 1: Pull BLOB Transfer mode|
|uint16_t|[in]|group_address|The group address to use if the multicast_threshold is exceeded. Zero to only use unicast.|
|[uuid_128](uuid-128)|[in]|virtual_address|If the group address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|multicast_threshold|If the number of servers for any step exceeds or is equal to this number, the group address will be used. Otherwise, servers will be looped through one by one. Value of 0 disables the feature.|
|size_t|[in]|servers_len|Length of data in `servers`|
|const uint8_t *|[in]|servers|List of MBT Server addresses, represented as little endian two byte sequences.|

Set up a new BLOB transfer.

This is the first step in starting a transfer. Basic information of the BLOB and the transfer are defined with this command.

After setting up a transfer, the information of the servers should be queried with [sl_btmesh_mbt_client_query_information](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-information).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_query_information

`sl_status_t sl_btmesh_mbt_client_query_information(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|

Query MBT Server information.

After setting up a new BLOB transfer with [sl_btmesh_mbt_client_setup](sl-btmesh-mbt-client#sl-btmesh-mbt-client-setup), the server information needs to be queried with this command. The received query result for each server is carried in a separate [sl_btmesh_evt_mbt_client_server_information_status](sl-btmesh-evt-mbt-client-server-information-status) event. This information should be used by the application to determine the size of blocks in which the BLOB is divided when transmitting, and the size of chunks in which each block is divided.

The [sl_btmesh_evt_mbt_client_query_information_complete](sl-btmesh-evt-mbt-client-query-information-complete) event indicates that all servers have responded to the query. If this is not received in a timely manner, the query may be resent by calling this command again.

After the information query is successfully completed, the BLOB transfer should be initiated with [sl_btmesh_mbt_client_start_transfer](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-transfer).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_client_server_information_status](sl-btmesh-evt-mbt-client-server-information-status)
- [sl_btmesh_evt_mbt_client_query_information_complete](sl-btmesh-evt-mbt-client-query-information-complete)

##### sl_btmesh_mbt_client_get_server_status

`sl_status_t sl_btmesh_mbt_client_get_server_status(uint16_t elem_index, uint16_t server_index, uint16_t *server_address, uint8_t *current_procedure_status, uint16_t *rx_blocks, uint16_t *rx_chunks)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint16_t|[in]|server_index|The index of the MBT Server which status to check.|
|uint16_t *|[out]|server_address|The MBT Server address to identify which server the information belongs to.|
|uint8_t *|[out]|current_procedure_status|Enum [sl_btmesh_mbt_client_server_status_t](sl-btmesh-mbt-client#sl-btmesh-mbt-client-server-status-t). The MBT Server Status.|
|uint16_t *|[out]|rx_blocks|BLOB Transfer blocks delivered and confirmed.|
|uint16_t *|[out]|rx_chunks|BLOB Transfer current block chunks delivered and confirmed.<br/><br/>**Note** : parameter is only valid in the push transfer mode.|

Check the status of a MBT Server participating in the transfer, as recorded in the Client's internal bookkeeping.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_add_server

`sl_status_t sl_btmesh_mbt_client_add_server(uint16_t elem_index, uint16_t server_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint16_t|[in]|server_address|The address of the MBT Server to add.|

Add MBT Server. Server can be added after calling [sl_btmesh_mbt_client_setup](sl-btmesh-mbt-client#sl-btmesh-mbt-client-setup) and before calling [sl_btmesh_mbt_client_query_information](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-information).

**Returns**

- SL_STATUS_OK if successful. SL_STATUS_BT_MESH_LIMIT_REACHED if the configured maximun storage has been reached. SL_STATUS_INVALID_STATE if invalid state, as proper call time for this API specified within the description of the API. SL_STATUS_BT_MESH_DOES_NOT_EXIST if the MBT Client model does not exist within the element specifed by the input parameter.

##### sl_btmesh_mbt_client_configure_throttle

`sl_status_t sl_btmesh_mbt_client_configure_throttle(uint16_t elem_index, uint16_t throttle_delay_ms, uint8_t throttle_concurrent)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint16_t|[in]|throttle_delay_ms|Controls the delay in milliseconds between batches of messages. Works in conjunction with `throttle_concurrent` to control message sending rate. When the first transmission in the current batch completes, the sender will wait for this delay before refilling the batch up to the `throttle_concurrent` limit with new transmissions.|
|uint8_t|[in]|throttle_concurrent|Defines how many messages are being sent concurrently. If set to 0, the maximum supported value is used.|

Configure the MBT Client's sender.

This command is used to configure sender of the MBT Client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_start_transfer

`sl_status_t sl_btmesh_mbt_client_start_transfer(uint16_t elem_index, uint8_t block_size_log, uint8_t transfer_mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint8_t|[in]|block_size_log|The block size as an exponent n in 2^n. Range: 6 - 32.|
|uint8_t|[in]|transfer_mode|Enum [sl_btmesh_mbt_client_transfer_mode_t](sl-btmesh-mbt-client#sl-btmesh-mbt-client-transfer-mode-t). The transfer mode to use for the transfer. Must select exactly one mode from [sl_btmesh_evt_mbt_client_query_information_complete_s.supported_transfer_modes](sl-btmesh-evt-mbt-client-query-information-complete-s#supported-transfer-modes).|

Initiate the BLOB transfer.

After receiving [sl_btmesh_evt_mbt_client_query_information_complete](sl-btmesh-evt-mbt-client-query-information-complete) event, the BLOB transfer should be initiated by this command. Each server's response is carried in a separate [sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status) event.

The [sl_btmesh_evt_mbt_client_start_transfer_complete](sl-btmesh-evt-mbt-client-start-transfer-complete) event indicates that all servers have responded to this command. If this is not received in a timely manner, the initiation request may be resent by calling this command again.

After the transfer start is successfully completed, the first block should be started with [sl_btmesh_mbt_client_start_block](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-block).

When the transfer is eventually complete, the [sl_btmesh_evt_mbt_client_transfer_complete](sl-btmesh-evt-mbt-client-transfer-complete) event is emitted.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status)
- [sl_btmesh_evt_mbt_client_start_transfer_complete](sl-btmesh-evt-mbt-client-start-transfer-complete)
- [sl_btmesh_evt_mbt_client_transfer_complete](sl-btmesh-evt-mbt-client-transfer-complete)

##### sl_btmesh_mbt_client_start_block

`sl_status_t sl_btmesh_mbt_client_start_block(uint16_t elem_index, uint16_t chunk_size, uint16_t *block_number, uint32_t *block_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint16_t|[in]|chunk_size|The block is divided into chunks of this size. The chunk size has to be large enough so that the number of chunks in which a block gets divided doesn't exceed any server's maximum, see [sl_btmesh_evt_mbt_client_query_information_complete_s::max_chunks_min](sl-btmesh-evt-mbt-client-query-information-complete-s#max-chunks-min). Range: 1 - 241.|
|uint16_t *|[out]|block_number|The index number of the block.|
|uint32_t *|[out]|block_size|The size of the block.|

Initiate block start.

After receiving [sl_btmesh_evt_mbt_client_start_transfer_complete](sl-btmesh-evt-mbt-client-start-transfer-complete) event in the beginning of the transfer, or [sl_btmesh_evt_mbt_client_query_block_status_complete](sl-btmesh-evt-mbt-client-query-block-status-complete) event indicating the previous block is complete, the next incomplete block should be started by this command. Each server's response is carried in in a separate [sl_btmesh_evt_mbt_client_server_block_status](sl-btmesh-evt-mbt-client-server-block-status) event.

The [sl_btmesh_evt_mbt_client_start_block_complete](sl-btmesh-evt-mbt-client-start-block-complete) event indicates that all servers have responded to this command. If this is not received in a timely manner, the initiation request may be resent by calling this command again.

After the block start is successfully completed, the MBT Client starts sending chunks to the servers. The data to send is requested from the application via [sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request) events.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_client_server_block_status](sl-btmesh-evt-mbt-client-server-block-status)
- [sl_btmesh_evt_mbt_client_start_block_complete](sl-btmesh-evt-mbt-client-start-block-complete)
- [sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request)

##### sl_btmesh_mbt_client_send_chunk_request_rsp

`sl_status_t sl_btmesh_mbt_client_send_chunk_request_rsp(uint16_t elem_index, size_t data_len, const uint8_t *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|size_t|[in]|data_len|Length of data in `data`|
|const uint8_t *|[in]|data|The chunk data.|

Provide requested chunk data.

This command is used to provide the chunk data requested by the MBT Client in a [sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_query_block_status

`sl_status_t sl_btmesh_mbt_client_query_block_status(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|

Query the current block status.

After receiving [sl_btmesh_evt_mbt_client_send_chunks_complete](sl-btmesh-evt-mbt-client-send-chunks-complete), the block statuses of the MBT Servers should be queried to determine if any chunks are still missing. Each server's response is carried in a separate [sl_btmesh_evt_mbt_client_server_block_status](sl-btmesh-evt-mbt-client-server-block-status) event.

The [sl_btmesh_evt_mbt_client_query_block_status_complete](sl-btmesh-evt-mbt-client-query-block-status-complete) event indicates that all servers have responded to this command. If this is not received in a timely manner, the block status query may be resent by calling this command again.

After the block status query is successfully completed, but some servers still have chunks missing, the MBT Client starts resending those automatically. See [sl_btmesh_evt_mbt_client_query_block_status_complete](sl-btmesh-evt-mbt-client-query-block-status-complete) for more information.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_client_server_block_status](sl-btmesh-evt-mbt-client-server-block-status)
- [sl_btmesh_evt_mbt_client_query_block_status_complete](sl-btmesh-evt-mbt-client-query-block-status-complete)
- [sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request)

##### sl_btmesh_mbt_client_get_status

`sl_status_t sl_btmesh_mbt_client_get_status(uint16_t elem_index, uint8_t *state, uint16_t *total_blocks, uint16_t *total_chunks)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint8_t *|[out]|state|The current client state<br/><br/>- 0 = inactive<br/>- 1 = transfer set up, ready to start<br/>- 2 = collecting server info<br/>- 3 = sending transfer start to servers<br/>- 4 = sending block start to servers<br/>- 5 = sending chunks to servers<br/>- 6 = querying received chunk statuses from servers<br/>- 7 = transfer complete (successfully, unsuccessfully, or partially successfully)|
|uint16_t *|[out]|total_blocks|Total number of BLOB Transfer blocks.|
|uint16_t *|[out]|total_chunks|Total number of BLOB Transfer chunks within the current block, 0 if there's no active Block.|

Get the status of the current transfer.

This command returns the MBT Client's current state and the status of each server in the current transfer.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_client_get_transfer_status

`sl_status_t sl_btmesh_mbt_client_get_transfer_status(uint16_t elem_index, uint16_t server_address, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|uint16_t|[in]|server_address|The MBT Server address. May also be a group or virtual address.|
|[uuid_128](uuid-128)|[in]|virtual_address|If the server address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|

Get the transfer status of an MBT Server.

This command can be used to check whether an MBT Server (or several, if a group address is used) is already taking part in a transfer. This command does not need to be used when executing a transfer.

The [sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status) event contains the status response received from the server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status)

##### sl_btmesh_mbt_client_cancel_transfer

`sl_status_t sl_btmesh_mbt_client_cancel_transfer(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|

Cancel a transfer.

This command may be used to cancel a transfer at any point after it has been set up with the [sl_btmesh_mbt_client_setup](sl-btmesh-mbt-client#sl-btmesh-mbt-client-setup) command. Each server's response is carried in a separate [sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status) event.

The [sl_btmesh_evt_mbt_client_transfer_complete](sl-btmesh-evt-mbt-client-transfer-complete) event indicates that all servers have responded to the cancellation. If this is not received in a timely manner, the cancellation may be retried by calling this command again.

After the transfer is successfully canceled, a new transfer may be set up with the [sl_btmesh_mbt_client_setup](sl-btmesh-mbt-client#sl-btmesh-mbt-client-setup) command.

It's also possible to use this for canceling a previous transfer on a list of MBT Servers in order to start a new one. In this case, the cancel would be issued right after setting up the transfer with the ID of the BLOB to be canceled.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_client_server_transfer_status](sl-btmesh-evt-mbt-client-server-transfer-status)
- [sl_btmesh_evt_mbt_client_transfer_complete](sl-btmesh-evt-mbt-client-transfer-complete)

##### sl_btmesh_mbt_client_abort

`sl_status_t sl_btmesh_mbt_client_abort(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|

Abort a previously set up BLOB transfer.

Abort a transfer and clear the Client's state. Note that this function does not inform the Servers that the Client has aborted the transfer.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_mbt_client_init_id 0x09280028`

`#define sl_btmesh_cmd_mbt_client_deinit_id 0x07280028`

`#define sl_btmesh_cmd_mbt_client_setup_id 0x00280028`

`#define sl_btmesh_cmd_mbt_client_query_information_id 0x01280028`

`#define sl_btmesh_cmd_mbt_client_get_server_status_id 0x0d280028`

`#define sl_btmesh_cmd_mbt_client_add_server_id 0x0e280028`

`#define sl_btmesh_cmd_mbt_client_configure_throttle_id 0x0f280028`

`#define sl_btmesh_cmd_mbt_client_start_transfer_id 0x02280028`

`#define sl_btmesh_cmd_mbt_client_start_block_id 0x03280028`

`#define sl_btmesh_cmd_mbt_client_send_chunk_request_rsp_id 0x04280028`

`#define sl_btmesh_cmd_mbt_client_query_block_status_id 0x05280028`

`#define sl_btmesh_cmd_mbt_client_get_status_id 0x06280028`

`#define sl_btmesh_cmd_mbt_client_get_transfer_status_id 0x0a280028`

`#define sl_btmesh_cmd_mbt_client_cancel_transfer_id 0x0b280028`

`#define sl_btmesh_cmd_mbt_client_abort_id 0x0c280028`

`#define sl_btmesh_rsp_mbt_client_init_id 0x09280028`

`#define sl_btmesh_rsp_mbt_client_deinit_id 0x07280028`

`#define sl_btmesh_rsp_mbt_client_setup_id 0x00280028`

`#define sl_btmesh_rsp_mbt_client_query_information_id 0x01280028`

`#define sl_btmesh_rsp_mbt_client_get_server_status_id 0x0d280028`

`#define sl_btmesh_rsp_mbt_client_add_server_id 0x0e280028`

`#define sl_btmesh_rsp_mbt_client_configure_throttle_id 0x0f280028`

`#define sl_btmesh_rsp_mbt_client_start_transfer_id 0x02280028`

`#define sl_btmesh_rsp_mbt_client_start_block_id 0x03280028`

`#define sl_btmesh_rsp_mbt_client_send_chunk_request_rsp_id 0x04280028`

`#define sl_btmesh_rsp_mbt_client_query_block_status_id 0x05280028`

`#define sl_btmesh_rsp_mbt_client_get_status_id 0x06280028`

`#define sl_btmesh_rsp_mbt_client_get_transfer_status_id 0x0a280028`

`#define sl_btmesh_rsp_mbt_client_cancel_transfer_id 0x0b280028`

`#define sl_btmesh_rsp_mbt_client_abort_id 0x0c280028`

#### sl_btmesh_evt_mbt_client_server_information_status

MBT Server information. 

MBT Server information received as a response to the [sl_btmesh_mbt_client_query_information](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-information) command. 

##### Modules

[sl_btmesh_evt_mbt_client_server_information_status_s](sl-btmesh-evt-mbt-client-server-information-status-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_server_information_status_t

`typedef struct sl_btmesh_evt_mbt_client_server_information_status_s sl_btmesh_evt_mbt_client_server_information_status_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_server_information_status_id 0x002800a8`

**Description**: Identifier of the server_information_status event.

Data structure of the server_information_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_information_status_s::elem_index
```

**Details:** The client model element index.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_information_status_s::server_address
```

**Details:** The MBT Server address.

###### min_block_size_log (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_information_status_s::min_block_size_log
```

**Details:** The minimum supported block size as an exponent n in 2^n.

###### max_block_size_log (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_information_status_s::max_block_size_log
```

**Details:** The maximum supported block size as an exponent n in 2^n.

###### max_chunks (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_information_status_s::max_chunks
```

**Details:** The maximum number of chunks supported.

###### max_chunk_size (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_information_status_s::max_chunk_size
```

**Details:** The maximum supported chunk size.

#### sl_btmesh_evt_mbt_client_query_information_complete

Query MBT Server information is complete. 

All active servers have responded to the information query. The common values supported by all servers are contained in this event for convenience.

Note that if no common block size values are supported by all servers, the `block_size_log_min` will be larger than the `block_size_log_max`. In such case, the application should select a block size that is supported by as many servers as possible based on the [sl_btmesh_evt_mbt_client_server_information_status](sl-btmesh-evt-mbt-client-server-information-status) events received for each server. Another option is to select either `block_size_log_min` or `block_size_log_max` as is, which are both guaranteed to be supported by at least one server.

The BLOB transfer should be initiated next with [sl_btmesh_mbt_client_start_transfer](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-transfer). 

##### Modules

[sl_btmesh_evt_mbt_client_query_information_complete_s](sl-btmesh-evt-mbt-client-query-information-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_query_information_complete_t

`typedef struct sl_btmesh_evt_mbt_client_query_information_complete_s sl_btmesh_evt_mbt_client_query_information_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_query_information_complete_id 0x042800a8`

**Description**: Identifier of the query_information_complete event.

Data structure of the query_information_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_query_information_complete_s::elem_index
```

**Details:** The client model element index.

###### block_size_log_min (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_query_information_complete_s::block_size_log_min
```

**Details:** The minimum block size supported by all servers as an exponent n in 2^n.

###### block_size_log_max (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_query_information_complete_s::block_size_log_max
```

**Details:** The maximum block size supported by all servers as an exponent n in 2^n.

###### max_chunk_size_min (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_query_information_complete_s::max_chunk_size_min
```

**Details:** The maximum chunk size supported by all servers.

###### max_chunks_min (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_query_information_complete_s::max_chunks_min
```

**Details:** The maximum number of chunks supported by all servers.

###### supported_transfer_modes (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_query_information_complete_s::supported_transfer_modes
```

**Details:** Enum [sl_btmesh_mbt_client_transfer_mode_t](sl-btmesh-mbt-client#sl-btmesh-mbt-client-transfer-mode-t). Transfer modes supported by at least one server and the client.

###### common_transfer_modes (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_query_information_complete_s::common_transfer_modes
```

**Details:** Enum [sl_btmesh_mbt_client_transfer_mode_t](sl-btmesh-mbt-client#sl-btmesh-mbt-client-transfer-mode-t). Transfer modes supported by all servers and the client.

#### sl_btmesh_evt_mbt_client_server_transfer_status

The MBT Server's current transfer status. 

This event contains the current transfer status received from a MBT Server. The status is received as a response to [sl_btmesh_mbt_client_start_transfer](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-transfer) or [sl_btmesh_mbt_client_get_transfer_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-get-transfer-status) commands. 

##### Modules

[sl_btmesh_evt_mbt_client_server_transfer_status_s](sl-btmesh-evt-mbt-client-server-transfer-status-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_server_transfer_status_t

`typedef struct sl_btmesh_evt_mbt_client_server_transfer_status_s sl_btmesh_evt_mbt_client_server_transfer_status_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_server_transfer_status_id 0x012800a8`

**Description**: Identifier of the server_transfer_status event.

Data structure of the server_transfer_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_transfer_status_s::elem_index
```

**Details:** The client model element index.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_transfer_status_s::server_address
```

**Details:** The MBT Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_transfer_status_s::status
```

**Details:** The status code for the last operation.

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_transfer_status_s::phase
```

**Details:** The MBT Server phase.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_mbt_client_server_transfer_status_s::blob_id
```

**Details:** The ID of the BLOB.

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_client_server_transfer_status_s::blob_size
```

**Details:** The size of the BLOB.

###### block_size_log (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_transfer_status_s::block_size_log
```

**Details:** The block size as an exponent n in 2^n.

###### blocks_not_received (heading level 7)

```
uint8array sl_btmesh_evt_mbt_client_server_transfer_status_s::blocks_not_received
```

**Details:** A bitfield indicating blocks which are not yet received. The least significant bit of the first byte in the array belongs to block zero.

#### sl_btmesh_evt_mbt_client_start_transfer_complete

Transfer start is complete. 

All active servers have responded to the transfer start command. The first block start should be initiated with [sl_btmesh_mbt_client_start_block](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-block). 

##### Modules

[sl_btmesh_evt_mbt_client_start_transfer_complete_s](sl-btmesh-evt-mbt-client-start-transfer-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_start_transfer_complete_t

`typedef struct sl_btmesh_evt_mbt_client_start_transfer_complete_s sl_btmesh_evt_mbt_client_start_transfer_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_start_transfer_complete_id 0x052800a8`

**Description**: Identifier of the start_transfer_complete event.

Data structure of the start_transfer_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_start_transfer_complete_s::elem_index
```

**Details:** The client model element index.

#### sl_btmesh_evt_mbt_client_server_block_status

The MBT Server's current block status. 

This event contains the current block status received from a MBT Server. The status is received as a response to [sl_btmesh_mbt_client_start_block](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-block) or [sl_btmesh_mbt_client_query_block_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-block-status) commands. 

##### Modules

[sl_btmesh_evt_mbt_client_server_block_status_s](sl-btmesh-evt-mbt-client-server-block-status-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_server_block_status_t

`typedef struct sl_btmesh_evt_mbt_client_server_block_status_s sl_btmesh_evt_mbt_client_server_block_status_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_server_block_status_id 0x032800a8`

**Description**: Identifier of the server_block_status event.

Data structure of the server_block_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_block_status_s::elem_index
```

**Details:** The client model element index.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_block_status_s::server_address
```

**Details:** The MBT Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_block_status_s::status
```

**Details:** The status code for the last operation.

###### missing_chunks (heading level 7)

```
uint8array sl_btmesh_evt_mbt_client_server_block_status_s::missing_chunks
```

**Details:** A bitfield indicating missing chunks. The least significant bit of the first byte in the array belongs to chunk zero.

#### sl_btmesh_evt_mbt_client_start_block_complete

Block start is complete. 

All active servers have responded to the block start command. 

##### Modules

[sl_btmesh_evt_mbt_client_start_block_complete_s](sl-btmesh-evt-mbt-client-start-block-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_start_block_complete_t

`typedef struct sl_btmesh_evt_mbt_client_start_block_complete_s sl_btmesh_evt_mbt_client_start_block_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_start_block_complete_id 0x062800a8`

**Description**: Identifier of the start_block_complete event.

Data structure of the start_block_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_start_block_complete_s::elem_index
```

**Details:** The client model element index.

###### block_number (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_start_block_complete_s::block_number
```

**Details:** The index number of the block.

###### block_size (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_client_start_block_complete_s::block_size
```

**Details:** The size of the block.

#### sl_btmesh_evt_mbt_client_send_chunk_request

Request for chunk data. 

The data for the next chunk to be sent is requested from the application. The requested data should be provided with the [sl_btmesh_mbt_client_send_chunk_request_rsp](sl-btmesh-mbt-client#sl-btmesh-mbt-client-send-chunk-request-rsp) command. 

##### Modules

[sl_btmesh_evt_mbt_client_send_chunk_request_s](sl-btmesh-evt-mbt-client-send-chunk-request-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_send_chunk_request_t

`typedef struct sl_btmesh_evt_mbt_client_send_chunk_request_s sl_btmesh_evt_mbt_client_send_chunk_request_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_send_chunk_request_id 0x072800a8`

**Description**: Identifier of the send_chunk_request event.

Data structure of the send_chunk_request event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_send_chunk_request_s::elem_index
```

**Details:** The client model element index.

###### offset (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_client_send_chunk_request_s::offset
```

**Details:** The chunk offset from the beginning of the BLOB.

###### length (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_send_chunk_request_s::length
```

**Details:** The number of bytes requested.

#### sl_btmesh_evt_mbt_client_server_partial_block_report

The MBT Server's partial block report. 

When the BLOB is transferred using the Pull BLOB Transfer mode, the MBT Server requests chunks from the MBT Client by sending Partial Block Report messages. The `missing_chunks` field indicates which chunks were requested. If no bits are set in `missing_chunks`, then the MBT Server has received all chunks of the current block.

The MBT Client starts sending the requested chunks to the server. The chunk data is requested from the application via the [sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request) events. 

##### Modules

[sl_btmesh_evt_mbt_client_server_partial_block_report_s](sl-btmesh-evt-mbt-client-server-partial-block-report-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_server_partial_block_report_t

`typedef struct sl_btmesh_evt_mbt_client_server_partial_block_report_s sl_btmesh_evt_mbt_client_server_partial_block_report_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_server_partial_block_report_id 0x0c2800a8`

**Description**: Identifier of the server_partial_block_report event.

Data structure of the server_partial_block_report event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_partial_block_report_s::elem_index
```

**Details:** The client model element index.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_partial_block_report_s::server_address
```

**Details:** The MBT Server address.

###### missing_chunks (heading level 7)

```
uint8array sl_btmesh_evt_mbt_client_server_partial_block_report_s::missing_chunks
```

**Details:** A bitfield indicating missing chunks. The least significant bit of the first byte in the array belongs to chunk zero.

#### sl_btmesh_evt_mbt_client_send_chunks_complete

All chunks in the current block have been sent. 

Each block is transferred in chunks, sending the chunks to the servers which have them missing. This event indicates that a single round of sending those chunks is complete.

After receiving this event, the block status should be queried from the servers with the [sl_btmesh_mbt_client_query_block_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-query-block-status) command. 

##### Modules

[sl_btmesh_evt_mbt_client_send_chunks_complete_s](sl-btmesh-evt-mbt-client-send-chunks-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_send_chunks_complete_t

`typedef struct sl_btmesh_evt_mbt_client_send_chunks_complete_s sl_btmesh_evt_mbt_client_send_chunks_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_send_chunks_complete_id 0x082800a8`

**Description**: Identifier of the send_chunks_complete event.

Data structure of the send_chunks_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_send_chunks_complete_s::elem_index
```

**Details:** The client model element index.

#### sl_btmesh_evt_mbt_client_query_block_status_complete

Querying the current block status is complete. 

All active servers have responded to the block status query. If the `transfer_complete` is non-zero, all blocks of the BLOB have been successfully transmitted and the transfer is complete. The MBT Client state is cleaned up and a new transfer may be started.

If the transfer is not complete, but the `block_complete` is non-zero, the current block is successfully transmitted and the next block should be started with [sl_btmesh_mbt_client_start_block](sl-btmesh-mbt-client#sl-btmesh-mbt-client-start-block) command. If the `block_complete` is zero, some servers still have chunks missing in the current block. The MBT client starts resending those automatically, requesting the data to send again from the application via [sl_btmesh_evt_mbt_client_send_chunk_request](sl-btmesh-evt-mbt-client-send-chunk-request) events. 

##### Modules

[sl_btmesh_evt_mbt_client_query_block_status_complete_s](sl-btmesh-evt-mbt-client-query-block-status-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_query_block_status_complete_t

`typedef struct sl_btmesh_evt_mbt_client_query_block_status_complete_s sl_btmesh_evt_mbt_client_query_block_status_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_query_block_status_complete_id 0x092800a8`

**Description**: Identifier of the query_block_status_complete event.

Data structure of the query_block_status_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_query_block_status_complete_s::elem_index
```

**Details:** The client model element index.

###### block_complete (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_query_block_status_complete_s::block_complete
```

**Details:** Non-zero if the block is complete.

###### transfer_complete (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_query_block_status_complete_s::transfer_complete
```

**Details:** Non-zero if the transfer is complete.

#### sl_btmesh_evt_mbt_client_tx_complete

Previous command has been transmitted to all recipients. 

When the previous command has been transmitted to all MBT Servers, either multicasting or unicasting to each server one by one, this event indicates that the whole transmission is completed. It may be used for timing retries, in case all servers do not respond within an expected time after this event. 

##### Modules

[sl_btmesh_evt_mbt_client_tx_complete_s](sl-btmesh-evt-mbt-client-tx-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_tx_complete_t

`typedef struct sl_btmesh_evt_mbt_client_tx_complete_s sl_btmesh_evt_mbt_client_tx_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_tx_complete_id 0x0a2800a8`

**Description**: Identifier of the tx_complete event.

Data structure of the tx_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_tx_complete_s::elem_index
```

**Details:** The client model element index.

#### sl_btmesh_evt_mbt_client_server_failed

A server failed and was removed from the transfer. 

This event indicates that a server timed out or reported an irrecoverable error. A failed server is removed from the transfer. 

##### Modules

[sl_btmesh_evt_mbt_client_server_failed_s](sl-btmesh-evt-mbt-client-server-failed-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_server_failed_t

`typedef struct sl_btmesh_evt_mbt_client_server_failed_s sl_btmesh_evt_mbt_client_server_failed_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_server_failed_id 0x0b2800a8`

**Description**: Identifier of the server_failed event.

Data structure of the server_failed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_failed_s::elem_index
```

**Details:** The client model element index.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_server_failed_s::server_address
```

**Details:** The MBT Server address.

###### timeout (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_failed_s::timeout
```

**Details:** Non-zero if a timeout occurred.

###### error (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_client_server_failed_s::error
```

**Details:** Non-zero if an error occurred.

#### sl_btmesh_evt_mbt_client_transfer_complete

The transfer is complete. 

This event indicates that the transfer is complete, either successfully or unsuccessfully. Servers which have failed before the transfer is complete, indicated by [sl_btmesh_evt_mbt_client_server_failed](sl-btmesh-evt-mbt-client-server-failed) event, have failed to receive the full object. All other servers have received the full object successfully. The [sl_btmesh_mbt_client_get_status](sl-btmesh-mbt-client#sl-btmesh-mbt-client-get-status) command may be used to get the current status of each server to determine if the transfer to a specific server succeeded or not. Servers which successfully completed the transfer are marked with status done. 

##### Modules

[sl_btmesh_evt_mbt_client_transfer_complete_s](sl-btmesh-evt-mbt-client-transfer-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_client_transfer_complete_t

`typedef struct sl_btmesh_evt_mbt_client_transfer_complete_s sl_btmesh_evt_mbt_client_transfer_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_client_transfer_complete_id 0x0d2800a8`

**Description**: Identifier of the transfer_complete event.

Data structure of the transfer_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_client_transfer_complete_s::elem_index
```

**Details:** The client model element index.

### Bluetooth Mesh BLOB Transfer Server Model

Bluetooth Mesh BLOB Transfer Server Model. 

The Bluetooth Mesh BLOB Transfer (MBT) Server model is used to receive binary large objects (BLOBs) over a Bluetooth Mesh network from a MBT Client.

There are two different modes in which the transfer may be performed: Push BLOB Transfer mode and Pull BLOB Transfer mode. The MBT Server may support both, or only one of these modes. The MBT Server API usage flow is identical in both transfer modes.

A Low Power Node (LPN) typically only supports the Pull BLOB Transfer mode, as that mode makes it possible for the MBT Server to throttle the transfer speed. This is necessary for ensuring that no more chunks than the Friend node can store in its Friend Queue are transmitted at once. While an LPN is receiving a transfer, the application needs to make sure that messages are polled from the Friend node at least every 30 seconds. If the LPN's Poll Timeout is larger than this, the application may call [sl_btmesh_lpn_poll](sl-btmesh-lpn#sl-btmesh-lpn-poll) to satisfy this requirement.

The MBT Server model is normally used as a transport in a higher-layer model, e.g., the Firmware Update models. Please refer to the documentation of such a model for more information on how to interact with the MBT Server API in that context. 

#### Modules

[sl_btmesh_evt_mbt_server_state_changed](sl-btmesh-evt-mbt-server-state-changed)

[sl_btmesh_evt_mbt_server_transfer_start_req](sl-btmesh-evt-mbt-server-transfer-start-req)

[sl_btmesh_evt_mbt_server_block_start](sl-btmesh-evt-mbt-server-block-start)

[sl_btmesh_evt_mbt_server_chunk](sl-btmesh-evt-mbt-server-chunk)

[sl_btmesh_evt_mbt_server_block_complete](sl-btmesh-evt-mbt-server-block-complete)

[sl_btmesh_evt_mbt_server_transfer_cancel](sl-btmesh-evt-mbt-server-transfer-cancel)

[sl_btmesh_evt_mbt_server_partial_block_report_tx_complete](sl-btmesh-evt-mbt-server-partial-block-report-tx-complete)

#### Enumerations

##### sl_btmesh_mbt_server_status_t

```
enum sl_btmesh_mbt_server_status_t {
    sl_btmesh_mbt_server_status_success = 0x0
    sl_btmesh_mbt_server_status_invalid_block_number = 0x1
    sl_btmesh_mbt_server_status_wrong_block_size = 0x2
    sl_btmesh_mbt_server_status_wrong_chunk_size = 0x3
    sl_btmesh_mbt_server_status_invalid_state = 0x4
    sl_btmesh_mbt_server_status_invalid_parameter = 0x5
    sl_btmesh_mbt_server_status_wrong_object_id = 0x6
    sl_btmesh_mbt_server_status_storage_limit = 0x7
    sl_btmesh_mbt_server_status_unsupported_transfer_mode = 0x8
    sl_btmesh_mbt_server_status_internal_error = 0x9
    sl_btmesh_mbt_server_status_information_unavailable = 0xa
    sl_btmesh_mbt_server_status_malformed_message = 0xfe
    sl_btmesh_mbt_server_status_timeout = 0xff
}
```

**Description:**

The MBT Status codes.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_mbt_server_status_success|(0x0) The Client message was successfully received by the Server.|
|sl_btmesh_mbt_server_status_invalid_block_number|(0x1) The Block number is higher than the total number of blocks indicates.|
|sl_btmesh_mbt_server_status_wrong_block_size|(0x2) The Block Size is outside of the boundaries specified by the Server's Min and Max Block Size Log capabilities.|
|sl_btmesh_mbt_server_status_wrong_chunk_size|(0x3) The Chunk Size is too large for the Server to accept, or so small that the Block's total chunks number would exceed the Server's Max Chunks capability.|
|sl_btmesh_mbt_server_status_invalid_state|(0x4) The Server is in a state where it cannot process the message.|
|sl_btmesh_mbt_server_status_invalid_parameter|(0x5) A parameter in the message is outside of its valid range.|
|sl_btmesh_mbt_server_status_wrong_object_id|(0x6) The Server is not expecting to receive this BLOB ID.|
|sl_btmesh_mbt_server_status_storage_limit|(0x7) Not enough space to store the BLOB.|
|sl_btmesh_mbt_server_status_unsupported_transfer_mode|(0x8) Transfer Mode not supported.|
|sl_btmesh_mbt_server_status_internal_error|(0x9) Internal error occurred.|
|sl_btmesh_mbt_server_status_information_unavailable|(0xa) The requested information is not available. A Block Get was sent, but no Block is active.|
|sl_btmesh_mbt_server_status_malformed_message|(0xfe) A malformed message was received.|
|sl_btmesh_mbt_server_status_timeout|(0xff) Timeout occurred.|

##### sl_btmesh_mbt_server_phase_t

```
enum sl_btmesh_mbt_server_phase_t {
    sl_btmesh_mbt_server_phase_inactive = 0x0
    sl_btmesh_mbt_server_phase_idle = 0x1
    sl_btmesh_mbt_server_phase_waiting_for_block = 0x2
    sl_btmesh_mbt_server_phase_waiting_for_chunks = 0x3
    sl_btmesh_mbt_server_phase_complete = 0x4
    sl_btmesh_mbt_server_phase_suspended = 0x5
}
```

**Description:**

The MBT Server Phase.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_mbt_server_phase_inactive|(0x0) The Server has not been given a BLOB ID to expect.|
|sl_btmesh_mbt_server_phase_idle|(0x1) The Server has a BLOB ID to expect, but is not (yet) receiving the BLOB.|
|sl_btmesh_mbt_server_phase_waiting_for_block|(0x2) The Server is waiting for the next Block Start message.|
|sl_btmesh_mbt_server_phase_waiting_for_chunks|(0x3) The Server is waiting for Chunk messages.|
|sl_btmesh_mbt_server_phase_complete|(0x4) The Server has received the full BLOB.|
|sl_btmesh_mbt_server_phase_suspended|(0x5) The Server has timed out and gone to Suspended phase.|

#### Functions

##### sl_btmesh_mbt_server_init

`sl_status_t sl_btmesh_mbt_server_init(uint16_t elem_index, uint8_t min_block_size_log, uint8_t max_block_size_log, uint16_t max_chunks_per_block, uint16_t max_chunk_size, uint32_t max_blob_size, uint8_t supported_transfer_modes, uint16_t pull_mode_chunks_to_request, uint16_t pull_mode_retry_interval_ms, uint16_t pull_mode_retry_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|uint8_t|[in]|min_block_size_log|The minimum supported block size as an exponent n in 2^n. Range: 6 - 32.|
|uint8_t|[in]|max_block_size_log|The maximum supported block size as an exponent n in 2^n. Must be less than or equal to `max_chunks_per_block * max_chunk_size`. Range: 6 - 32.|
|uint16_t|[in]|max_chunks_per_block|The maximum number of chunks into which a block can be broken down.|
|uint16_t|[in]|max_chunk_size|The maximum supported chunk size. Range: 8 - 241.|
|uint32_t|[in]|max_blob_size|The maximum supported BLOB size.|
|uint8_t|[in]|supported_transfer_modes|A bitfield of supported transfer modes. At least one must be supported.<br/><br/>- Bit 0: Push BLOB Transfer mode<br/>- Bit 1: Pull BLOB Transfer mode|
|uint16_t|[in]|pull_mode_chunks_to_request|In Pull BLOB Transfer mode, how many chunks to request at a time. Can be set to zero if this transfer mode is not supported.|
|uint16_t|[in]|pull_mode_retry_interval_ms|In Pull BLOB Transfer mode, retry requesting chunks with this interval in milliseconds. Can be set to zero if this transfer mode is not supported.|
|uint16_t|[in]|pull_mode_retry_count|In Pull BLOB Transfer mode, retry requesting chunks this many times before giving up. Note that if the timeout set by [sl_btmesh_mbt_server_start](sl-btmesh-mbt-server#sl-btmesh-mbt-server-start) occurs before the retry attempts are exhausted, no more retries will be attempted. Can be set to zero if this transfer mode is not supported.|

Initialize the MBT Server.

Note that the configuration parameters `min_block_size_log`, `max_chunks_per_block` and `max_blob_size` have memory usage implications. The server needs to store 1 bit of information per chunk, so every additional 8 chunks supported add 1 byte of RAM usage. Each potential block needs 1 bit of information, so the server must allocate 1 byte of RAM for every 8 potential blocks. Supporting small blocks and large objects, or large blocks and small chunks, will use more memory. The values should be chosen to conservatively satisfy the use cases of the node if RAM usage is of concern.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_deinit

`sl_status_t sl_btmesh_mbt_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|

De-initializes the MBT Client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_start

`sl_status_t sl_btmesh_mbt_server_start(uint16_t elem_index, sl_bt_uuid_64_t blob_id, uint16_t timeout_10s, uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t)|[in]|blob_id|The ID of the BLOB.|
|uint16_t|[in]|timeout_10s|If no messages are received from the MBT Client within this time frame, the transfer will be suspended.|
|uint8_t|[in]|ttl|The time-to-live value to use when communicating with the MBT Client. Valid values: 0, range:[2-127] and 255.|

Start receiving a BLOB.

This is used to declare a BLOB to the MBT Server for receiving. The `blob_id` identifies the expected BLOB. The MBT Server will wait for the MBT Client to start the transfer, which is indicated by [sl_btmesh_evt_mbt_server_transfer_start_req](sl-btmesh-evt-mbt-server-transfer-start-req).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_mbt_server_transfer_start_req](sl-btmesh-evt-mbt-server-transfer-start-req)

##### sl_btmesh_mbt_server_get_transfer_status

`sl_status_t sl_btmesh_mbt_server_get_transfer_status(uint16_t elem_index, uint8_t *state, sl_bt_uuid_64_t *blob_id, uint32_t *blob_size, uint16_t *block_number, size_t max_blocks_missing_mask_size, size_t *blocks_missing_mask_len, uint8_t *blocks_missing_mask)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|uint8_t *|[out]|state|The current state<br/><br/>- 0: Inactive, not expecting any transfer<br/>- 1: Waiting for the BLOB transfer to start<br/>- 2: Waiting for a new block to start<br/>- 3: Waiting for chunks of the current block<br/>- 4: The BLOB has been transferred successfully<br/>- 5: Timeout occurred and the transfer is suspended|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t) *|[out]|blob_id|The ID of the BLOB.|
|uint32_t *|[out]|blob_size|The size of the BLOB.|
|uint16_t *|[out]|block_number|The index number of the current block.|
|size_t|[in]|max_blocks_missing_mask_size|Size of output buffer passed in `blocks_missing_mask`|
|size_t *|[out]|blocks_missing_mask_len|On return, set to the length of output data written to `blocks_missing_mask`|
|uint8_t *|[out]|blocks_missing_mask|A bitfield indicating missing blocks. The least significant bit of the first byte in the array belongs to block zero.|

Get the status of the transfer.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_transfer_complete

`sl_status_t sl_btmesh_mbt_server_transfer_complete(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|

To be called when the transfer is completed. This is only needed when implementing your vendor model that uses MBT Server. The DFU models use this API internally.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_abort

`sl_status_t sl_btmesh_mbt_server_abort(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|

Abort the ongoing transfer, if any.

Abort a transfer and clear the Server's state. Note that this function does not inform the Client that the Server has aborted the transfer.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_set_pull_mode_parameters

`sl_status_t sl_btmesh_mbt_server_set_pull_mode_parameters(uint16_t elem_index, uint16_t pull_mode_retry_interval_ms, uint16_t pull_mode_retry_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|uint16_t|[in]|pull_mode_retry_interval_ms|The retry interval in milliseconds (ms).|
|uint16_t|[in]|pull_mode_retry_count|The retry count.|

Set the retry interval and the retry count parameters in the Pull BLOB Transfer Mode. The new values will take effect at the next transfer start. The command does not modify parameters of the ongoing transfer.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_transfer_start_rsp

`sl_status_t sl_btmesh_mbt_server_transfer_start_rsp(uint16_t elem_index, uint8_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|uint8_t|[in]|status|mesh_mbt_status_success to accept, mesh_mbt_status_internal_error and mesh_mbt_status_storage_limit to reject.|

Response to the [sl_btmesh_evt_mbt_server_transfer_start_req](sl-btmesh-evt-mbt-server-transfer-start-req) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_enable_block_start_req

`sl_status_t sl_btmesh_mbt_server_enable_block_start_req(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|

Enable the MBT Server block start request.

This changes the behavior of the [sl_btmesh_evt_mbt_server_block_start](sl-btmesh-evt-mbt-server-block-start) event, making it a request instead of a notification. If this is enabled, [sl_btmesh_mbt_server_block_start_rsp](sl-btmesh-mbt-server#sl-btmesh-mbt-server-block-start-rsp) must be called after receiving the event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_mbt_server_block_start_rsp

`sl_status_t sl_btmesh_mbt_server_block_start_rsp(uint16_t elem_index, uint8_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|uint8_t|[in]|status|[sl_btmesh_mbt_server_status_success](sl-btmesh-mbt-server#sl-btmesh-mbt-server-status-success) to accept, [sl_btmesh_mbt_server_status_internal_error](sl-btmesh-mbt-server#sl-btmesh-mbt-server-status-internal-error) to reject.|

Accept or reject an MBT Server block start request.

This command must be called after receiving the [sl_btmesh_evt_mbt_server_block_start](sl-btmesh-evt-mbt-server-block-start) event to accept or reject the block. If some preparation is needed for the block, e.g. erasing flash pages, those should be done before accepting the block. The block might also be rejected if implementation-specific errors occur.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_mbt_server_init_id 0x02290028`

`#define sl_btmesh_cmd_mbt_server_deinit_id 0x09290028`

`#define sl_btmesh_cmd_mbt_server_start_id 0x00290028`

`#define sl_btmesh_cmd_mbt_server_get_transfer_status_id 0x01290028`

`#define sl_btmesh_cmd_mbt_server_transfer_complete_id 0x03290028`

`#define sl_btmesh_cmd_mbt_server_abort_id 0x04290028`

`#define sl_btmesh_cmd_mbt_server_set_pull_mode_parameters_id 0x05290028`

`#define sl_btmesh_cmd_mbt_server_transfer_start_rsp_id 0x06290028`

`#define sl_btmesh_cmd_mbt_server_enable_block_start_req_id 0x07290028`

`#define sl_btmesh_cmd_mbt_server_block_start_rsp_id 0x08290028`

`#define sl_btmesh_rsp_mbt_server_init_id 0x02290028`

`#define sl_btmesh_rsp_mbt_server_deinit_id 0x09290028`

`#define sl_btmesh_rsp_mbt_server_start_id 0x00290028`

`#define sl_btmesh_rsp_mbt_server_get_transfer_status_id 0x01290028`

`#define sl_btmesh_rsp_mbt_server_transfer_complete_id 0x03290028`

`#define sl_btmesh_rsp_mbt_server_abort_id 0x04290028`

`#define sl_btmesh_rsp_mbt_server_set_pull_mode_parameters_id 0x05290028`

`#define sl_btmesh_rsp_mbt_server_transfer_start_rsp_id 0x06290028`

`#define sl_btmesh_rsp_mbt_server_enable_block_start_req_id 0x07290028`

`#define sl_btmesh_rsp_mbt_server_block_start_rsp_id 0x08290028`

#### sl_btmesh_evt_mbt_server_state_changed

The state of the MBT Server has changed. 

This event may be used by the application to determine the current state and progress of the transfer. 

##### Modules

[sl_btmesh_evt_mbt_server_state_changed_s](sl-btmesh-evt-mbt-server-state-changed-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_state_changed_t

`typedef struct sl_btmesh_evt_mbt_server_state_changed_s sl_btmesh_evt_mbt_server_state_changed_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_state_changed_id 0x062900a8`

**Description**: Identifier of the state_changed event.

Data structure of the state_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_state_changed_s::elem_index
```

**Details:** The server model element index.

###### new_state (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_server_state_changed_s::new_state
```

**Details:** The new state

- 0: Inactive, not expecting any transfer
- 1: Waiting for the BLOB transfer to start
- 2: Waiting for a new block to start
- 3: Waiting for chunks of the current block
- 4: The BLOB has been transferred successfully
- 5: Timeout occurred and the transfer is suspended

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_mbt_server_state_changed_s::blob_id
```

**Details:** The ID of the BLOB.

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_server_state_changed_s::blob_size
```

**Details:** The size of the BLOB.

###### block_number (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_state_changed_s::block_number
```

**Details:** The index number of the current block.

###### block_size (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_server_state_changed_s::block_size
```

**Details:** The size of the block.

###### chunk_size (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_state_changed_s::chunk_size
```

**Details:** The current block is divided into chunks of this size.

#### sl_btmesh_evt_mbt_server_transfer_start_req

The MBT Client has requested the transfer start. 

The command [sl_btmesh_mbt_server_transfer_start_rsp](sl-btmesh-mbt-server#sl-btmesh-mbt-server-transfer-start-rsp) must be called to accept or reject the transfer start request.

After the transfer has been started, the start of the first block is indicated by the [sl_btmesh_evt_mbt_server_block_start](sl-btmesh-evt-mbt-server-block-start) event. 

##### Modules

[sl_btmesh_evt_mbt_server_transfer_start_req_s](sl-btmesh-evt-mbt-server-transfer-start-req-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_transfer_start_req_t

`typedef struct sl_btmesh_evt_mbt_server_transfer_start_req_s sl_btmesh_evt_mbt_server_transfer_start_req_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_transfer_start_req_id 0x002900a8`

**Description**: Identifier of the transfer_start_req event.

Data structure of the transfer_start_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_transfer_start_req_s::elem_index
```

**Details:** The server model element index.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_transfer_start_req_s::client_address
```

**Details:** The address of the MBT Client.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_mbt_server_transfer_start_req_s::blob_id
```

**Details:** The ID of the BLOB.

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_server_transfer_start_req_s::blob_size
```

**Details:** The size of the BLOB.

###### block_size_log (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_server_transfer_start_req_s::block_size_log
```

**Details:** The block size as an exponent n in 2^n.

###### transfer_mode (heading level 7)

```
uint8_t sl_btmesh_evt_mbt_server_transfer_start_req_s::transfer_mode
```

**Details:** Transfer mode: 1 = Push Mode (client-driven), 2 = Pull Mode (server-driven).

#### sl_btmesh_evt_mbt_server_block_start

The transfer of a new block has started. 

If the block start request has been enabled with [sl_btmesh_mbt_server_enable_block_start_req](sl-btmesh-mbt-server#sl-btmesh-mbt-server-enable-block-start-req), the [sl_btmesh_mbt_server_block_start_rsp](sl-btmesh-mbt-server#sl-btmesh-mbt-server-block-start-rsp) command must be called to accept or reject the block. The new block starts immediately after it has been accepted.

After the new block has been started, the MBT Client starts sending the chunks of the block. The chunk data is carried in [sl_btmesh_evt_mbt_server_chunk](sl-btmesh-evt-mbt-server-chunk) events. When all chunks of the block have been successfully received, a [sl_btmesh_evt_mbt_server_block_complete](sl-btmesh-evt-mbt-server-block-complete) event is emitted. 

##### Modules

[sl_btmesh_evt_mbt_server_block_start_s](sl-btmesh-evt-mbt-server-block-start-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_block_start_t

`typedef struct sl_btmesh_evt_mbt_server_block_start_s sl_btmesh_evt_mbt_server_block_start_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_block_start_id 0x012900a8`

**Description**: Identifier of the block_start event.

Data structure of the block_start event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_start_s::elem_index
```

**Details:** The server model element index.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_start_s::client_address
```

**Details:** The address of the MBT Client.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_mbt_server_block_start_s::blob_id
```

**Details:** The ID of the BLOB.

###### block_number (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_start_s::block_number
```

**Details:** The index number of the new block.

###### chunk_size (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_start_s::chunk_size
```

**Details:** The new block is divided into chunks of this size.

###### block_size (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_start_s::block_size
```

**Details:** The size of the new block.

#### sl_btmesh_evt_mbt_server_chunk

Received a new chunk of BLOB data. 

Each chunk is delivered to the application with this event only once when it is first received. The offset of the chunk `data` relative to the whole BLOB is in `total_offset`, and relative to the current block in `block_offset`. 

##### Modules

[sl_btmesh_evt_mbt_server_chunk_s](sl-btmesh-evt-mbt-server-chunk-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_chunk_t

`typedef struct sl_btmesh_evt_mbt_server_chunk_s sl_btmesh_evt_mbt_server_chunk_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_chunk_id 0x032900a8`

**Description**: Identifier of the chunk event.

Data structure of the chunk event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_chunk_s::elem_index
```

**Details:** The server model element index.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_chunk_s::client_address
```

**Details:** The address of the MBT Client.

###### block_number (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_chunk_s::block_number
```

**Details:** The index number of the current block.

###### total_offset (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_server_chunk_s::total_offset
```

**Details:** The offset of the chunk in the BLOB.

###### block_offset (heading level 7)

```
uint32_t sl_btmesh_evt_mbt_server_chunk_s::block_offset
```

**Details:** The offset of the chunk in the current block.

###### data (heading level 7)

```
uint8array sl_btmesh_evt_mbt_server_chunk_s::data
```

**Details:** The chunk data.

#### sl_btmesh_evt_mbt_server_block_complete

The transfer of the current block is complete. 

If there are more blocks to transfer, a new block will be started by the MBT Client, indicated by the [sl_btmesh_evt_mbt_server_block_start](sl-btmesh-evt-mbt-server-block-start) event. Otherwise, the transfer completed successfully, and a [sl_btmesh_evt_mbt_server_state_changed](sl-btmesh-evt-mbt-server-state-changed) event with the proper `new_state` is emitted. 

##### Modules

[sl_btmesh_evt_mbt_server_block_complete_s](sl-btmesh-evt-mbt-server-block-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_block_complete_t

`typedef struct sl_btmesh_evt_mbt_server_block_complete_s sl_btmesh_evt_mbt_server_block_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_block_complete_id 0x042900a8`

**Description**: Identifier of the block_complete event.

Data structure of the block_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_complete_s::elem_index
```

**Details:** The server model element index.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_complete_s::client_address
```

**Details:** The address of the MBT Client.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_mbt_server_block_complete_s::blob_id
```

**Details:** The ID of the BLOB.

###### block_number (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_complete_s::block_number
```

**Details:** The index number of the completed block.

###### block_size (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_block_complete_s::block_size
```

**Details:** The size of the completed block.

#### sl_btmesh_evt_mbt_server_transfer_cancel

The MBT Client has canceled the transfer. 

##### Modules

[sl_btmesh_evt_mbt_server_transfer_cancel_s](sl-btmesh-evt-mbt-server-transfer-cancel-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_transfer_cancel_t

`typedef struct sl_btmesh_evt_mbt_server_transfer_cancel_s sl_btmesh_evt_mbt_server_transfer_cancel_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_transfer_cancel_id 0x072900a8`

**Description**: Identifier of the transfer_cancel event.

Data structure of the transfer_cancel event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_transfer_cancel_s::elem_index
```

**Details:** The server model element index.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_transfer_cancel_s::client_address
```

**Details:** The address of the MBT Client.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_mbt_server_transfer_cancel_s::blob_id
```

**Details:** The ID of the BLOB.

#### sl_btmesh_evt_mbt_server_partial_block_report_tx_complete

The MBT Server has sent partial block report. 

##### Modules

[sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_s](sl-btmesh-evt-mbt-server-partial-block-report-tx-complete-s)

##### Typedefs

###### sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_t

`typedef struct sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_s sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_t`

##### Macros

`#define sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_id 0x082900a8`

**Description**: Identifier of the partial_block_report_tx_complete event.

Data structure of the partial_block_report_tx_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_s::elem_index
```

**Details:** The server model element index.

###### num_requested_chunks (heading level 7)

```
uint16_t sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_s::num_requested_chunks
```

**Details:** Number of requested chunks.

###### requested_chunks (heading level 7)

```
uint8array sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_s::requested_chunks
```

**Details:** The array of requested chunks in little-endian uint16 format.

### Bluetooth Mesh Sensor Server Model

Bluetooth Mesh Sensor Server Model. 

This class provides the commands and messages to interface with the Sensor Server model.

A Sensor State consists of four states:

- Sensor Descriptor
- Sensor Setting
- Sensor Cadence
- Measurement value

A multisensor setup is possible by having multiple sensor states within the same model, provided that each sensor has a unique Sensor Property ID.

Sensor Descriptor states are constant. Therefore, the stack can cache them and enumerate the present sensors to clients when requested.

Currently, the Sensor Server model does not cache the measurement data, sensor settings, or cadence. When a client is querying sensor data, the requests will be propagated to the application. 

#### Modules

[sl_btmesh_evt_sensor_server_get_request](sl-btmesh-evt-sensor-server-get-request)

[sl_btmesh_evt_sensor_server_get_column_request](sl-btmesh-evt-sensor-server-get-column-request)

[sl_btmesh_evt_sensor_server_get_series_request](sl-btmesh-evt-sensor-server-get-series-request)

[sl_btmesh_evt_sensor_server_publish](sl-btmesh-evt-sensor-server-publish)

#### Functions

##### sl_btmesh_sensor_server_init

`sl_status_t sl_btmesh_sensor_server_init(uint16_t elem_index, size_t descriptors_len, const uint8_t *descriptors)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|size_t|[in]|descriptors_len|Length of data in `descriptors`|
|const uint8_t *|[in]|descriptors|Sensor Descriptor State structures submitted as a byte array<br/><br/>A sensor descriptor represents the attributes describing the sensor data. It does not change throughout the lifetime of the element.<br/><br/>The following fields are required:<br/><br/>- Sensor Property ID: 16 bits<br/>- Sensor Positive Tolerance: 12 bits<br/>- Sensor Negative Tolerance: 12 bits<br/>- Sensor Sampling Function: 8 bits<br/>- Sensor Measurement Period: 8 bits<br/>- Sensor Update Interval: 8 bits<br/><br/>Sensor Property ID is a 2-octet value referencing a device property that describes the meaning and the format of data reported by the sensor. The value 0x0000 is prohibited. Valid range is 0x0001 to 0xFFFF.|

Initialize the Sensor Server model with Sensor Descriptors present at the element. The descriptors are cached and Descriptor Get queries are served without propagating it to the application. All incoming client queries are checked against the cached data. However, only valid requests related to existing sensors are propagated to the the application.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_server_deinit

`sl_status_t sl_btmesh_sensor_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|

Deinitialize the Sensor Server functionality. Note that the heap reserved space cannot be freed or reallocated. Reinitializing with greater number of sensors than before will eventually return an out of memory error until the device is reset.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_server_send_descriptor_status

`sl_status_t sl_btmesh_sensor_server_send_descriptor_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, size_t descriptors_len, const uint8_t *descriptors)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|size_t|[in]|descriptors_len|Length of data in `descriptors`|
|const uint8_t *|[in]|descriptors|Serialized Sensor Descriptor states for all sensors within the element consisting one or more 8 bytes structures as follows:<br/><br/>- Sensor Property ID: 16 bits<br/>- Sensor Positive Tolerance: 12 bits<br/>- Sensor Negative Tolerance: 12 bits<br/>- Sensor Sampling Function: 8 bits<br/>- Sensor Measurement Period: 8 bits|

Send a Descriptor Status message either as a reply to a Get Descriptor client request.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_server_send_status

`sl_status_t sl_btmesh_sensor_server_send_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, size_t sensor_data_len, const uint8_t *sensor_data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Setup Server model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|No flags defined currently|
|size_t|[in]|sensor_data_len|Length of data in `sensor_data`|
|const uint8_t *|[in]|sensor_data|Serialized Sensor Data consisting of one or more Sensor state for each sensor within the element. To simplify processing, the byte array is in TLV format:<br/><br/>- 1st Property ID: 16 bits<br/>- Value Length: 8 bits<br/>- Value: variable<br/>- 2nd Property ID: 16 bits<br/>- Value Length: 8 bits<br/>- Value: variable<br/>- ...<br/><br/>If sensor data was requested for a Property ID that does not exist within the element, the reply must contain the given Property ID with zero length.|

Send Sensor Status message as a reply to a Get client request or as an unsolicited message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_server_send_column_status

`sl_status_t sl_btmesh_sensor_server_send_column_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t sensor_data_len, const uint8_t *sensor_data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|sensor_data_len|Length of data in `sensor_data`|
|const uint8_t *|[in]|sensor_data|Byte array containing the serialized Sensor Series Column state in the following format:<br/><br/>- Sensor Raw Value X, variable length raw value representing the left corner of a column<br/>- Sensor Column Width, variable length raw value representing the width of the column<br/>- Sensor Raw Value Y, variable length raw value representing the height of the column<br/><br/>If the Property ID or the column ID (Raw value X) does not exist, the reply must contain only these two fields, omitting the optional Column Width and Raw Value Y fields.|

Send Column Status message as a response to a Column Get client request or as an unsolicited message

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_server_send_series_status

`sl_status_t sl_btmesh_sensor_server_send_series_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t sensor_data_len, const uint8_t *sensor_data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|sensor_data_len|Length of data in `sensor_data`|
|const uint8_t *|[in]|sensor_data|Byte array containing the serialized sequence of Sensor Series Column states in the following format:<br/><br/>- 1st Sensor Raw Value X, variable length raw value representing the left corner of a column<br/>- 1st Sensor Column Width, variable length raw value representing the width of the column<br/>- 1st Sensor Raw Value Y, variable length raw value representing the height of the column<br/>- ...<br/>- Nth Sensor Raw Value X, variable length raw value representing the left corner of a column<br/>- Nth Sensor Column Width, variable length raw value representing the width of the column<br/>- Nth Sensor Raw Value Y, variable length raw value representing the height of the column<br/><br/>If Property ID does not exist in the element, the reply must contain only the given Property ID, omitting the other optional fields to column identifiers and column values.|

Send Series Status message as a response to a Series Get client request or as an unsolicited message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_sensor_server_init_id 0x00470028`

`#define sl_btmesh_cmd_sensor_server_deinit_id 0x01470028`

`#define sl_btmesh_cmd_sensor_server_send_descriptor_status_id 0x02470028`

`#define sl_btmesh_cmd_sensor_server_send_status_id 0x03470028`

`#define sl_btmesh_cmd_sensor_server_send_column_status_id 0x04470028`

`#define sl_btmesh_cmd_sensor_server_send_series_status_id 0x05470028`

`#define sl_btmesh_rsp_sensor_server_init_id 0x00470028`

`#define sl_btmesh_rsp_sensor_server_deinit_id 0x01470028`

`#define sl_btmesh_rsp_sensor_server_send_descriptor_status_id 0x02470028`

`#define sl_btmesh_rsp_sensor_server_send_status_id 0x03470028`

`#define sl_btmesh_rsp_sensor_server_send_column_status_id 0x04470028`

`#define sl_btmesh_rsp_sensor_server_send_series_status_id 0x05470028`

#### sl_btmesh_evt_sensor_server_get_request

Indicate an incoming Sensor Get request to get the Sensor Data state(s) 

This event must be replied to by sending the Sensor Status message. 

##### Modules

[sl_btmesh_evt_sensor_server_get_request_s](sl-btmesh-evt-sensor-server-get-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_server_get_request_t

`typedef struct sl_btmesh_evt_sensor_server_get_request_s sl_btmesh_evt_sensor_server_get_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_server_get_request_id 0x014700a8`

**Description**: Identifier of the get_request event.

Data structure of the get_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_request_s::server_address
```

**Details:** Destination server address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_request_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_request_s::client_address
```

**Details:** Source client address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_server_get_request_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, or 0x0000 to get the values of all sensors.

#### sl_btmesh_evt_sensor_server_get_column_request

Indicate an incoming Sensor Column Get message to get Sensor Series Column state. 

The event must be replied to by sending a Sensor Column Status message. 

##### Modules

[sl_btmesh_evt_sensor_server_get_column_request_s](sl-btmesh-evt-sensor-server-get-column-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_server_get_column_request_t

`typedef struct sl_btmesh_evt_sensor_server_get_column_request_s sl_btmesh_evt_sensor_server_get_column_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_server_get_column_request_id 0x024700a8`

**Description**: Identifier of the get_column_request event.

Data structure of the get_column_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_column_request_s::server_address
```

**Details:** Destination server address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_column_request_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_column_request_s::client_address
```

**Details:** Source client model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_column_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_server_get_column_request_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_column_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### column_ids (heading level 7)

```
uint8array sl_btmesh_evt_sensor_server_get_column_request_s::column_ids
```

**Details:** Raw value identifying a column

#### sl_btmesh_evt_sensor_server_get_series_request

Indicate an incoming Sensor Series Get message to get the Sensor Series Column states. 

This event must be replied to by sending a Sensor Series Status message. 

##### Modules

[sl_btmesh_evt_sensor_server_get_series_request_s](sl-btmesh-evt-sensor-server-get-series-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_server_get_series_request_t

`typedef struct sl_btmesh_evt_sensor_server_get_series_request_s sl_btmesh_evt_sensor_server_get_series_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_server_get_series_request_id 0x034700a8`

**Description**: Identifier of the get_series_request event.

Data structure of the get_series_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_series_request_s::server_address
```

**Details:** Destination server address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_series_request_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_series_request_s::client_address
```

**Details:** Source client address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_series_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_server_get_series_request_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_get_series_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### column_ids (heading level 7)

```
uint8array sl_btmesh_evt_sensor_server_get_series_request_s::column_ids
```

**Details:** Optional raw values identifying starting and ending columns

#### sl_btmesh_evt_sensor_server_publish

Indicate that the publishing period timer elapsed and the app should publish its state. 

##### Modules

[sl_btmesh_evt_sensor_server_publish_s](sl-btmesh-evt-sensor-server-publish-s)

##### Typedefs

###### sl_btmesh_evt_sensor_server_publish_t

`typedef struct sl_btmesh_evt_sensor_server_publish_s sl_btmesh_evt_sensor_server_publish_t`

##### Macros

`#define sl_btmesh_evt_sensor_server_publish_id 0x044700a8`

**Description**: Identifier of the publish event.

Data structure of the publish event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_server_publish_s::elem_index
```

**Details:** Client model element index

###### period_ms (heading level 7)

```
uint32_t sl_btmesh_evt_sensor_server_publish_s::period_ms
```

**Details:** The current publishing period that can be used to estimate the next tick, e.g., when the state should be reported at higher frequency.

### Bluetooth Mesh Sensor Setup Server Model

Bluetooth Mesh Sensor Setup Server Model. 

This class provides the commands and messages to interface with the Sensor Setup Server model. Elements containing sensor model must have a setup server model attached. Therefore, it is initialized/deinitialized internally together with the server model. 

#### Modules

[sl_btmesh_evt_sensor_setup_server_get_cadence_request](sl-btmesh-evt-sensor-setup-server-get-cadence-request)

[sl_btmesh_evt_sensor_setup_server_set_cadence_request](sl-btmesh-evt-sensor-setup-server-set-cadence-request)

[sl_btmesh_evt_sensor_setup_server_get_settings_request](sl-btmesh-evt-sensor-setup-server-get-settings-request)

[sl_btmesh_evt_sensor_setup_server_get_setting_request](sl-btmesh-evt-sensor-setup-server-get-setting-request)

[sl_btmesh_evt_sensor_setup_server_set_setting_request](sl-btmesh-evt-sensor-setup-server-set-setting-request)

[sl_btmesh_evt_sensor_setup_server_publish](sl-btmesh-evt-sensor-setup-server-publish)

#### Functions

##### sl_btmesh_sensor_setup_server_send_cadence_status

`sl_status_t sl_btmesh_sensor_setup_server_send_cadence_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t params_len, const uint8_t *params)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client address The address 0x0000 can be used to publish the message according model configuration instead of a direct reply.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|params_len|Length of data in `params`|
|const uint8_t *|[in]|params|Optional byte array containing the serialized Sensor Cadence state, excluding the property ID. If not empty, the state consists of the following fields:<br/><br/>- Fast Cadence Period Divisor, 7 bits<br/>- Status Trigger type, 1 bits (0 = discrete value, 1 = percentage)<br/>- Status Trigger Delta Down, variable length<br/>- Status Trigger Delta Up, variable length<br/>- Status Min Interval, 8 bits, representing a power of 2 milliseconds. Valid range is 0-26<br/>- Fast Cadence Low, variable length, lower bound for the fast cadence range<br/>- Low Cadence Low, variable length, higher bound for the fast cadence range|

Reply to a Get/Set Cadence client request with a Cadence Status message. Only Cadence Set (acknowledged) must be answered by sending the status message to the client. In addition, configuration changes must be published according to model publishing configuration.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_setup_server_send_settings_status

`sl_status_t sl_btmesh_sensor_setup_server_send_settings_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t setting_ids_len, const uint8_t *setting_ids)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|setting_ids_len|Length of data in `setting_ids`|
|const uint8_t *|[in]|setting_ids|Array of 16-bit Setting Property IDs of the settings the given sensor has|

Reply to a Get Settings client request with a Settings Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_setup_server_send_setting_status

`sl_status_t sl_btmesh_sensor_setup_server_send_setting_status(uint16_t client_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, uint16_t setting_id, size_t raw_value_len, const uint8_t *raw_value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|client_address|Destination client model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|uint16_t|[in]|setting_id|Sensor Setting Property ID field identifying the device property of a setting. Range: 0x0001 - 0xffff, 0x0000 is prohibited.|
|size_t|[in]|raw_value_len|Length of data in `raw_value`|
|const uint8_t *|[in]|raw_value|Sensor Setting raw value. Size and representation depends on the type defined by the Sensor Setting Property ID.|

Reply to a Get/Set Setting client request with a Setting Status message. Only Set Setting (acknowledged) request must be answered by sending a reply to the unicast address of the sender. In addition, configuration changes must be published if model publishing is set up.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_sensor_setup_server_send_cadence_status_id 0x00480028`

`#define sl_btmesh_cmd_sensor_setup_server_send_settings_status_id 0x01480028`

`#define sl_btmesh_cmd_sensor_setup_server_send_setting_status_id 0x02480028`

`#define sl_btmesh_rsp_sensor_setup_server_send_cadence_status_id 0x00480028`

`#define sl_btmesh_rsp_sensor_setup_server_send_settings_status_id 0x01480028`

`#define sl_btmesh_rsp_sensor_setup_server_send_setting_status_id 0x02480028`

#### sl_btmesh_evt_sensor_setup_server_get_cadence_request

Indicate an incoming Sensor Cadence Get request. 

This event must be replied to by sending a Sensor Cadence Status message. 

##### Modules

[sl_btmesh_evt_sensor_setup_server_get_cadence_request_s](sl-btmesh-evt-sensor-setup-server-get-cadence-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_setup_server_get_cadence_request_t

`typedef struct sl_btmesh_evt_sensor_setup_server_get_cadence_request_s sl_btmesh_evt_sensor_setup_server_get_cadence_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_setup_server_get_cadence_request_id 0x004800a8`

**Description**: Identifier of the get_cadence_request event.

Data structure of the get_cadence_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_cadence_request_s::server_address
```

**Details:** Address the request was directed to, either the server's unicast address or a group address the server subscribes to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_cadence_request_s::elem_index
```

**Details:** Setup Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_cadence_request_s::client_address
```

**Details:** Requesting client model's address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_cadence_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_get_cadence_request_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_cadence_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

#### sl_btmesh_evt_sensor_setup_server_set_cadence_request

Indicate an incoming Sensor Cadence Set request, which can be replied to by sending a Sensor Cadence Status message. 

Only Sensor Cadence Set (acknowledged) request results in a direct reply. In addition, configuration changes must be reported by publishing the updated cadence state according to model configuration. 

##### Modules

[sl_btmesh_evt_sensor_setup_server_set_cadence_request_s](sl-btmesh-evt-sensor-setup-server-set-cadence-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_setup_server_set_cadence_request_t

`typedef struct sl_btmesh_evt_sensor_setup_server_set_cadence_request_s sl_btmesh_evt_sensor_setup_server_set_cadence_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_setup_server_set_cadence_request_id 0x014800a8`

**Description**: Identifier of the set_cadence_request event.

Data structure of the set_cadence_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::server_address
```

**Details:** Address the request was directed to, either the server's unicast address or a group address the server subscribes to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::elem_index
```

**Details:** Setup Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::client_address
```

**Details:** Requesting client model's address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::flags
```

**Details:** Bit 1 (0x02) defines whether response is required. If set to 1, the client sent the message with SET CADENCE opcode and expects a CADENCE STATUS message in return.

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### period_divisor (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::period_divisor
```

**Details:** Fast Cadence Period Divisor, 7 bits defining the divisor for the Publish Period

###### trigger_type (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::trigger_type
```

**Details:** Status Trigger Type, 1 bit: 0 = discrete value, 1 = delta percentage

###### params (heading level 7)

```
uint8array sl_btmesh_evt_sensor_setup_server_set_cadence_request_s::params
```

**Details:** Optional byte array containing serialized fields of Sensor Cadence state, excluding the property ID, period divisor, and trigger type

- Fast Cadence Period Divisor, 7 bits
- Status Trigger type, 1 bit (0 = discrete value, 1 = percentage)
- Status Trigger Delta Down, variable length
- Status Trigger Delta Up, variable length
- Status Min Interval, 8 bits, representing a power of 2 milliseconds. Valid range is 0-26
- Fast Cadence Low, variable length, lower bound for the fast cadence range
- Low Cadence Low, variable length, higher bound for the fast cadence range

#### sl_btmesh_evt_sensor_setup_server_get_settings_request

Indicate an incoming Sensor Settings Get message to fetch the Sensor Setting Property IDs configured for the given Sensor. 

This event must be replied to by sending a Sensor Settings Status message. 

##### Modules

[sl_btmesh_evt_sensor_setup_server_get_settings_request_s](sl-btmesh-evt-sensor-setup-server-get-settings-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_setup_server_get_settings_request_t

`typedef struct sl_btmesh_evt_sensor_setup_server_get_settings_request_s sl_btmesh_evt_sensor_setup_server_get_settings_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_setup_server_get_settings_request_id 0x024800a8`

**Description**: Identifier of the get_settings_request event.

Data structure of the get_settings_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_settings_request_s::server_address
```

**Details:** Address the request was directed to, either the server's unicast address or a group address the server subscribes to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_settings_request_s::elem_index
```

**Details:** Setup Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_settings_request_s::client_address
```

**Details:** Requesting client model's address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_settings_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_get_settings_request_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_settings_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

#### sl_btmesh_evt_sensor_setup_server_get_setting_request

Indicate an incoming Sensor Get Setting request to fetch the value of a setting to a given sensor of a setting given by its ID. 

This event must be replied to by sending a Sensor Setting Status message. 

##### Modules

[sl_btmesh_evt_sensor_setup_server_get_setting_request_s](sl-btmesh-evt-sensor-setup-server-get-setting-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_setup_server_get_setting_request_t

`typedef struct sl_btmesh_evt_sensor_setup_server_get_setting_request_s sl_btmesh_evt_sensor_setup_server_get_setting_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_setup_server_get_setting_request_id 0x034800a8`

**Description**: Identifier of the get_setting_request event.

Data structure of the get_setting_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::server_address
```

**Details:** Address the request was directed to, either the server's unicast address, or a group address the server subscribes to

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::elem_index
```

**Details:** Setup Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::client_address
```

**Details:** Requesting client model's address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### setting_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_get_setting_request_s::setting_id
```

**Details:** Sensor Setting Property ID field identifying the device property of a setting. Range: 0x0001 - 0xffff, 0x0000 is prohibited.

#### sl_btmesh_evt_sensor_setup_server_set_setting_request

Indicate an incoming Sensor Set Setting request, which can be replied to by sending a Sensor Setting Status message. 

Only Setting Set (acknowledged) request is replied directly to the client. In addition, configuration changes must be reported by publishing the new state according to model publishing configuration. 

##### Modules

[sl_btmesh_evt_sensor_setup_server_set_setting_request_s](sl-btmesh-evt-sensor-setup-server-set-setting-request-s)

##### Typedefs

###### sl_btmesh_evt_sensor_setup_server_set_setting_request_t

`typedef struct sl_btmesh_evt_sensor_setup_server_set_setting_request_s sl_btmesh_evt_sensor_setup_server_set_setting_request_t`

##### Macros

`#define sl_btmesh_evt_sensor_setup_server_set_setting_request_id 0x044800a8`

**Description**: Identifier of the set_setting_request event.

Data structure of the set_setting_request event. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::server_address
```

**Details:** Address the request was directed to, either the server's unicast address, or a group address the server subscribes to.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::elem_index
```

**Details:** Setup Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::client_address
```

**Details:** Requesting client address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::flags
```

**Details:** Bit 1 (0x02) defines whether response is required. If set to 1, the client sent the message with SET SETTING opcode and expects a SETTING STATUS message in return.

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### setting_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_set_setting_request_s::setting_id
```

**Details:** Sensor Setting Property ID field identifying the device property of a setting. Range: 0x0001 - 0xffff, 0x0000 is prohibited.

###### raw_value (heading level 7)

```
uint8array sl_btmesh_evt_sensor_setup_server_set_setting_request_s::raw_value
```

**Details:** Sensor Setting raw value. Size and representation depends on the type defined by the Sensor Setting Property ID.

#### sl_btmesh_evt_sensor_setup_server_publish

Indicate that the publishing period timer elapsed and the app should/can publish its state. 

##### Modules

[sl_btmesh_evt_sensor_setup_server_publish_s](sl-btmesh-evt-sensor-setup-server-publish-s)

##### Typedefs

###### sl_btmesh_evt_sensor_setup_server_publish_t

`typedef struct sl_btmesh_evt_sensor_setup_server_publish_s sl_btmesh_evt_sensor_setup_server_publish_t`

##### Macros

`#define sl_btmesh_evt_sensor_setup_server_publish_id 0x054800a8`

**Description**: Identifier of the publish event.

Data structure of the publish event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_setup_server_publish_s::elem_index
```

**Details:** Client model element index

###### period_ms (heading level 7)

```
uint32_t sl_btmesh_evt_sensor_setup_server_publish_s::period_ms
```

**Details:** The current publishing period that can be used to estimate the next tick, e.g., when the state should be reported at higher frequency.

### Bluetooth Mesh Sensor Client Model

Bluetooth Mesh Sensor Client Model. 

This class provides the commands and messages to interface with the Sensor Client model. 

#### Modules

[sl_btmesh_evt_sensor_client_descriptor_status](sl-btmesh-evt-sensor-client-descriptor-status)

[sl_btmesh_evt_sensor_client_cadence_status](sl-btmesh-evt-sensor-client-cadence-status)

[sl_btmesh_evt_sensor_client_settings_status](sl-btmesh-evt-sensor-client-settings-status)

[sl_btmesh_evt_sensor_client_setting_status](sl-btmesh-evt-sensor-client-setting-status)

[sl_btmesh_evt_sensor_client_status](sl-btmesh-evt-sensor-client-status)

[sl_btmesh_evt_sensor_client_column_status](sl-btmesh-evt-sensor-client-column-status)

[sl_btmesh_evt_sensor_client_series_status](sl-btmesh-evt-sensor-client-series-status)

[sl_btmesh_evt_sensor_client_publish](sl-btmesh-evt-sensor-client-publish)

#### Functions

##### sl_btmesh_sensor_client_init

`sl_status_t sl_btmesh_sensor_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the Sensor Client model. Sensor Client does not have any internal configuration, it only activates the model in the Bluetooth mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_client_deinit

`sl_status_t sl_btmesh_sensor_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the Sensor Client model. There are no sensor-specific configurations to reset. Normally, models are initialized at boot and never deinitialized.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sensor_client_get_descriptor

`sl_status_t sl_btmesh_sensor_client_get_descriptor(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|ProperyID for the sensor (optional). Range: 0x0001 - 0xffff for a specific device property ID or 0x0000 to get all (the value 0x0000 is prohibited as a real ID).|

Get the Sensor Descriptor state of one specific sensor or all sensors within a model. Results in a Sensor Descriptor Status event

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_descriptor_status](sl-btmesh-evt-sensor-client-descriptor-status)

##### sl_btmesh_sensor_client_get

`sl_status_t sl_btmesh_sensor_client_get(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, or 0x0000 when not used to get values for all sensors present in the element.|

Send a Sensor Get message to fetch the Sensor Data state of one specific sensor given by its Property ID, results in a Sensor Status event. The Property ID 0x0000 can be used to fetch all sensor values present at a server element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_status](sl-btmesh-evt-sensor-client-status)

##### sl_btmesh_sensor_client_get_column

`sl_status_t sl_btmesh_sensor_client_get_column(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t column_id_len, const uint8_t *column_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|column_id_len|Length of data in `column_id`|
|const uint8_t *|[in]|column_id|Raw value identifying a column|

Get a Sensor Series Column state, results in a Sensor Column Status event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_column_status](sl-btmesh-evt-sensor-client-column-status)

##### sl_btmesh_sensor_client_get_series

`sl_status_t sl_btmesh_sensor_client_get_series(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t column_ids_len, const uint8_t *column_ids)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|column_ids_len|Length of data in `column_ids`|
|const uint8_t *|[in]|column_ids|Raw values identifying starting and ending columns|

Get a Sensor Series Column state, which results in a Sensor Series Status event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_series_status](sl-btmesh-evt-sensor-client-series-status)

##### sl_btmesh_sensor_client_get_cadence

`sl_status_t sl_btmesh_sensor_client_get_cadence(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|

Send a Sensor Get Cadence message to get the Sensor Cadence state, which results in a Sensor Cadence Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_cadence_status](sl-btmesh-evt-sensor-client-cadence-status)

##### sl_btmesh_sensor_client_set_cadence

`sl_status_t sl_btmesh_sensor_client_set_cadence(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t params_len, const uint8_t *params)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET CADENCE message will be sent, zero will send SET CADENCE UNACKNOWLEDGED|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|params_len|Length of data in `params`|
|const uint8_t *|[in]|params|Byte array containing serialized fields of Sensor Cadence state, excluding the property ID<br/><br/>- Fast Cadence Period Divisor, 7 bits<br/>- Status Trigger type, 1 bit (0 = discrete value, 1 = percentage)<br/>- Status Trigger Delta Down, variable length<br/>- Status Trigger Delta Up, variable length<br/>- Status Min Interval, 8 bits, representing a power of 2 milliseconds. Valid range is 0-26<br/>- Fast Cadence Low, variable length, lower bound for the fast cadence range<br/>- Low Cadence Low, variable length, higher bound for the fast cadence range|

Send a Sensor Cadence Set message, either acknowledged or unacknowledged, depending on the message flags. Acknowledged message results in a Cadence Status reply message and event. The server must publish its new state in any case.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_cadence_status](sl-btmesh-evt-sensor-client-cadence-status)

##### sl_btmesh_sensor_client_get_settings

`sl_status_t sl_btmesh_sensor_client_get_settings(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|

Send a Sensor Settings Get message to fetch the Sensor Property IDs present for the given sensor, which results in a Sensor Settings Status event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_settings_status](sl-btmesh-evt-sensor-client-settings-status)

##### sl_btmesh_sensor_client_get_setting

`sl_status_t sl_btmesh_sensor_client_get_setting(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, uint16_t setting_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|No flags defined currently|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|uint16_t|[in]|setting_id|Sensor Setting Property ID field identifying the device property of a setting. Range: 0x0001 - 0xffff, 0x0000 is prohibited.|

Send a Sensor Get Setting message to get the value of a specific setting for the given sensor, which results in a Sensor Setting Status event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_setting_status](sl-btmesh-evt-sensor-client-setting-status)

##### sl_btmesh_sensor_client_set_setting

`sl_status_t sl_btmesh_sensor_client_set_setting(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, uint16_t setting_id, size_t raw_value_len, const uint8_t *raw_value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET SETTING message is sent, zero will use SET SETTING UNACKNOWLEDGED.|
|uint16_t|[in]|property_id|Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|uint16_t|[in]|setting_id|Sensor Setting Property ID field identifying the device property of a setting. Range: 0x0001 - 0xffff, 0x0000 is prohibited.|
|size_t|[in]|raw_value_len|Length of data in `raw_value`|
|const uint8_t *|[in]|raw_value|Sensor Setting raw value. Size and representation depends on the type defined by the Sensor Setting Property ID.|

Send Sensor Setting Set message to update the value of a specific setting for the given sensor, either acknowledged or unacknowledged depending on the message flags. Only acknowledged requests will have a direct Sensor Setting Status reply. The server must publish its new state in any case.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sensor_client_setting_status](sl-btmesh-evt-sensor-client-setting-status)

#### Macros

`#define sl_btmesh_cmd_sensor_client_init_id 0x00490028`

`#define sl_btmesh_cmd_sensor_client_deinit_id 0x01490028`

`#define sl_btmesh_cmd_sensor_client_get_descriptor_id 0x02490028`

`#define sl_btmesh_cmd_sensor_client_get_id 0x03490028`

`#define sl_btmesh_cmd_sensor_client_get_column_id 0x04490028`

`#define sl_btmesh_cmd_sensor_client_get_series_id 0x05490028`

`#define sl_btmesh_cmd_sensor_client_get_cadence_id 0x06490028`

`#define sl_btmesh_cmd_sensor_client_set_cadence_id 0x07490028`

`#define sl_btmesh_cmd_sensor_client_get_settings_id 0x08490028`

`#define sl_btmesh_cmd_sensor_client_get_setting_id 0x09490028`

`#define sl_btmesh_cmd_sensor_client_set_setting_id 0x0a490028`

`#define sl_btmesh_rsp_sensor_client_init_id 0x00490028`

`#define sl_btmesh_rsp_sensor_client_deinit_id 0x01490028`

`#define sl_btmesh_rsp_sensor_client_get_descriptor_id 0x02490028`

`#define sl_btmesh_rsp_sensor_client_get_id 0x03490028`

`#define sl_btmesh_rsp_sensor_client_get_column_id 0x04490028`

`#define sl_btmesh_rsp_sensor_client_get_series_id 0x05490028`

`#define sl_btmesh_rsp_sensor_client_get_cadence_id 0x06490028`

`#define sl_btmesh_rsp_sensor_client_set_cadence_id 0x07490028`

`#define sl_btmesh_rsp_sensor_client_get_settings_id 0x08490028`

`#define sl_btmesh_rsp_sensor_client_get_setting_id 0x09490028`

`#define sl_btmesh_rsp_sensor_client_set_setting_id 0x0a490028`

#### sl_btmesh_evt_sensor_client_descriptor_status

Indicate an incoming Sensor Descriptor Status message, received as a response to the [sl_btmesh_sensor_client_get_descriptor](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-descriptor) command. 

##### Modules

[sl_btmesh_evt_sensor_client_descriptor_status_s](sl-btmesh-evt-sensor-client-descriptor-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_descriptor_status_t

`typedef struct sl_btmesh_evt_sensor_client_descriptor_status_s sl_btmesh_evt_sensor_client_descriptor_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_descriptor_status_id 0x004900a8`

**Description**: Identifier of the descriptor_status event.

Data structure of the descriptor_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_descriptor_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_descriptor_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_descriptor_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_descriptor_status_s::appkey_index
```

**Details:** The application key index to use.

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_descriptor_status_s::flags
```

**Details:** No flags defined currently

###### descriptors (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_descriptor_status_s::descriptors
```

**Details:** One or more Sensor Descriptor states (N times 8 bytes) As a reply to a Get message referencing a sensor that does not exist, the array contains only the requested Property ID. Format of the Descriptor state is as follows:

- Property ID, 16 bits
- Sensor Positive Tolerance, 12 bits
- Sensor Negative Tolerance, 12 bits
- Sensor Sampling Function, 8 bits
- Sensor Measurement Period, 8 bits
- Sensor Update Interval, 8 bits {/ul>

#### sl_btmesh_evt_sensor_client_cadence_status

Indicate an incoming Sensor Cadence Status message, received as a response to the [sl_btmesh_sensor_client_get_cadence](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-cadence) or [sl_btmesh_sensor_client_set_cadence](sl-btmesh-sensor-client#sl-btmesh-sensor-client-set-cadence) command. 

##### Modules

[sl_btmesh_evt_sensor_client_cadence_status_s](sl-btmesh-evt-sensor-client-cadence-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_cadence_status_t

`typedef struct sl_btmesh_evt_sensor_client_cadence_status_s sl_btmesh_evt_sensor_client_cadence_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_cadence_status_id 0x014900a8`

**Description**: Identifier of the cadence_status event.

Data structure of the cadence_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_cadence_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_cadence_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_cadence_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_cadence_status_s::appkey_index
```

**Details:** The application key index to use.

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_cadence_status_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_cadence_status_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### params (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_cadence_status_s::params
```

**Details:** Optional byte array containing serialized fields of Sensor Cadence state, excluding the property ID

- Fast Cadence Period Divisor, 7 bits
- Status Trigger type, 1 bit (0 = discrete value, 1 = percentage)
- Status Trigger Delta Down, variable length
- Status Trigger Delta Up, variable length
- Status Min Interval, 8 bits, representing a power of 2 milliseconds. Valid range is 0-26
- Fast Cadence Low, variable length, lower bound for the fast cadence range
- Low Cadence Low, variable length, higher bound for the fast cadence range

#### sl_btmesh_evt_sensor_client_settings_status

Indicate an incoming Sensor Settings Status message, received as a response to the [sl_btmesh_sensor_client_get_settings](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-settings) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_sensor_client_settings_status_s](sl-btmesh-evt-sensor-client-settings-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_settings_status_t

`typedef struct sl_btmesh_evt_sensor_client_settings_status_s sl_btmesh_evt_sensor_client_settings_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_settings_status_id 0x024900a8`

**Description**: Identifier of the settings_status event.

Data structure of the settings_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_settings_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_settings_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_settings_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_settings_status_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_settings_status_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_settings_status_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### setting_ids (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_settings_status_s::setting_ids
```

**Details:** Array of 16-bit Setting Property IDs of the settings the given sensor has

#### sl_btmesh_evt_sensor_client_setting_status

Indicate an incoming Sensor Setting Status message, received as a response to the [sl_btmesh_sensor_client_get_setting](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-setting) or [sl_btmesh_sensor_client_set_setting](sl-btmesh-sensor-client#sl-btmesh-sensor-client-set-setting) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_sensor_client_setting_status_s](sl-btmesh-evt-sensor-client-setting-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_setting_status_t

`typedef struct sl_btmesh_evt_sensor_client_setting_status_s sl_btmesh_evt_sensor_client_setting_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_setting_status_id 0x034900a8`

**Description**: Identifier of the setting_status event.

Data structure of the setting_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_setting_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_setting_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_setting_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_setting_status_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_setting_status_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_setting_status_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### setting_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_setting_status_s::setting_id
```

**Details:** Sensor Setting Property ID field identifying the device property of a setting. Range: 0x0001 - 0xffff, 0x0000 is prohibited.

###### raw_value (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_setting_status_s::raw_value
```

**Details:** Sensor Setting raw value. Size and representation depends on the type defined by the Sensor Setting Property ID.

#### sl_btmesh_evt_sensor_client_status

Indicate an incoming Sensor Status event as a published data state from the sensor server or as a reply to the [sl_btmesh_sensor_client_get](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get) command. 

##### Modules

[sl_btmesh_evt_sensor_client_status_s](sl-btmesh-evt-sensor-client-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_status_t

`typedef struct sl_btmesh_evt_sensor_client_status_s sl_btmesh_evt_sensor_client_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_status_id 0x044900a8`

**Description**: Identifier of the status event.

Data structure of the status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_status_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_status_s::flags
```

**Details:** No flags defined currently

###### sensor_data (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_status_s::sensor_data
```

**Details:** Serialized Sensor Data consisting of one or more Sensor state for each sensor within the element. To simplify processing, the byte array is in TLV format:

- 1st Property ID: 16 bits
- Value Length: 8 bits
- Value: variable
- 2nd Property ID: 16 bits
- Value Length: 8 bits
- Value: variable
- ...

If the requested Property ID does not exist at the server element, the reply contains only the given Property ID and zero length.

#### sl_btmesh_evt_sensor_client_column_status

Indicate an incoming Sensor Column Status event, received as a response to the [sl_btmesh_sensor_client_get_column](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-column) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_sensor_client_column_status_s](sl-btmesh-evt-sensor-client-column-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_column_status_t

`typedef struct sl_btmesh_evt_sensor_client_column_status_s sl_btmesh_evt_sensor_client_column_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_column_status_id 0x054900a8`

**Description**: Identifier of the column_status event.

Data structure of the column_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_column_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_column_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_column_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_column_status_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_column_status_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_column_status_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### sensor_data (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_column_status_s::sensor_data
```

**Details:** Byte array containing the serialized Sensor Series Column state in the following format:

- Sensor Raw Value X, variable length raw value representing the left corner of a column
- Sensor Column Width, variable length raw value representing the width of the column
- Sensor Raw Value Y, variable length raw value representing the height of the column

If the requested Property ID or column ID does not exist at the server elements, the reply status message contains only these two fields, omitting column width and height values.

#### sl_btmesh_evt_sensor_client_series_status

Indicate an incoming Sensor Series Status message, received as a response to the [sl_btmesh_sensor_client_get_series](sl-btmesh-sensor-client#sl-btmesh-sensor-client-get-series) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_sensor_client_series_status_s](sl-btmesh-evt-sensor-client-series-status-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_series_status_t

`typedef struct sl_btmesh_evt_sensor_client_series_status_s sl_btmesh_evt_sensor_client_series_status_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_series_status_id 0x064900a8`

**Description**: Identifier of the series_status event.

Data structure of the series_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_series_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_series_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_series_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_series_status_s::appkey_index
```

**Details:** The application key index to use

###### flags (heading level 7)

```
uint8_t sl_btmesh_evt_sensor_client_series_status_s::flags
```

**Details:** No flags defined currently

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_series_status_s::property_id
```

**Details:** Property ID for the sensor. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.

###### sensor_data (heading level 7)

```
uint8array sl_btmesh_evt_sensor_client_series_status_s::sensor_data
```

**Details:** Byte array containing the serialized sequence of Sensor Serier Column states in the following format:

- 1st Sensor Raw Value X, variable length raw value representing the left corner of a column
- 1st Sensor Column Width, variable length raw value representing the width of the column
- 1st Sensor Raw Value Y, variable length raw value representing the height of the column
- ...
- Nth Sensor Raw Value X, variable length raw value representing the left corner of a column
- Nth Sensor Column Width, variable length raw value representing the width of the column
- Nth Sensor Raw Value Y, variable length raw value representing the height of the column

If a Property ID or column requested does not exist at the server element, the reply Series Status message contains only the given Property ID.

#### sl_btmesh_evt_sensor_client_publish

Indicate that the publishing period timer elapsed and the app should/can publish its state or any request. 

##### Modules

[sl_btmesh_evt_sensor_client_publish_s](sl-btmesh-evt-sensor-client-publish-s)

##### Typedefs

###### sl_btmesh_evt_sensor_client_publish_t

`typedef struct sl_btmesh_evt_sensor_client_publish_s sl_btmesh_evt_sensor_client_publish_t`

##### Macros

`#define sl_btmesh_evt_sensor_client_publish_id 0x074900a8`

**Description**: Identifier of the publish event.

Data structure of the publish event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_sensor_client_publish_s::elem_index
```

**Details:** Client model element index

###### period_ms (heading level 7)

```
uint32_t sl_btmesh_evt_sensor_client_publish_s::period_ms
```

**Details:** The current publishing period that can be used to estimate the next tick, e.g., when the state should be reported at higher frequency.

### Bluetooth Mesh Firmware Update Client Model

Bluetooth Mesh Firmware Update Client Model. 

This class provides the commands and messages to interface with the Firmware Update Client model.

If Firmware Distribution Server is used only the [sl_btmesh_fw_update_client_init](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-init) function shall be called as all of the other functions are called by the Distribution Server inside the BT Mesh stack automatically.

The MBT Client must be initialized before the Update Client. 

#### Modules

[sl_btmesh_evt_fw_update_client_info_status_current_fwid](sl-btmesh-evt-fw-update-client-info-status-current-fwid)

[sl_btmesh_evt_fw_update_client_info_status_update_uri](sl-btmesh-evt-fw-update-client-info-status-update-uri)

[sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status)

[sl_btmesh_evt_fw_update_client_metadata_status](sl-btmesh-evt-fw-update-client-metadata-status)

#### Enumerations

##### sl_btmesh_fw_update_client_additional_info_t

```
enum sl_btmesh_fw_update_client_additional_info_t {
    sl_btmesh_fw_update_client_additional_info_none = 0x0
    sl_btmesh_fw_update_client_additional_info_dcd_change_no_rp = 0x1
    sl_btmesh_fw_update_client_additional_info_dcd_change_rp_supported = 0x2
    sl_btmesh_fw_update_client_additional_info_unprovisioned_after_update = 0x3
}
```

**Description:**

The Additional Information value for the firmware update candidate. This value is reported in the Update Server's Metadata Status message, and in the Update Status message if an update is active. This value indicates what will happen to the Target Node after the new firmware is applied successfully and the node is rebooted.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_update_client_additional_info_none|(0x0) No changes to Device Composition Data.|
|sl_btmesh_fw_update_client_additional_info_dcd_change_no_rp|(0x1) Device Composition Data will change, but Remote Provisioning, and thus Composition Data Refresh is not supported. The node will need to be re-provisioned to take its new models into use.|
|sl_btmesh_fw_update_client_additional_info_dcd_change_rp_supported|(0x2) Device Composition Data will change, and can be refreshed.|
|sl_btmesh_fw_update_client_additional_info_unprovisioned_after_update|(0x3) The node will be unprovisioned after the update.|

#### Functions

##### sl_btmesh_fw_update_client_init

`sl_status_t sl_btmesh_fw_update_client_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Initialize the Firmware Update Client model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_update_client_deinit

`sl_status_t sl_btmesh_fw_update_client_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Deinitialize the Firmware Update Client model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_update_client_get_info

`sl_status_t sl_btmesh_fw_update_client_get_info(uint16_t elem_index, uint16_t dst, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl, uint8_t first_index, uint8_t max_entries)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|[uuid_128](uuid-128)|[in]|virtual_address|If the destination address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|
|uint8_t|[in]|first_index|Index of the first requested entry|
|uint8_t|[in]|max_entries|Maximum number of entries|

Query information about the firmware images installed on a node. The received query result is carried in [sl_btmesh_evt_fw_update_client_info_status_current_fwid](sl-btmesh-evt-fw-update-client-info-status-current-fwid) and [sl_btmesh_evt_fw_update_client_info_status_update_uri](sl-btmesh-evt-fw-update-client-info-status-update-uri) events.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_client_info_status_current_fwid](sl-btmesh-evt-fw-update-client-info-status-current-fwid)
- [sl_btmesh_evt_fw_update_client_info_status_update_uri](sl-btmesh-evt-fw-update-client-info-status-update-uri)

##### sl_btmesh_fw_update_client_get_update

`sl_status_t sl_btmesh_fw_update_client_get_update(uint16_t elem_index, uint16_t dst, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|[uuid_128](uuid-128)|[in]|virtual_address|If the destination address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|

Get the current status of the server. [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status) is sent as a response.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status)

##### sl_btmesh_fw_update_client_start_update

`sl_status_t sl_btmesh_fw_update_client_start_update(uint16_t elem_index, uint16_t dst, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl, uint8_t update_ttl, uint16_t update_timeout_base, sl_bt_uuid_64_t blob_id, uint8_t fw_index, size_t metadata_len, const uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|[uuid_128](uuid-128)|[in]|virtual_address|If the destination address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use for sending this message. Valid values: 0, range:[2-127] and 255.|
|uint8_t|[in]|update_ttl|The time-to-live value the node should use when sending its status responses in the firmware image transfer. Valid values: 0, range:[2-127] and 255.|
|uint16_t|[in]|update_timeout_base|Update Timeout Base value to inform to the node.|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t)|[in]|blob_id|The BLOB ID of the firmware image that is going to be transferred.|
|uint8_t|[in]|fw_index|Index of the firmware on the node to be updated.|
|size_t|[in]|metadata_len|Length of data in `metadata`|
|const uint8_t *|[in]|metadata|Metadata associated with the firmware image to be transferred.|

Start a firmware update on a server. [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status) is sent as a response.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status)

##### sl_btmesh_fw_update_client_cancel_update

`sl_status_t sl_btmesh_fw_update_client_cancel_update(uint16_t elem_index, uint16_t dst, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|[uuid_128](uuid-128)|[in]|virtual_address|If the destination address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|

Cancel a firmware update and delete any stored information about the update on a server. [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status) is sent as a response.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status)

##### sl_btmesh_fw_update_client_apply_update

`sl_status_t sl_btmesh_fw_update_client_apply_update(uint16_t elem_index, uint16_t dst, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|[uuid_128](uuid-128)|[in]|virtual_address|If the destination address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|

Apply a firmware image that has been transferred to a server. [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status) is sent as a response.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_client_update_status](sl-btmesh-evt-fw-update-client-update-status)

##### sl_btmesh_fw_update_client_check_metadata

`sl_status_t sl_btmesh_fw_update_client_check_metadata(uint16_t elem_index, uint16_t dst, uuid_128 virtual_address, uint16_t appkey_index, uint8_t ttl, uint8_t fw_index, size_t metadata_len, const uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|[uuid_128](uuid-128)|[in]|virtual_address|If the destination address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|
|uint8_t|[in]|fw_index|Index of the firmware on the node to check the metadata against.|
|size_t|[in]|metadata_len|Length of data in `metadata`|
|const uint8_t *|[in]|metadata|Metadata to check.|

Check whether the node can accept a firmware based on the firmware's metadata. [sl_btmesh_evt_fw_update_client_metadata_status](sl-btmesh-evt-fw-update-client-metadata-status) is sent as a response.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_client_metadata_status](sl-btmesh-evt-fw-update-client-metadata-status)

#### Macros

`#define sl_btmesh_cmd_fw_update_client_init_id 0x004a0028`

`#define sl_btmesh_cmd_fw_update_client_deinit_id 0x014a0028`

`#define sl_btmesh_cmd_fw_update_client_get_info_id 0x084a0028`

`#define sl_btmesh_cmd_fw_update_client_get_update_id 0x094a0028`

`#define sl_btmesh_cmd_fw_update_client_start_update_id 0x0a4a0028`

`#define sl_btmesh_cmd_fw_update_client_cancel_update_id 0x0b4a0028`

`#define sl_btmesh_cmd_fw_update_client_apply_update_id 0x0c4a0028`

`#define sl_btmesh_cmd_fw_update_client_check_metadata_id 0x0d4a0028`

`#define sl_btmesh_rsp_fw_update_client_init_id 0x004a0028`

`#define sl_btmesh_rsp_fw_update_client_deinit_id 0x014a0028`

`#define sl_btmesh_rsp_fw_update_client_get_info_id 0x084a0028`

`#define sl_btmesh_rsp_fw_update_client_get_update_id 0x094a0028`

`#define sl_btmesh_rsp_fw_update_client_start_update_id 0x0a4a0028`

`#define sl_btmesh_rsp_fw_update_client_cancel_update_id 0x0b4a0028`

`#define sl_btmesh_rsp_fw_update_client_apply_update_id 0x0c4a0028`

`#define sl_btmesh_rsp_fw_update_client_check_metadata_id 0x0d4a0028`

#### sl_btmesh_evt_fw_update_client_info_status_current_fwid

Report information about firmware images installed on a node, FWID part of the Information Status message. 

Sent as a response to [sl_btmesh_fw_update_client_get_info](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-get-info)

##### Modules

[sl_btmesh_evt_fw_update_client_info_status_current_fwid_s](sl-btmesh-evt-fw-update-client-info-status-current-fwid-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_client_info_status_current_fwid_t

`typedef struct sl_btmesh_evt_fw_update_client_info_status_current_fwid_s sl_btmesh_evt_fw_update_client_info_status_current_fwid_t`

##### Macros

`#define sl_btmesh_evt_fw_update_client_info_status_current_fwid_id 0x004a00a8`

**Description**: Identifier of the info_status_current_fwid event.

Data structure of the info_status_current_fwid event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_info_status_current_fwid_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_info_status_current_fwid_s::server_address
```

**Details:** Unicast address of the server

###### index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_info_status_current_fwid_s::index
```

**Details:** Index of this FWID in the Firmware Information List

###### count (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_info_status_current_fwid_s::count
```

**Details:** Total number of entries in the Firmware Information List

###### current_fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_update_client_info_status_current_fwid_s::current_fwid
```

**Details:** Current Firmware ID

#### sl_btmesh_evt_fw_update_client_info_status_update_uri

Report information about firmware images installed on a node, Update URI part of the Information Status message. 

Send as a response to [sl_btmesh_fw_update_client_get_info](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-get-info)

##### Modules

[sl_btmesh_evt_fw_update_client_info_status_update_uri_s](sl-btmesh-evt-fw-update-client-info-status-update-uri-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_client_info_status_update_uri_t

`typedef struct sl_btmesh_evt_fw_update_client_info_status_update_uri_s sl_btmesh_evt_fw_update_client_info_status_update_uri_t`

##### Macros

`#define sl_btmesh_evt_fw_update_client_info_status_update_uri_id 0x014a00a8`

**Description**: Identifier of the info_status_update_uri event.

Data structure of the info_status_update_uri event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_info_status_update_uri_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_info_status_update_uri_s::server_address
```

**Details:** Unicast address of the server

###### index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_info_status_update_uri_s::index
```

**Details:** Index of this URI in the Firmware Information List

###### count (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_info_status_update_uri_s::count
```

**Details:** Total number of entries in the Firmware Information List

###### update_uri (heading level 7)

```
uint8array sl_btmesh_evt_fw_update_client_info_status_update_uri_s::update_uri
```

**Details:** Update URI

#### sl_btmesh_evt_fw_update_client_update_status

Report the status of a firmware update. 

Sent in response to a [sl_btmesh_fw_update_client_get_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-get-update)[sl_btmesh_fw_update_client_start_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-start-update)[sl_btmesh_fw_update_client_cancel_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-cancel-update)[sl_btmesh_fw_update_client_apply_update](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-apply-update) messages. 

##### Modules

[sl_btmesh_evt_fw_update_client_update_status_s](sl-btmesh-evt-fw-update-client-update-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_client_update_status_t

`typedef struct sl_btmesh_evt_fw_update_client_update_status_s sl_btmesh_evt_fw_update_client_update_status_t`

##### Macros

`#define sl_btmesh_evt_fw_update_client_update_status_id 0x024a00a8`

**Description**: Identifier of the update_status event.

Data structure of the update_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_update_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_update_status_s::server_address
```

**Details:** Unicast address of the server

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_update_status_s::status
```

**Details:** Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Status code returned

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_update_status_s::phase
```

**Details:** Enum [sl_btmesh_fw_update_server_update_phase_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-phase-t). Phase of the Update Server

###### additional_information (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_update_status_s::additional_information
```

**Details:** Enum [sl_btmesh_fw_update_client_additional_info_t](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-additional-info-t). Additional information about what will happen to the node after the update is applied. 0 = no changes to DCD; 1 = DCD will change but Composition Data Refresh is not supported; 2 = DCD change and Composition Data Refresh is supported; 3 = node will become unprovisioned.

###### update_timeout_base (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_update_status_s::update_timeout_base
```

**Details:** Base value for BLOB Transfer Timeout

###### distributor_ttl (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_update_status_s::distributor_ttl
```

**Details:** TTL used by the Distributor. Ignore if no update is active.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_update_client_update_status_s::blob_id
```

**Details:** BLOB ID of the firmware being transferred. Ignore if no update is active.

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_update_status_s::fw_index
```

**Details:** Index of the firmware being updated on the node.

#### sl_btmesh_evt_fw_update_client_metadata_status

Report whether a server can accept a firmware update. 

Sent in response to a [sl_btmesh_fw_update_client_check_metadata](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-check-metadata)

##### Modules

[sl_btmesh_evt_fw_update_client_metadata_status_s](sl-btmesh-evt-fw-update-client-metadata-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_client_metadata_status_t

`typedef struct sl_btmesh_evt_fw_update_client_metadata_status_s sl_btmesh_evt_fw_update_client_metadata_status_t`

##### Macros

`#define sl_btmesh_evt_fw_update_client_metadata_status_id 0x0a4a00a8`

**Description**: Identifier of the metadata_status event.

Data structure of the metadata_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_metadata_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_client_metadata_status_s::server_address
```

**Details:** Unicast address of the server

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_metadata_status_s::status
```

**Details:** Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Status code returned

###### additional_information (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_metadata_status_s::additional_information
```

**Details:** Enum [sl_btmesh_fw_update_client_additional_info_t](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-additional-info-t). Additional information about what will happen to the node after the update is applied. 0 = no changes to DCD; 1 = DCD will change but Composition Data Refresh is not supported; 2 = DCD change and Composition Data Refresh is supported; 3 = node will become unprovisioned.

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_client_metadata_status_s::fw_index
```

**Details:** Index of the firmware that was checked against the metadata.

### Bluetooth Mesh Light Control Client Model

Bluetooth Mesh Light Control Client Model. 

Bluetooth Mesh LC Client model API provides functionality to send and receive messages to/from the LC Server and LC Setup Server models.

Throughout the API, the client model that's used is identified by its element address and model ID, while the server model responding to the client model requests is identified by its element address and model ID.

The API has functions for querying server model states and requesting server model state changes 

#### Modules

[sl_btmesh_evt_lc_client_mode_status](sl-btmesh-evt-lc-client-mode-status)

[sl_btmesh_evt_lc_client_om_status](sl-btmesh-evt-lc-client-om-status)

[sl_btmesh_evt_lc_client_light_onoff_status](sl-btmesh-evt-lc-client-light-onoff-status)

[sl_btmesh_evt_lc_client_property_status](sl-btmesh-evt-lc-client-property-status)

#### Functions

##### sl_btmesh_lc_client_init

`sl_status_t sl_btmesh_lc_client_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the client element.|

Initialize the LC Client model. LC Client does not have any internal configuration. It only activates the model in the mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_client_get_mode

`sl_status_t sl_btmesh_lc_client_get_mode(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Device to be queried. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Index of the client element.|
|uint16_t|[in]|appkey_index|Appkey used by server_address.|

Get the mode status.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_mode_status](sl-btmesh-evt-lc-client-mode-status)

##### sl_btmesh_lc_client_set_mode

`sl_status_t sl_btmesh_lc_client_set_mode(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint8_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether a response is required. If set to 1, SET PROPERTY message will be sent. Zero will send SET PROPERTY UNACKNOWLEDGED.|
|uint8_t|[in]|mode|Mode value to set|

Set mode

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_mode_status](sl-btmesh-evt-lc-client-mode-status)

##### sl_btmesh_lc_client_get_om

`sl_status_t sl_btmesh_lc_client_get_om(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Device to be queried. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Index of the client element.|
|uint16_t|[in]|appkey_index|Appkey used by server_address.|

Get the OM status.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_om_status](sl-btmesh-evt-lc-client-om-status)

##### sl_btmesh_lc_client_set_om

`sl_status_t sl_btmesh_lc_client_set_om(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint8_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET PROPERTY message will be sent. Zero will send SET PROPERTY UNACKNOWLEDGED.|
|uint8_t|[in]|mode|Mode value to set|

Set occupancy mode.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_om_status](sl-btmesh-evt-lc-client-om-status)

##### sl_btmesh_lc_client_get_light_onoff

`sl_status_t sl_btmesh_lc_client_get_light_onoff(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Device to be queried. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Index of the client element.|
|uint16_t|[in]|appkey_index|Appkey used by server_address.|

Get the Light OnOff status.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_light_onoff_status](sl-btmesh-evt-lc-client-light-onoff-status)

##### sl_btmesh_lc_client_set_light_onoff

`sl_status_t sl_btmesh_lc_client_set_light_onoff(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint8_t target_state, uint8_t tid, uint32_t transition_time_ms, uint16_t message_delay_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET PROPERTY message will be sent. Zero will send SET PROPERTY UNACKNOWLEDGED.|
|uint8_t|[in]|target_state|The target value of the Light LC Light OnOff state|
|uint8_t|[in]|tid|Transaction identifier|
|uint32_t|[in]|transition_time_ms|Transition time in milliseconds. Value of 0xFFFFFFFF will cause this parameter as well as the "delay" parameter to be omitted.|
|uint16_t|[in]|message_delay_ms|Message execution delay in milliseconds. If the "transition_time" is 0xFFFFFFFF, this parameter is ignored. If both the transition time and the delay are zero, the transition is immediate. Valid range: 0-1275.|

Set the Light OnOff.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_light_onoff_status](sl-btmesh-evt-lc-client-light-onoff-status)

##### sl_btmesh_lc_client_get_property

`sl_status_t sl_btmesh_lc_client_get_property(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint16_t property_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Device to be queried. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Index of the client element.|
|uint16_t|[in]|appkey_index|Appkey used by server_address.|
|uint16_t|[in]|property_id|The property ID to query.|

Get the Property status.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_property_status](sl-btmesh-evt-lc-client-property-status)

##### sl_btmesh_lc_client_set_property

`sl_status_t sl_btmesh_lc_client_set_property(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint16_t property_id, size_t params_len, const uint8_t *params)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET PROPERTY message will be sent. Zero will send SET PROPERTY UNACKNOWLEDGED.|
|uint16_t|[in]|property_id|Property ID for the LC Server. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|params_len|Length of data in `params`|
|const uint8_t *|[in]|params|Byte array containing serialized fields of LC Property, excluding the property ID|

Set a particular property.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lc_client_property_status](sl-btmesh-evt-lc-client-property-status)

#### Macros

`#define sl_btmesh_cmd_lc_client_init_id 0x004c0028`

`#define sl_btmesh_cmd_lc_client_get_mode_id 0x014c0028`

`#define sl_btmesh_cmd_lc_client_set_mode_id 0x024c0028`

`#define sl_btmesh_cmd_lc_client_get_om_id 0x044c0028`

`#define sl_btmesh_cmd_lc_client_set_om_id 0x054c0028`

`#define sl_btmesh_cmd_lc_client_get_light_onoff_id 0x074c0028`

`#define sl_btmesh_cmd_lc_client_set_light_onoff_id 0x084c0028`

`#define sl_btmesh_cmd_lc_client_get_property_id 0x094c0028`

`#define sl_btmesh_cmd_lc_client_set_property_id 0x0a4c0028`

`#define sl_btmesh_rsp_lc_client_init_id 0x004c0028`

`#define sl_btmesh_rsp_lc_client_get_mode_id 0x014c0028`

`#define sl_btmesh_rsp_lc_client_set_mode_id 0x024c0028`

`#define sl_btmesh_rsp_lc_client_get_om_id 0x044c0028`

`#define sl_btmesh_rsp_lc_client_set_om_id 0x054c0028`

`#define sl_btmesh_rsp_lc_client_get_light_onoff_id 0x074c0028`

`#define sl_btmesh_rsp_lc_client_set_light_onoff_id 0x084c0028`

`#define sl_btmesh_rsp_lc_client_get_property_id 0x094c0028`

`#define sl_btmesh_rsp_lc_client_set_property_id 0x0a4c0028`

#### sl_btmesh_evt_lc_client_mode_status

Indicate an incoming LC Mode Status message, received as a response to [sl_btmesh_lc_client_get_mode](sl-btmesh-lc-client#sl-btmesh-lc-client-get-mode) or [sl_btmesh_lc_client_set_mode](sl-btmesh-lc-client#sl-btmesh-lc-client-set-mode). 

##### Modules

[sl_btmesh_evt_lc_client_mode_status_s](sl-btmesh-evt-lc-client-mode-status-s)

##### Typedefs

###### sl_btmesh_evt_lc_client_mode_status_t

`typedef struct sl_btmesh_evt_lc_client_mode_status_s sl_btmesh_evt_lc_client_mode_status_t`

##### Macros

`#define sl_btmesh_evt_lc_client_mode_status_id 0x004c00a8`

**Description**: Identifier of the mode_status event.

Data structure of the mode_status event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_mode_status_s::destination_address
```

**Details:** Address of the client or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_mode_status_s::elem_index
```

**Details:** Index of the element for which received the status.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_mode_status_s::server_address
```

**Details:** Device which sent the status.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_mode_status_s::appkey_index
```

**Details:** Appkey used by server_address.

###### mode_status_value (heading level 7)

```
uint8_t sl_btmesh_evt_lc_client_mode_status_s::mode_status_value
```

**Details:** Value reported by server.

#### sl_btmesh_evt_lc_client_om_status

Indicate an incoming LC Occupancy Mode Status message, received as a response to [sl_btmesh_lc_client_get_om](sl-btmesh-lc-client#sl-btmesh-lc-client-get-om) or [sl_btmesh_lc_client_set_om](sl-btmesh-lc-client#sl-btmesh-lc-client-set-om). 

##### Modules

[sl_btmesh_evt_lc_client_om_status_s](sl-btmesh-evt-lc-client-om-status-s)

##### Typedefs

###### sl_btmesh_evt_lc_client_om_status_t

`typedef struct sl_btmesh_evt_lc_client_om_status_s sl_btmesh_evt_lc_client_om_status_t`

##### Macros

`#define sl_btmesh_evt_lc_client_om_status_id 0x014c00a8`

**Description**: Identifier of the om_status event.

Data structure of the om_status event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_om_status_s::destination_address
```

**Details:** Address of the client or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_om_status_s::elem_index
```

**Details:** Index of the element for which received the status.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_om_status_s::server_address
```

**Details:** Device which sent the status.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_om_status_s::appkey_index
```

**Details:** Appkey used by server_address.

###### om_status_value (heading level 7)

```
uint8_t sl_btmesh_evt_lc_client_om_status_s::om_status_value
```

**Details:** Value reported by server.

#### sl_btmesh_evt_lc_client_light_onoff_status

Indicate an incoming LC Light OnOff Status message, received as a response to [sl_btmesh_lc_client_get_light_onoff](sl-btmesh-lc-client#sl-btmesh-lc-client-get-light-onoff) or [sl_btmesh_lc_client_set_light_onoff](sl-btmesh-lc-client#sl-btmesh-lc-client-set-light-onoff). 

##### Modules

[sl_btmesh_evt_lc_client_light_onoff_status_s](sl-btmesh-evt-lc-client-light-onoff-status-s)

##### Typedefs

###### sl_btmesh_evt_lc_client_light_onoff_status_t

`typedef struct sl_btmesh_evt_lc_client_light_onoff_status_s sl_btmesh_evt_lc_client_light_onoff_status_t`

##### Macros

`#define sl_btmesh_evt_lc_client_light_onoff_status_id 0x024c00a8`

**Description**: Identifier of the light_onoff_status event.

Data structure of the light_onoff_status event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_light_onoff_status_s::destination_address
```

**Details:** Address of the client or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_light_onoff_status_s::elem_index
```

**Details:** Index of the element for which received the status.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_light_onoff_status_s::server_address
```

**Details:** Device which sent the status.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_light_onoff_status_s::appkey_index
```

**Details:** Appkey used by server_address.

###### present_light_onoff (heading level 7)

```
uint8_t sl_btmesh_evt_lc_client_light_onoff_status_s::present_light_onoff
```

**Details:** Present value of the Light OnOff state

###### target_light_onoff (heading level 7)

```
uint8_t sl_btmesh_evt_lc_client_light_onoff_status_s::target_light_onoff
```

**Details:** Target value of the Light OnOff state

###### remaining_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_lc_client_light_onoff_status_s::remaining_time_ms
```

**Details:** Time (in milliseconds) remaining in transition

#### sl_btmesh_evt_lc_client_property_status

Indicate an incoming LC Property Status message, received as a response to [sl_btmesh_lc_client_get_property](sl-btmesh-lc-client#sl-btmesh-lc-client-get-property) or [sl_btmesh_lc_client_set_property](sl-btmesh-lc-client#sl-btmesh-lc-client-set-property). 

##### Modules

[sl_btmesh_evt_lc_client_property_status_s](sl-btmesh-evt-lc-client-property-status-s)

##### Typedefs

###### sl_btmesh_evt_lc_client_property_status_t

`typedef struct sl_btmesh_evt_lc_client_property_status_s sl_btmesh_evt_lc_client_property_status_t`

##### Macros

`#define sl_btmesh_evt_lc_client_property_status_id 0x034c00a8`

**Description**: Identifier of the property_status event.

Data structure of the property_status event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_property_status_s::destination_address
```

**Details:** Address of the client or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_property_status_s::elem_index
```

**Details:** Index of the element for which received the status.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_property_status_s::server_address
```

**Details:** Device which sent the status.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_property_status_s::appkey_index
```

**Details:** Appkey used by server_address.

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_lc_client_property_status_s::property_id
```

**Details:** Property ID

###### property_value (heading level 7)

```
uint8array sl_btmesh_evt_lc_client_property_status_s::property_value
```

**Details:** Property value

### Bluetooth Mesh Light Control Server Model

Bluetooth Mesh Light Control Server Model. 

Bluetooth Mesh Light Control Server model functionality.

All LC Server state resides in and is own by the Model (stack). The state update notification events to the application are informational: the application is not required to react to them. The application may choose to save the LC Server state in persistent storage and set the states in the LC Server following a restart. To do this the application can utilize the notification events and update command.

Each LC Server instance requires that a Lightness Server is initialized in the element preceding the LC Server element: LC Server controls the Lightness Server residing in the preceding element. Each LC Server instance requires that a generic OnOff Server is initialized in the same element as the LC Server. 

#### Modules

[sl_btmesh_evt_lc_server_mode_updated](sl-btmesh-evt-lc-server-mode-updated)

[sl_btmesh_evt_lc_server_om_updated](sl-btmesh-evt-lc-server-om-updated)

[sl_btmesh_evt_lc_server_light_onoff_updated](sl-btmesh-evt-lc-server-light-onoff-updated)

[sl_btmesh_evt_lc_server_occupancy_updated](sl-btmesh-evt-lc-server-occupancy-updated)

[sl_btmesh_evt_lc_server_ambient_lux_level_updated](sl-btmesh-evt-lc-server-ambient-lux-level-updated)

[sl_btmesh_evt_lc_server_linear_output_updated](sl-btmesh-evt-lc-server-linear-output-updated)

[sl_btmesh_evt_lc_server_state_updated](sl-btmesh-evt-lc-server-state-updated)

[sl_btmesh_evt_lc_server_regulator_debug_info](sl-btmesh-evt-lc-server-regulator-debug-info)

#### Enumerations

##### sl_btmesh_lc_server_lc_state_t

```
enum sl_btmesh_lc_server_lc_state_t {
    sl_btmesh_lc_server_lc_state_off = 0x0
    sl_btmesh_lc_server_lc_state_standby = 0x1
    sl_btmesh_lc_server_lc_state_fade_on = 0x2
    sl_btmesh_lc_server_lc_state_run = 0x3
    sl_btmesh_lc_server_lc_state_fade = 0x4
    sl_btmesh_lc_server_lc_state_prolong = 0x5
    sl_btmesh_lc_server_lc_state_fade_standby_auto = 0x6
    sl_btmesh_lc_server_lc_state_fade_standby_manual = 0x7
}
```

**Description:**

These values define the possible states of Light Controller.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_lc_server_lc_state_off|(0x0) The controller is turned off and does not control lighting.|
|sl_btmesh_lc_server_lc_state_standby|(0x1) The controller is turned on and awaits an event from an occupancy sensor or a manual switch.|
|sl_btmesh_lc_server_lc_state_fade_on|(0x2) The controller has been triggered and gradually transitions to the Run phase, gradually dimming the lights up.>|
|sl_btmesh_lc_server_lc_state_run|(0x3) The lights are on and the timer counts down (but may be re-triggered by a sensor or a switch event).|
|sl_btmesh_lc_server_lc_state_fade|(0x4) The Run timer has expired and the controller gradually transitions to the Prolong state.|
|sl_btmesh_lc_server_lc_state_prolong|(0x5) The lights are at a lower level and the timer counts down (but may be re-triggered by a sensor or a switch event).|
|sl_btmesh_lc_server_lc_state_fade_standby_auto|(0x6) The controller gradually returns to the Standby state|
|sl_btmesh_lc_server_lc_state_fade_standby_manual|(0x7) The controller gradually returns to the Standby state after external event.|

##### sl_btmesh_lc_server_lc_debug_events_t

```
enum sl_btmesh_lc_server_lc_debug_events_t {
    sl_btmesh_lc_server_lc_event_state_updated = 0x1
    sl_btmesh_lc_server_lc_event_regulator_debug_info = 0x2
}
```

**Description:**

These values identify optional diagnostic events that provide more information to the application about LC behavior.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_lc_server_lc_event_state_updated|(0x1) Event reporting LC Server state machine state changes along with the remaining state timer.|
|sl_btmesh_lc_server_lc_event_regulator_debug_info|(0x2) Event reporting LC Server PI regulator integral term and regulator output.|

##### sl_btmesh_lc_server_lc_regulator_mode_t

```
enum sl_btmesh_lc_server_lc_regulator_mode_t {
    sl_btmesh_lc_server_lc_regulator_disabled = 0x0
    sl_btmesh_lc_server_lc_regulator_conditional = 0x1
    sl_btmesh_lc_server_lc_regulator_enabled = 0x2
}
```

**Description:**

These values define the regulator PI calculation mode. If the regulator is disabled, the output only depends on the configured lightness levels. Ignoring PI is non-standard behavior and should only be used for debugging purposes. If conitionally enabled, the regulator output is adjusted based on the sensor input, if available. This is default state. The conditionality permits a fallback to the disabled mode, which is the modus operandi in 1.1 and before. If permanently enabled, the regulator always adjusts the output based on the sensor input, even if it is zero, which will push the output to its maximum. This behavior has been introduced in Mesh 1.1.1 and should be used with caution, as the Test Specification is not yet updated to reflect this.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_lc_server_lc_regulator_disabled|(0x0) Regulator permanently disabled.|
|sl_btmesh_lc_server_lc_regulator_conditional|(0x1) Regulator conditionally enabled - only when sensor input is available (default).|
|sl_btmesh_lc_server_lc_regulator_enabled|(0x2) Regulator permanently enabled.|

#### Functions

##### sl_btmesh_lc_server_init

`sl_status_t sl_btmesh_lc_server_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

Initialize the LC Server model. The server does not have any internal configuration. The command only activates the model in the mesh stack.

Each LC Server instance requires that a Lightness Server is initialized in the element preceding the LC Server element: LC Server controls the Lightness Server residing in the preceding element. Each LC Server instance requires that a generic OnOff Server is initialized in the same element as the LC Server.

LC properties are initialized as follows:

PropertyID: PropertyValue 0x002B: 0x111111, 0x002C: 0x011111, 0x002D: 0x001111, 0x002E: 0xf000, 0x002F: 0x0f00, 0x0030: 0x00f0, 0x031: 50, 0x032: 25.0, 0x0033: 250.0, 0x0034: 80.0, 0x0035: 80.0, 0x0036: 3000, 0x0037: 3000, 0x0038: 3000, 0x0039: 3000, 0x003A: 0, 0x003B: 3000, 0x003C: 3000

PI Regulator interval (T) is initialized to 50ms

The rest of the state values are initialized to zero

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_deinit

`sl_status_t sl_btmesh_lc_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

De-initializes the LC Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_update_mode

`sl_status_t sl_btmesh_lc_server_update_mode(uint16_t elem_index, uint8_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint8_t|[in]|mode|Mode value. Valid range: 0-1.|

Update the LC Server model Mode state in the stack. Application may choose to directly set the model state in the stack, this function will pass the state value to the LC Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_update_om

`sl_status_t sl_btmesh_lc_server_update_om(uint16_t elem_index, uint8_t om)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint8_t|[in]|om|Occupancy Mode value. Valid range: 0-1.|

Update the LC Server model Occupancy Mode state in the stack. The application may choose to directly set the model state in the stack. This function will pass the state value to the LC Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_update_light_onoff

`sl_status_t sl_btmesh_lc_server_update_light_onoff(uint16_t elem_index, uint8_t light_onoff, uint32_t transition_time_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint8_t|[in]|light_onoff|Light OnOff value. Valid range: 0-1.|
|uint32_t|[in]|transition_time_ms|Amount of time (in milliseconds) that the element will take to transition to the target state from the present state. If set to 0, the transition will be immediate.|

Update the LC Server model Light OnOff state in the stack. The application may choose to directly set the model state in the stack. This function will pass the state value to the LC Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_init_all_properties

`sl_status_t sl_btmesh_lc_server_init_all_properties(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

Initialize all LC properties in one attempt. The following values are used:

PropertyID: PropertyValue 0x002B: 0x111111, 0x002C: 0x011111, 0x002D: 0x001111, 0x002E: 0xf000, 0x002F: 0x0f00, 0x0030: 0x00f0, 0x031: 50, 0x032: 25.0, 0x0033: 250.0, 0x0034: 80.0, 0x0035: 80.0, 0x0036: 3000, 0x0037: 3000, 0x0038: 3000, 0x0039: 3000, 0x003A: 0, 0x003B: 3000, 0x003C: 3000

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_set_publish_mask

`SL_BGAPI_DEPRECATED sl_status_t sl_btmesh_lc_server_set_publish_mask(uint16_t elem_index, uint16_t status_type, uint8_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint16_t|[in]|status_type|The type of status message to turn on/off. Options for this are:<br/><br/>LC Mode Status 0x8294 LC Occupancy Mode Status 0x8298 LC Light On Off Status 0x829C|
|uint8_t|[in]|value|Turn on or off the status message. Non zero - enable, otherwise disable.|

Update the bitmask that controls which messages are sent when the LC Server publishes. By default, the bitmask will be enabled to publish a Light LC Light OnOff Status message. This is a deprecated function. The LC Server is intended to publish only Light LC Light OnOff Status message when the Light LC State Machine Light OnOff state changes, so this function should not be used.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_set_regulator_interval

`sl_status_t sl_btmesh_lc_server_set_regulator_interval(uint16_t elem_index, uint8_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint8_t|[in]|value|Valid values are 1 ms-100 ms. (Default: 50 ms)|

Update the summation interval (T) at which the PI regulator is run. Only valid when the regulator is disabled (Light LC Mode is 0).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_set_event_mask

`sl_status_t sl_btmesh_lc_server_set_event_mask(uint16_t elem_index, uint16_t event_type, uint8_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint16_t|[in]|event_type|The type of event to enable/disable. Options are:<br/><br/>lc_event_state_updated = 0x01, state_updated event report state changes lc_event_regulator_debug_info = 0x02, regulator_debug_info Regulator calculation details|
|uint8_t|[in]|value|Valid values are 0 and 1 to disable or enable the event|

Enable or disable additional diagnostics events. See lc_debug_events.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_get_lc_state

`sl_status_t sl_btmesh_lc_server_get_lc_state(uint16_t elem_index, uint8_t *state, uint32_t *transition_time)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint8_t *|[out]|state|The current state of LC state machine|
|uint32_t *|[out]|transition_time|Transition time left for the current LC state.|

Fetch the current LC state. States can be as Off, Standby, Fade On, Run, Fade, Prolong, Fade Standby Auto, Fade Standby Manual

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_set_regulator_mode

`sl_status_t sl_btmesh_lc_server_set_regulator_mode(uint16_t elem_index, uint8_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint8_t|[in]|mode|Enum [sl_btmesh_lc_server_lc_regulator_mode_t](sl-btmesh-lc-server#sl-btmesh-lc-server-lc-regulator-mode-t). Regulator mode:<br/><br/>lc_regulator_disabled (0) - Permanently disabled lc_regulator_conditional (1) - Enabled when sensor input available (default) lc_regulator_enabled (2) - Permanently enabled|

Set the regulator mode (disabled, conditional, or enabled). This controls whether the LC regulator PI calculation is permanently disabled, conditionally enabled (only when sensor input is available), or permanently enabled.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lc_server_set_sensor_timeout

`sl_status_t sl_btmesh_lc_server_set_sensor_timeout(uint16_t elem_index, uint32_t timeout_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|
|uint32_t|[in]|timeout_ms|Timeout period in milliseconds (must be non-zero, default: 5000ms).|

Set the sensor timeout period. If no sensor status message is received within this period, the sensor is considered disconnected and the ambient lux level is cleared to zero.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_lc_server_init_id 0x004d0028`

`#define sl_btmesh_cmd_lc_server_deinit_id 0x014d0028`

`#define sl_btmesh_cmd_lc_server_update_mode_id 0x024d0028`

`#define sl_btmesh_cmd_lc_server_update_om_id 0x034d0028`

`#define sl_btmesh_cmd_lc_server_update_light_onoff_id 0x044d0028`

`#define sl_btmesh_cmd_lc_server_init_all_properties_id 0x054d0028`

`#define sl_btmesh_cmd_lc_server_set_publish_mask_id 0x064d0028`

`#define sl_btmesh_cmd_lc_server_set_regulator_interval_id 0x074d0028`

`#define sl_btmesh_cmd_lc_server_set_event_mask_id 0x084d0028`

`#define sl_btmesh_cmd_lc_server_get_lc_state_id 0x094d0028`

`#define sl_btmesh_cmd_lc_server_set_regulator_mode_id 0x0a4d0028`

`#define sl_btmesh_cmd_lc_server_set_sensor_timeout_id 0x0b4d0028`

`#define sl_btmesh_rsp_lc_server_init_id 0x004d0028`

`#define sl_btmesh_rsp_lc_server_deinit_id 0x014d0028`

`#define sl_btmesh_rsp_lc_server_update_mode_id 0x024d0028`

`#define sl_btmesh_rsp_lc_server_update_om_id 0x034d0028`

`#define sl_btmesh_rsp_lc_server_update_light_onoff_id 0x044d0028`

`#define sl_btmesh_rsp_lc_server_init_all_properties_id 0x054d0028`

`#define sl_btmesh_rsp_lc_server_set_publish_mask_id 0x064d0028`

`#define sl_btmesh_rsp_lc_server_set_regulator_interval_id 0x074d0028`

`#define sl_btmesh_rsp_lc_server_set_event_mask_id 0x084d0028`

`#define sl_btmesh_rsp_lc_server_get_lc_state_id 0x094d0028`

`#define sl_btmesh_rsp_lc_server_set_regulator_mode_id 0x0a4d0028`

`#define sl_btmesh_rsp_lc_server_set_sensor_timeout_id 0x0b4d0028`

#### sl_btmesh_evt_lc_server_mode_updated

LC Mode state has been updated. 

The update could be triggered by a reception of a client message or by an LC Server State Machine action. 

##### Modules

[sl_btmesh_evt_lc_server_mode_updated_s](sl-btmesh-evt-lc-server-mode-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_mode_updated_t

`typedef struct sl_btmesh_evt_lc_server_mode_updated_s sl_btmesh_evt_lc_server_mode_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_mode_updated_id 0x004d00a8`

**Description**: Identifier of the mode_updated event.

Data structure of the mode_updated event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_mode_updated_s::destination_address
```

**Details:** Message destination address if triggered by a message, 0 otherwise.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_mode_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_mode_updated_s::client_address
```

**Details:** Message source address if triggered by a message, 0 otherwise.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_mode_updated_s::appkey_index
```

**Details:** Message appkey index if triggered by a message, 0xFFFF otherwise.

###### mode_value (heading level 7)

```
uint8_t sl_btmesh_evt_lc_server_mode_updated_s::mode_value
```

**Details:** The value the LC Mode state is being set to.

###### manual_override (heading level 7)

```
uint8_t sl_btmesh_evt_lc_server_mode_updated_s::manual_override
```

**Details:** Light Control Mode state can be set to zero by a binding from Light Lightness Linear when it is modified by an action from the application or a Light Lightness Client command. In this case, the parameter is set to 0x01. In all other cases, this parameter is zero. For example, when LC Mode is modified by the application or by a LC Client command, this parameter will be set to 0.

#### sl_btmesh_evt_lc_server_om_updated

LC Occupancy Mode state has been updated. 

The update could be triggered by a reception of a client message or by an LC Server State Machine action. 

##### Modules

[sl_btmesh_evt_lc_server_om_updated_s](sl-btmesh-evt-lc-server-om-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_om_updated_t

`typedef struct sl_btmesh_evt_lc_server_om_updated_s sl_btmesh_evt_lc_server_om_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_om_updated_id 0x014d00a8`

**Description**: Identifier of the om_updated event.

Data structure of the om_updated event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_om_updated_s::destination_address
```

**Details:** Message destination address if triggered by a message, 0 otherwise.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_om_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_om_updated_s::client_address
```

**Details:** Message source address if triggered by a message, 0 otherwise.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_om_updated_s::appkey_index
```

**Details:** Message appkey index if triggered by a message, 0xFFFF otherwise.

###### om_value (heading level 7)

```
uint8_t sl_btmesh_evt_lc_server_om_updated_s::om_value
```

**Details:** The value the LC Occupancy Mode state is being set to.

#### sl_btmesh_evt_lc_server_light_onoff_updated

LC Light OnOff state has been updated. 

The update could be triggered by a reception of a client message or by an LC Server State Machine action. 

##### Modules

[sl_btmesh_evt_lc_server_light_onoff_updated_s](sl-btmesh-evt-lc-server-light-onoff-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_light_onoff_updated_t

`typedef struct sl_btmesh_evt_lc_server_light_onoff_updated_s sl_btmesh_evt_lc_server_light_onoff_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_light_onoff_updated_id 0x024d00a8`

**Description**: Identifier of the light_onoff_updated event.

Data structure of the light_onoff_updated event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_light_onoff_updated_s::destination_address
```

**Details:** Message destination address if triggered by a message, 0 otherwise.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_light_onoff_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### source_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_light_onoff_updated_s::source_address
```

**Details:** Message source address if triggered by a message, 0 otherwise.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_light_onoff_updated_s::appkey_index
```

**Details:** Message appkey index if triggered by a message, 0xFFFF otherwise.

###### onoff_state (heading level 7)

```
uint8_t sl_btmesh_evt_lc_server_light_onoff_updated_s::onoff_state
```

**Details:** The target value of the Light LC Light OnOff state.

###### onoff_trans_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_lc_server_light_onoff_updated_s::onoff_trans_time_ms
```

**Details:** Amount of time (in milliseconds) the element will take to transition to the target state from the present state.

#### sl_btmesh_evt_lc_server_occupancy_updated

LC Occupancy state has been updated. 

The update could be triggered by a reception of a sensor message or by an LC Server State Machine action. 

##### Modules

[sl_btmesh_evt_lc_server_occupancy_updated_s](sl-btmesh-evt-lc-server-occupancy-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_occupancy_updated_t

`typedef struct sl_btmesh_evt_lc_server_occupancy_updated_s sl_btmesh_evt_lc_server_occupancy_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_occupancy_updated_id 0x034d00a8`

**Description**: Identifier of the occupancy_updated event.

Data structure of the occupancy_updated event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_occupancy_updated_s::destination_address
```

**Details:** Message destination address if triggered by a message, 0 otherwise.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_occupancy_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### source_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_occupancy_updated_s::source_address
```

**Details:** Message source address if triggered by a message, 0 otherwise.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_occupancy_updated_s::appkey_index
```

**Details:** Message appkey index if triggered by a message, 0xFFFF otherwise.

###### occupancy_value (heading level 7)

```
uint8_t sl_btmesh_evt_lc_server_occupancy_updated_s::occupancy_value
```

**Details:** The updated value of the LC Occupancy state

#### sl_btmesh_evt_lc_server_ambient_lux_level_updated

LC Ambient LuxLevel state has been updated. 

The update is triggered by a reception of a sensor message. 

##### Modules

[sl_btmesh_evt_lc_server_ambient_lux_level_updated_s](sl-btmesh-evt-lc-server-ambient-lux-level-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_ambient_lux_level_updated_t

`typedef struct sl_btmesh_evt_lc_server_ambient_lux_level_updated_s sl_btmesh_evt_lc_server_ambient_lux_level_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_ambient_lux_level_updated_id 0x044d00a8`

**Description**: Identifier of the ambient_lux_level_updated event.

Data structure of the ambient_lux_level_updated event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_ambient_lux_level_updated_s::destination_address
```

**Details:** Message destination address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_ambient_lux_level_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### source_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_ambient_lux_level_updated_s::source_address
```

**Details:** Message source address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_ambient_lux_level_updated_s::appkey_index
```

**Details:** Message appkey index

###### ambient_lux_level_value (heading level 7)

```
uint32_t sl_btmesh_evt_lc_server_ambient_lux_level_updated_s::ambient_lux_level_value
```

**Details:** The updated value of the LC Ambient LuxLevel state

#### sl_btmesh_evt_lc_server_linear_output_updated

LC Linear Output state has been updated. 

The update is triggered by an LC Server State Machine action. 

##### Modules

[sl_btmesh_evt_lc_server_linear_output_updated_s](sl-btmesh-evt-lc-server-linear-output-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_linear_output_updated_t

`typedef struct sl_btmesh_evt_lc_server_linear_output_updated_s sl_btmesh_evt_lc_server_linear_output_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_linear_output_updated_id 0x054d00a8`

**Description**: Identifier of the linear_output_updated event.

Data structure of the linear_output_updated event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_linear_output_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### linear_output_value (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_linear_output_updated_s::linear_output_value
```

**Details:** The updated value of the LC Linear Output state

#### sl_btmesh_evt_lc_server_state_updated

LC state machine state has been updated. 

The update is triggered by LC mode switching on or off and transitions between phases. 

##### Modules

[sl_btmesh_evt_lc_server_state_updated_s](sl-btmesh-evt-lc-server-state-updated-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_state_updated_t

`typedef struct sl_btmesh_evt_lc_server_state_updated_s sl_btmesh_evt_lc_server_state_updated_t`

##### Macros

`#define sl_btmesh_evt_lc_server_state_updated_id 0x064d00a8`

**Description**: Identifier of the state_updated event.

Data structure of the state_updated event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_state_updated_s::elem_index
```

**Details:** Index of the element where the update happened

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_lc_server_state_updated_s::state
```

**Details:** The updated value of the LC state

###### transition_time (heading level 7)

```
uint32_t sl_btmesh_evt_lc_server_state_updated_s::transition_time
```

**Details:** Transition time defined for the current LC state.

#### sl_btmesh_evt_lc_server_regulator_debug_info

LC regulator calculation details. 

##### Modules

[sl_btmesh_evt_lc_server_regulator_debug_info_s](sl-btmesh-evt-lc-server-regulator-debug-info-s)

##### Typedefs

###### sl_btmesh_evt_lc_server_regulator_debug_info_t

`typedef struct sl_btmesh_evt_lc_server_regulator_debug_info_s sl_btmesh_evt_lc_server_regulator_debug_info_t`

##### Macros

`#define sl_btmesh_evt_lc_server_regulator_debug_info_id 0x074d00a8`

**Description**: Identifier of the regulator_debug_info event.

Data structure of the regulator_debug_info event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_regulator_debug_info_s::elem_index
```

**Details:** Index of the element where LC server is located

###### i (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_regulator_debug_info_s::i
```

**Details:** Integral term

###### l (heading level 7)

```
uint16_t sl_btmesh_evt_lc_server_regulator_debug_info_s::l
```

**Details:** Regulator output

### Bluetooth Mesh Light Control Setup Server Model

Bluetooth Mesh Light Control Setup Server Model. 

Bluetooth Mesh Light Control model Setup Server functionality.

This class provides the API that the LC Setup server uses to inform the application of its received events. The API is informational: application is not required to react to these events. 

#### Modules

[sl_btmesh_evt_lc_setup_server_set_property](sl-btmesh-evt-lc-setup-server-set-property)

#### Functions

##### sl_btmesh_lc_setup_server_update_property

`sl_status_t sl_btmesh_lc_setup_server_update_property(uint16_t elem_index, uint16_t property_id, size_t params_len, const uint8_t *params)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|property_id|Property ID for the LC Server. Range: 0x0001 - 0x0ffff for a specific device property, the value 0x0000 is prohibited.|
|size_t|[in]|params_len|Length of data in `params`|
|const uint8_t *|[in]|params|Byte array containing serialized fields of LC Property, excluding the property ID|

Update the LC Server property. The application may choose to directly set model properties in the stack. This function will pass the property value to the LC Setup Server and on to the LC Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_lc_setup_server_update_property_id 0x004e0028`

`#define sl_btmesh_rsp_lc_setup_server_update_property_id 0x004e0028`

#### sl_btmesh_evt_lc_setup_server_set_property

LC Property Set from the Client. 

##### Modules

[sl_btmesh_evt_lc_setup_server_set_property_s](sl-btmesh-evt-lc-setup-server-set-property-s)

##### Typedefs

###### sl_btmesh_evt_lc_setup_server_set_property_t

`typedef struct sl_btmesh_evt_lc_setup_server_set_property_s sl_btmesh_evt_lc_setup_server_set_property_t`

##### Macros

`#define sl_btmesh_evt_lc_setup_server_set_property_id 0x004e00a8`

**Description**: Identifier of the set_property event.

Data structure of the set_property event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_setup_server_set_property_s::destination_address
```

**Details:** Address of the server or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_setup_server_set_property_s::elem_index
```

**Details:** Index of the element which received the command.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_lc_setup_server_set_property_s::client_address
```

**Details:** Device which sent the request.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_lc_setup_server_set_property_s::appkey_index
```

**Details:** Appkey used by client_address.

###### property_id (heading level 7)

```
uint16_t sl_btmesh_evt_lc_setup_server_set_property_s::property_id
```

**Details:** Property ID

###### property_value (heading level 7)

```
uint8array sl_btmesh_evt_lc_setup_server_set_property_s::property_value
```

**Details:** Property value

### Bluetooth Mesh Scene Client Model

Bluetooth Mesh Scene Client Model. 

Bluetooth Mesh Scene Client model functionality to send and receive messages to/from the Scene Server and Scene Setup Server models.

Throughout the API, the client model that is used is identified by its element address and model ID, while the server model responding to the client model requests is identified by its element address and model ID.

The API has functions for querying server model states and requesting server model state changes. 

#### Modules

[sl_btmesh_evt_scene_client_status](sl-btmesh-evt-scene-client-status)

[sl_btmesh_evt_scene_client_register_status](sl-btmesh-evt-scene-client-register-status)

#### Functions

##### sl_btmesh_scene_client_init

`sl_status_t sl_btmesh_scene_client_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the client element.|

Initialize the Scene Client model. The Scene Client does not have any internal configuration. It only activates the model in the mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scene_client_get

`sl_status_t sl_btmesh_scene_client_get(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Device to be queried. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Index of the client element.|
|uint16_t|[in]|appkey_index|Appkey used by server_address.|

Scene Get command.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scene_client_status](sl-btmesh-evt-scene-client-status)

##### sl_btmesh_scene_client_get_register

`sl_status_t sl_btmesh_scene_client_get_register(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|

Scene Register Get command

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scene_client_register_status](sl-btmesh-evt-scene-client-register-status)

##### sl_btmesh_scene_client_recall

`sl_status_t sl_btmesh_scene_client_recall(uint16_t server_address, uint16_t elem_index, uint16_t selected_scene, uint16_t appkey_index, uint8_t flags, uint8_t tid, uint32_t transition_time_ms, uint16_t delay_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to model configuration|
|uint16_t|[in]|elem_index|Index of the client element.|
|uint16_t|[in]|selected_scene|Scene of interest|
|uint16_t|[in]|appkey_index|Appkey used by server_address.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET PROPERTY message will be sent, zero will send SET PROPERTY UNACKNOWLEDGED|
|uint8_t|[in]|tid|Transaction ID|
|uint32_t|[in]|transition_time_ms|Amount of time (in milliseconds) allotted for the transition to take place. Value of 0xFFFFFFFF will cause this parameter as well as the "delay" parameter to be omitted. The transition will be immediate if both the transition time and the delay are zero.|
|uint16_t|[in]|delay_ms|Message execution delay in milliseconds. If the "transition_time" is 0xFFFFFFFF, this parameter is ignored. If both the transition time and the delay are zero, the transition is immediate. Valid range: 0-1275.|

Recall a scene.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scene_client_status](sl-btmesh-evt-scene-client-status)

##### sl_btmesh_scene_client_store

`sl_status_t sl_btmesh_scene_client_store(uint16_t server_address, uint16_t elem_index, uint16_t selected_scene, uint16_t appkey_index, uint8_t flags)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|selected_scene|Scene of interest|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET PROPERTY message will be sent. Zero will send SET PROPERTY UNACKNOWLEDGED.|

Store a scene.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scene_client_register_status](sl-btmesh-evt-scene-client-register-status)

##### sl_btmesh_scene_client_delete

`sl_status_t sl_btmesh_scene_client_delete(uint16_t server_address, uint16_t elem_index, uint16_t selected_scene, uint16_t appkey_index, uint8_t flags)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address. The address 0x0000 can be used to publish the message according to the model configuration.|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|selected_scene|Scene of interest|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required. If set to 1, SET PROPERTY message will be sent. Zero will send SET PROPERTY UNACKNOWLEDGED.|

Delete a scene.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scene_client_register_status](sl-btmesh-evt-scene-client-register-status)

##### sl_btmesh_scene_client_deinit

`sl_status_t sl_btmesh_scene_client_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the client element.|

Deinitialize the Scene Client model. This deactivates the model in the mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_scene_client_init_id 0x004f0028`

`#define sl_btmesh_cmd_scene_client_get_id 0x014f0028`

`#define sl_btmesh_cmd_scene_client_get_register_id 0x024f0028`

`#define sl_btmesh_cmd_scene_client_recall_id 0x034f0028`

`#define sl_btmesh_cmd_scene_client_store_id 0x044f0028`

`#define sl_btmesh_cmd_scene_client_delete_id 0x054f0028`

`#define sl_btmesh_cmd_scene_client_deinit_id 0x064f0028`

`#define sl_btmesh_rsp_scene_client_init_id 0x004f0028`

`#define sl_btmesh_rsp_scene_client_get_id 0x014f0028`

`#define sl_btmesh_rsp_scene_client_get_register_id 0x024f0028`

`#define sl_btmesh_rsp_scene_client_recall_id 0x034f0028`

`#define sl_btmesh_rsp_scene_client_store_id 0x044f0028`

`#define sl_btmesh_rsp_scene_client_delete_id 0x054f0028`

`#define sl_btmesh_rsp_scene_client_deinit_id 0x064f0028`

#### sl_btmesh_evt_scene_client_status

Event indicating an incoming Scene Status message, response to [sl_btmesh_scene_client_get](sl-btmesh-scene-client#sl-btmesh-scene-client-get) or [sl_btmesh_scene_client_recall](sl-btmesh-scene-client#sl-btmesh-scene-client-recall) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_scene_client_status_s](sl-btmesh-evt-scene-client-status-s)

##### Typedefs

###### sl_btmesh_evt_scene_client_status_t

`typedef struct sl_btmesh_evt_scene_client_status_s sl_btmesh_evt_scene_client_status_t`

##### Macros

`#define sl_btmesh_evt_scene_client_status_id 0x004f00a8`

**Description**: Identifier of the status event.

Data structure of the status event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_status_s::destination_address
```

**Details:** Address of the client or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_status_s::elem_index
```

**Details:** Index of the element which received the status.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_status_s::server_address
```

**Details:** Device which sent the status.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_status_s::appkey_index
```

**Details:** Appkey used by client_address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_scene_client_status_s::status
```

**Details:** Status of the request.

###### current_scene (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_status_s::current_scene
```

**Details:** Currently selected scene.

###### target_scene (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_status_s::target_scene
```

**Details:** Scene to be transitioning to.

###### remaining_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scene_client_status_s::remaining_time_ms
```

**Details:** Time (in milliseconds) remaining in transition.

#### sl_btmesh_evt_scene_client_register_status

Event indicating an incoming Scene Register Status message, response to [sl_btmesh_scene_client_get_register](sl-btmesh-scene-client#sl-btmesh-scene-client-get-register) or [sl_btmesh_scene_client_store](sl-btmesh-scene-client#sl-btmesh-scene-client-store) or [sl_btmesh_scene_client_delete](sl-btmesh-scene-client#sl-btmesh-scene-client-delete) command. 

##### Modules

[sl_btmesh_evt_scene_client_register_status_s](sl-btmesh-evt-scene-client-register-status-s)

##### Typedefs

###### sl_btmesh_evt_scene_client_register_status_t

`typedef struct sl_btmesh_evt_scene_client_register_status_s sl_btmesh_evt_scene_client_register_status_t`

##### Macros

`#define sl_btmesh_evt_scene_client_register_status_id 0x014f00a8`

**Description**: Identifier of the register_status event.

Data structure of the register_status event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_register_status_s::destination_address
```

**Details:** Address of the client or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_register_status_s::elem_index
```

**Details:** Index of the element for which received the status.

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_register_status_s::server_address
```

**Details:** Device which sent the status.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_register_status_s::appkey_index
```

**Details:** Appkey used by client_address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_scene_client_register_status_s::status
```

**Details:** Status of the request.

###### current_scene (heading level 7)

```
uint16_t sl_btmesh_evt_scene_client_register_status_s::current_scene
```

**Details:** Currently selected scene.

###### scenes (heading level 7)

```
uint8array sl_btmesh_evt_scene_client_register_status_s::scenes
```

**Details:** List of stored scenes on the server derived from the Scene Register. It contains a variable length array of 16-bit values representing Scene Numbers in little endian format.

### Bluetooth Mesh Scene Server Model

Bluetooth Mesh Scene Server Model. 

Bluetooth Mesh Scene model Server functionality. 

#### Modules

[sl_btmesh_evt_scene_server_get](sl-btmesh-evt-scene-server-get)

[sl_btmesh_evt_scene_server_register_get](sl-btmesh-evt-scene-server-register-get)

[sl_btmesh_evt_scene_server_recall](sl-btmesh-evt-scene-server-recall)

[sl_btmesh_evt_scene_server_publish](sl-btmesh-evt-scene-server-publish)

[sl_btmesh_evt_scene_server_compact_recall](sl-btmesh-evt-scene-server-compact-recall)

#### Functions

##### sl_btmesh_scene_server_init

`sl_status_t sl_btmesh_scene_server_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

Initialize the Scene Server model. Server does not have any internal configurations. The command only activates the model in the mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scene_server_deinit

`sl_status_t sl_btmesh_scene_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

De-initializes the Scene Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scene_server_reset_register

`sl_status_t sl_btmesh_scene_server_reset_register(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element. This can be either element of the updated model or the element of the scene model responsible for controlling the scene of the updated model.|

Reset register value. This command should be invoked if state of a model has been modified in such a manner that it can't be in the scene, which is indicated by the scene register.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scene_server_enable_compact_recall_events

`sl_status_t sl_btmesh_scene_server_enable_compact_recall_events(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Switch to compact reporting for recalled states. Compact state reduces amount buffering memory needed by the scene recall and is recommended for devices with big amount of models or for devices in environment with lots of bluetooth advertisement traffic.

When compact mode is active [sl_btmesh_evt_scene_server_compact_recall](sl-btmesh-evt-scene-server-compact-recall) is generated instead of several [sl_btmesh_evt_generic_server_state_recall](sl-btmesh-evt-generic-server-state-recall) events.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_scene_server_init_id 0x00500028`

`#define sl_btmesh_cmd_scene_server_deinit_id 0x01500028`

`#define sl_btmesh_cmd_scene_server_reset_register_id 0x02500028`

`#define sl_btmesh_cmd_scene_server_enable_compact_recall_events_id 0x03500028`

`#define sl_btmesh_rsp_scene_server_init_id 0x00500028`

`#define sl_btmesh_rsp_scene_server_deinit_id 0x01500028`

`#define sl_btmesh_rsp_scene_server_reset_register_id 0x02500028`

`#define sl_btmesh_rsp_scene_server_enable_compact_recall_events_id 0x03500028`

#### sl_btmesh_evt_scene_server_get

Get the status. 

##### Modules

[sl_btmesh_evt_scene_server_get_s](sl-btmesh-evt-scene-server-get-s)

##### Typedefs

###### sl_btmesh_evt_scene_server_get_t

`typedef struct sl_btmesh_evt_scene_server_get_s sl_btmesh_evt_scene_server_get_t`

##### Macros

`#define sl_btmesh_evt_scene_server_get_id 0x015000a8`

**Description**: Identifier of the get event.

Data structure of the get event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_get_s::destination_address
```

**Details:** Address of the server or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_get_s::elem_index
```

**Details:** Index of the element which received the command.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_get_s::client_address
```

**Details:** Device which sent the request.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_get_s::appkey_index
```

**Details:** Appkey used by client_address.

#### sl_btmesh_evt_scene_server_register_get

Get the status of a register. 

##### Modules

[sl_btmesh_evt_scene_server_register_get_s](sl-btmesh-evt-scene-server-register-get-s)

##### Typedefs

###### sl_btmesh_evt_scene_server_register_get_t

`typedef struct sl_btmesh_evt_scene_server_register_get_s sl_btmesh_evt_scene_server_register_get_t`

##### Macros

`#define sl_btmesh_evt_scene_server_register_get_id 0x025000a8`

**Description**: Identifier of the register_get event.

Data structure of the register_get event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_register_get_s::destination_address
```

**Details:** Address of the server or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_register_get_s::elem_index
```

**Details:** Index of the element which received the command.

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_register_get_s::client_address
```

**Details:** Device which sent the request.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_register_get_s::appkey_index
```

**Details:** Appkey used by client_address.

#### sl_btmesh_evt_scene_server_recall

Recall a scene. 

##### Modules

[sl_btmesh_evt_scene_server_recall_s](sl-btmesh-evt-scene-server-recall-s)

##### Typedefs

###### sl_btmesh_evt_scene_server_recall_t

`typedef struct sl_btmesh_evt_scene_server_recall_s sl_btmesh_evt_scene_server_recall_t`

##### Macros

`#define sl_btmesh_evt_scene_server_recall_id 0x035000a8`

**Description**: Identifier of the recall event.

Data structure of the recall event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_recall_s::destination_address
```

**Details:** Address of the server or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_recall_s::elem_index
```

**Details:** Index of the element which received the command.

###### selected_scene (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_recall_s::selected_scene
```

**Details:** Scene of interest

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_recall_s::client_address
```

**Details:** Device which sent the request.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_recall_s::appkey_index
```

**Details:** Appkey used by client_address.

###### transition_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scene_server_recall_s::transition_time_ms
```

**Details:** Time (in milliseconds) allotted for the transition to take place

#### sl_btmesh_evt_scene_server_publish

Indicate that the publishing period timer elapsed and the app should/can publish its state or any request. 

##### Modules

[sl_btmesh_evt_scene_server_publish_s](sl-btmesh-evt-scene-server-publish-s)

##### Typedefs

###### sl_btmesh_evt_scene_server_publish_t

`typedef struct sl_btmesh_evt_scene_server_publish_s sl_btmesh_evt_scene_server_publish_t`

##### Macros

`#define sl_btmesh_evt_scene_server_publish_id 0x045000a8`

**Description**: Identifier of the publish event.

Data structure of the publish event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_server_publish_s::elem_index
```

**Details:** Client model element index

###### period_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scene_server_publish_s::period_ms
```

**Details:** The current publishing period that can be used to estimate the next tick, e.g., when the state should be reported at higher frequency.

#### sl_btmesh_evt_scene_server_compact_recall

Recall a scene. 

##### Modules

[sl_btmesh_evt_scene_server_compact_recall_s](sl-btmesh-evt-scene-server-compact-recall-s)

##### Typedefs

###### sl_btmesh_evt_scene_server_compact_recall_t

`typedef struct sl_btmesh_evt_scene_server_compact_recall_s sl_btmesh_evt_scene_server_compact_recall_t`

##### Macros

`#define sl_btmesh_evt_scene_server_compact_recall_id 0x055000a8`

**Description**: Identifier of the compact_recall event.

Data structure of the compact_recall event. 

###### Public Attributes

###### states (heading level 7)

```
uint8array sl_btmesh_evt_scene_server_compact_recall_s::states
```

**Details:** Byte array containind recalled states. Array consist of 5 byte chunks as follows:

- Element id as 16bit unsigned integer in little endian format
- Model id as 16bit unsigned integer in little endian format
- Model-specific state type, identifying the kind of state recalled See get state types list for details.

after this event application can request recalled states with [sl_btmesh_generic_server_get_cached_state](sl-btmesh-generic-server#sl-btmesh-generic-server-get-cached-state) command

### Bluetooth Mesh Scene Setup Server Model

Bluetooth Mesh Scene Setup Server Model. 

Bluetooth Mesh Scene model Setup Server functionality. 

#### Modules

[sl_btmesh_evt_scene_setup_server_store](sl-btmesh-evt-scene-setup-server-store)

[sl_btmesh_evt_scene_setup_server_delete](sl-btmesh-evt-scene-setup-server-delete)

[sl_btmesh_evt_scene_setup_server_publish](sl-btmesh-evt-scene-setup-server-publish)

#### Functions

##### sl_btmesh_scene_setup_server_init

`sl_status_t sl_btmesh_scene_setup_server_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

Initialize the Scene Setup Server model. Server does not have any internal configurations. The command only activates the model in the mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scene_setup_server_deinit

`sl_status_t sl_btmesh_scene_setup_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Index of the element.|

Deinitialize the Scene Setup Server model. This deactivates the model in the mesh stack.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_scene_setup_server_init_id 0x00510028`

`#define sl_btmesh_cmd_scene_setup_server_deinit_id 0x01510028`

`#define sl_btmesh_rsp_scene_setup_server_init_id 0x00510028`

`#define sl_btmesh_rsp_scene_setup_server_deinit_id 0x01510028`

#### sl_btmesh_evt_scene_setup_server_store

Scene Store from the Client. 

##### Modules

[sl_btmesh_evt_scene_setup_server_store_s](sl-btmesh-evt-scene-setup-server-store-s)

##### Typedefs

###### sl_btmesh_evt_scene_setup_server_store_t

`typedef struct sl_btmesh_evt_scene_setup_server_store_s sl_btmesh_evt_scene_setup_server_store_t`

##### Macros

`#define sl_btmesh_evt_scene_setup_server_store_id 0x005100a8`

**Description**: Identifier of the store event.

Data structure of the store event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_store_s::destination_address
```

**Details:** Address of the server or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_store_s::elem_index
```

**Details:** Index of the element which received the command.

###### scene_id (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_store_s::scene_id
```

**Details:** Scene ID

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_store_s::client_address
```

**Details:** Device which sent the request.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_store_s::appkey_index
```

**Details:** Appkey used by client_address.

#### sl_btmesh_evt_scene_setup_server_delete

Scene Delete from the Client. 

##### Modules

[sl_btmesh_evt_scene_setup_server_delete_s](sl-btmesh-evt-scene-setup-server-delete-s)

##### Typedefs

###### sl_btmesh_evt_scene_setup_server_delete_t

`typedef struct sl_btmesh_evt_scene_setup_server_delete_s sl_btmesh_evt_scene_setup_server_delete_t`

##### Macros

`#define sl_btmesh_evt_scene_setup_server_delete_id 0x015100a8`

**Description**: Identifier of the delete event.

Data structure of the delete event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_delete_s::destination_address
```

**Details:** Address of the server or the group address to which it was published.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_delete_s::elem_index
```

**Details:** Index of the element which received the command.

###### scene_id (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_delete_s::scene_id
```

**Details:** Scene ID

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_delete_s::client_address
```

**Details:** Device which sent the request.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_delete_s::appkey_index
```

**Details:** Appkey used by client_address.

#### sl_btmesh_evt_scene_setup_server_publish

Indicate that the publishing period timer elapsed and the app should/can publish its state or any request. 

##### Modules

[sl_btmesh_evt_scene_setup_server_publish_s](sl-btmesh-evt-scene-setup-server-publish-s)

##### Typedefs

###### sl_btmesh_evt_scene_setup_server_publish_t

`typedef struct sl_btmesh_evt_scene_setup_server_publish_s sl_btmesh_evt_scene_setup_server_publish_t`

##### Macros

`#define sl_btmesh_evt_scene_setup_server_publish_id 0x025100a8`

**Description**: Identifier of the publish event.

Data structure of the publish event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scene_setup_server_publish_s::elem_index
```

**Details:** Client model element index

###### period_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scene_setup_server_publish_s::period_ms
```

**Details:** The current publishing period that can be used to estimate the next tick, e.g., when the state should be reported at higher frequency.

### Bluetooth Mesh Scheduler Client Model

Bluetooth Mesh Scheduler Client Model. 

This class provides commands and messages to interface with the Scheduler Client model. Scheduler models uses multiple fields to define the occurrence of an event and the type of event to be triggered.

For the description of these fields, please see [Scheduler Server](#cls_mesh_scheduler_server)

#### Modules

[sl_btmesh_evt_scheduler_client_status](sl-btmesh-evt-scheduler-client-status)

[sl_btmesh_evt_scheduler_client_action_status](sl-btmesh-evt-scheduler-client-action-status)

#### Functions

##### sl_btmesh_scheduler_client_init

`sl_status_t sl_btmesh_scheduler_client_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Initializes the Scheduler Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scheduler_client_deinit

`sl_status_t sl_btmesh_scheduler_client_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Deinitialize the Scheduler Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scheduler_client_get

`sl_status_t sl_btmesh_scheduler_client_get(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|

Send a Scheduler Get message to get the Scheduler Register status of a Scheduler Server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scheduler_client_status](sl-btmesh-evt-scheduler-client-status)

##### sl_btmesh_scheduler_client_get_action

`sl_status_t sl_btmesh_scheduler_client_get_action(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|index|Index of the Scheduler Register entry to get|

Send a Scheduler Action Get message to get action defined by a Schedule Register state entry.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scheduler_client_action_status](sl-btmesh-evt-scheduler-client-action-status)

##### sl_btmesh_scheduler_client_set_action

`sl_status_t sl_btmesh_scheduler_client_set_action(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t flags, uint8_t index, uint8_t year, uint16_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint8_t day_of_week, uint8_t action, uint32_t transition_time_ms, uint16_t scene_number)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|flags|Bit 1 (0x02) defines whether response is required, othewise the unacknowledged message is used.|
|uint8_t|[in]|index|Index of the Scheduler Register entry to set|
|uint8_t|[in]|year|Scheduled year for the action|
|uint16_t|[in]|month|Scheduled month for the action|
|uint8_t|[in]|day|Scheduled day of the month for the action|
|uint8_t|[in]|hour|Scheduled hour for the action|
|uint8_t|[in]|minute|Scheduled minute for the action|
|uint8_t|[in]|second|Scheduled second for the action|
|uint8_t|[in]|day_of_week|Scheduled days of the week for the action|
|uint8_t|[in]|action|Action to be performed at the scheduled time|
|uint32_t|[in]|transition_time_ms|Transition time for this action|
|uint16_t|[in]|scene_number|Scene number to be used for some actions|

Send a Scheduler Action Set message to set the given entry of the Scheduler Register state.

For the description of these fields, see [Scheduler Server](#cls_mesh_scheduler_server)

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_scheduler_client_action_status](sl-btmesh-evt-scheduler-client-action-status)

#### Macros

`#define sl_btmesh_cmd_scheduler_client_init_id 0x00540028`

`#define sl_btmesh_cmd_scheduler_client_deinit_id 0x01540028`

`#define sl_btmesh_cmd_scheduler_client_get_id 0x02540028`

`#define sl_btmesh_cmd_scheduler_client_get_action_id 0x03540028`

`#define sl_btmesh_cmd_scheduler_client_set_action_id 0x04540028`

`#define sl_btmesh_rsp_scheduler_client_init_id 0x00540028`

`#define sl_btmesh_rsp_scheduler_client_deinit_id 0x01540028`

`#define sl_btmesh_rsp_scheduler_client_get_id 0x02540028`

`#define sl_btmesh_rsp_scheduler_client_get_action_id 0x03540028`

`#define sl_btmesh_rsp_scheduler_client_set_action_id 0x04540028`

#### sl_btmesh_evt_scheduler_client_status

Scheduler Status event, received as a response to the [sl_btmesh_scheduler_client_get](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-get) command. 

##### Modules

[sl_btmesh_evt_scheduler_client_status_s](sl-btmesh-evt-scheduler-client-status-s)

##### Typedefs

###### sl_btmesh_evt_scheduler_client_status_t

`typedef struct sl_btmesh_evt_scheduler_client_status_s sl_btmesh_evt_scheduler_client_status_t`

##### Macros

`#define sl_btmesh_evt_scheduler_client_status_id 0x005400a8`

**Description**: Identifier of the status event.

Data structure of the status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_status_s::appkey_index
```

**Details:** The application key index to use.

###### scheduler (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_status_s::scheduler
```

**Details:** Bit field indicating defined Actions in the Schedule Register

#### sl_btmesh_evt_scheduler_client_action_status

Scheduler Action Status event, received as a response to the [sl_btmesh_scheduler_client_set_action](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-set-action) or [sl_btmesh_scheduler_client_get_action](sl-btmesh-scheduler-client#sl-btmesh-scheduler-client-get-action) command. 

For the description of these fields, see [Scheduler Server](#cls_mesh_scheduler_server)

##### Modules

[sl_btmesh_evt_scheduler_client_action_status_s](sl-btmesh-evt-scheduler-client-action-status-s)

##### Typedefs

###### sl_btmesh_evt_scheduler_client_action_status_t

`typedef struct sl_btmesh_evt_scheduler_client_action_status_s sl_btmesh_evt_scheduler_client_action_status_t`

##### Macros

`#define sl_btmesh_evt_scheduler_client_action_status_id 0x015400a8`

**Description**: Identifier of the action_status event.

Data structure of the action_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_action_status_s::client_address
```

**Details:** Destination client model address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_action_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_action_status_s::server_address
```

**Details:** Source server model address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_action_status_s::appkey_index
```

**Details:** The application key index to use.

###### index (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::index
```

**Details:** Index of the Scheduler Register

###### year (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::year
```

**Details:** Scheduled year for the action

###### month (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_action_status_s::month
```

**Details:** Scheduled month for the action

###### day (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::day
```

**Details:** Scheduled day of the month for the action

###### hour (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::hour
```

**Details:** Scheduled hour for the action

###### minute (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::minute
```

**Details:** Scheduled minute for the action

###### second (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::second
```

**Details:** Scheduled second for the action

###### day_of_week (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::day_of_week
```

**Details:** Scheduled days of the week for the action

###### action (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_client_action_status_s::action
```

**Details:** Action to be performed at the scheduled time

###### transition_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scheduler_client_action_status_s::transition_time_ms
```

**Details:** Transition time for this action

###### scene_number (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_client_action_status_s::scene_number
```

**Details:** Scene number to be used for some actions

### Bluetooth Mesh Scheduler Server Model

Bluetooth Mesh Scheduler Server Model. 

This class provides commands and messages to interface with the Scheduler Server model

The scheduler server uses multiple fields to define the occurrence of an event and the type of event to be triggered. The field definitions are as follows.

**Year**

The year field represents 2 last significant digits of the year of the occurrence of the scheduled event.

- 0x00-0x63: 2 least significant digits of the year (0-99)
- 0x64: Any year
- All other values are prohibited

**Month**

The month field represents the months of the occurrences of the scheduled event, using a bitfield with one bit for each month.

- Bit 0: Scheduled in January
- Bit 1: February
- Bit 2: March
- Bit 3: April
- Bit 4: May
- Bit 5: June
- Bit 6: July
- Bit 7: August
- Bit 8: September
- Bit 9: October
- Bit 10: November
- Bit 11: December

**Day**

The Day field represents the day of the month of the occurrence of the scheduled event. If the day of the month has a number that is larger than the number of days in the month, the event occurs in the last day of the month. For example, in February if the day field holds the value 29, the action is triggered on February 28th in a non-leap year or February 29th in a leap year.

- 0x00: Any day
- 0x01-0x1F: Day of the month (1-31)
- All other values are prohibited

**Hour**

The Hour field represents the hour of the occurrence of the scheduled event.

- 0x00-0x17: Hour of the day (0-23)
- 0x18: Any hour of the day
- 0x19: Once a day (at a random hour)
- All other values are prohibited

**Minute**

The Minute field represents the minute of the occurrence of the scheduled event.

- 0x00-0x3B: Minute of the hour (0-59)
- 0x3C: Any minute of the hour
- 0x3D: Every 15 minutes (0, 15, 30, 45)
- 0x3E: Every 20 minutes (0, 20, 40)
- 0x3F: Once an hour (at a random minute)
- All other values are prohibited

**Second**

The Second field represents the second of the occurrence of the scheduled event.

- 0x00-0x3B: Seconds of the minute (0-59)
- 0x3C: Any second of the minute
- 0x3D: Every 15 seconds (0, 15, 30, 45)
- 0x3E: Every 20 seconds (0, 20, 40)
- 0x3F: Once a minute (at a random second)
- All other values are prohibited

**Day of Week**

The DayOfWeek field represents the days of the week when the scheduled event will trigger. The week days are represented by a bitfield, by one bit for each day.

- Bit 0: Scheduled on Mondays
- Bit 1: Scheduled on Tuesdays
- Bit 2: Scheduled on Wednesdays
- Bit 3: Scheduled on Thursdays
- Bit 4: Scheduled on Fridays
- Bit 5: Scheduled on Saturdays
- Bit 6: Scheduled on Sundays

**Action**

The action field represents an action to be executed for a scheduled event

- 0x00: Turn Off
- 0x01: Turn On
- 0x02: Scene Recall
- 0x0F: No action
- All other values are prohibited

**Transition time**

This is a 1-octet value that consists of two fields: a 2-bit bit field representing the step resolution and a 6-bit bit field representing the number of transition steps.

Bit 0-1: Transition Step Resolution

- 0b00: The Default Transition Step Resolution is 100 milliseconds
- 0b01: 1 second resolution
- 0b10: 10 seconds resolution
- 0b11: 10 minutes resolution

Bit 2-7: Transition Number of Steps

- 0x00: The Transition Time is immediate
- 0x01-0x3E: The number of steps
- 0x3F: The value is unknown. The state cannot be set to this value, but an element may report an unknown value if a transition is higher than 0x3E or not determined

#### Modules

[sl_btmesh_evt_scheduler_server_action_changed](sl-btmesh-evt-scheduler-server-action-changed)

[sl_btmesh_evt_scheduler_server_scene_changed](sl-btmesh-evt-scheduler-server-scene-changed)

[sl_btmesh_evt_scheduler_server_action_triggered](sl-btmesh-evt-scheduler-server-action-triggered)

#### Functions

##### sl_btmesh_scheduler_server_init

`sl_status_t sl_btmesh_scheduler_server_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Scheduler server model element index|

Initialize the Scheduler Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scheduler_server_deinit

`sl_status_t sl_btmesh_scheduler_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Scheduler server model element index|

Deinitialize the Scheduler Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scheduler_server_get

`sl_status_t sl_btmesh_scheduler_server_get(uint16_t elem_index, uint16_t *status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Scheduler server model element index|
|uint16_t *|[out]|status|Scheduler Server Scheduler Register status|

Get Scheduler Register status of Scheduler Server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scheduler_server_get_action

`sl_status_t sl_btmesh_scheduler_server_get_action(uint16_t elem_index, uint8_t index, uint8_t *index_, uint8_t *year, uint16_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *day_of_week, uint8_t *action, uint32_t *transition_time_ms, uint16_t *scene_number)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Scheduler server model element index|
|uint8_t|[in]|index|Index of the Scheduler Register entry to get|
|uint8_t *|[out]|index_|Index of the Scheduler Register entry to set|
|uint8_t *|[out]|year|Scheduled year for the action|
|uint16_t *|[out]|month|Scheduled month for the action|
|uint8_t *|[out]|day|Scheduled day of the month for the action|
|uint8_t *|[out]|hour|Scheduled hour for the action|
|uint8_t *|[out]|minute|Scheduled minute for the action|
|uint8_t *|[out]|second|Scheduled second for the action|
|uint8_t *|[out]|day_of_week|Scheduled days of the week for the action|
|uint8_t *|[out]|action|Action to be performed at the scheduled time|
|uint32_t *|[out]|transition_time_ms|Transition time for this action|
|uint16_t *|[out]|scene_number|Scene number to be used for some actions|

Get the Scheduler Action defined by a Schedule Register state entry.

For the description of returned fields, see [Scheduler Server](#cls_mesh_scheduler_server)

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_scheduler_server_set_action

`sl_status_t sl_btmesh_scheduler_server_set_action(uint16_t elem_index, uint8_t index, uint8_t year, uint16_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint8_t day_of_week, uint8_t action, uint32_t transition_time_ms, uint16_t scene_number)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Scheduler server model element index|
|uint8_t|[in]|index|Index of the Scheduler Register entry to set|
|uint8_t|[in]|year|Scheduled year for the action|
|uint16_t|[in]|month|Scheduled month for the action|
|uint8_t|[in]|day|Scheduled day of the month for the action|
|uint8_t|[in]|hour|Scheduled hour for the action|
|uint8_t|[in]|minute|Scheduled minute for the action|
|uint8_t|[in]|second|Scheduled second for the action|
|uint8_t|[in]|day_of_week|Scheduled days of the week for the action|
|uint8_t|[in]|action|Action to be performed at the scheduled time|
|uint32_t|[in]|transition_time_ms|Transition time for this action|
|uint16_t|[in]|scene_number|Scene number to be used for some actions|

Set the given Scheduler Action entry of the Scheduler Register state.

For the description of these fields, see [Scheduler Server](#cls_mesh_scheduler_server)

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_scheduler_server_init_id 0x00550028`

`#define sl_btmesh_cmd_scheduler_server_deinit_id 0x01550028`

`#define sl_btmesh_cmd_scheduler_server_get_id 0x02550028`

`#define sl_btmesh_cmd_scheduler_server_get_action_id 0x03550028`

`#define sl_btmesh_cmd_scheduler_server_set_action_id 0x04550028`

`#define sl_btmesh_rsp_scheduler_server_init_id 0x00550028`

`#define sl_btmesh_rsp_scheduler_server_deinit_id 0x01550028`

`#define sl_btmesh_rsp_scheduler_server_get_id 0x02550028`

`#define sl_btmesh_rsp_scheduler_server_get_action_id 0x03550028`

`#define sl_btmesh_rsp_scheduler_server_set_action_id 0x04550028`

#### sl_btmesh_evt_scheduler_server_action_changed

Notification of a Scheduler Action change as the result of a Scheduler Set message. 

For the description of these fields, see [Scheduler Server.](#cls_mesh_scheduler_server)

##### Modules

[sl_btmesh_evt_scheduler_server_action_changed_s](sl-btmesh-evt-scheduler-server-action-changed-s)

##### Typedefs

###### sl_btmesh_evt_scheduler_server_action_changed_t

`typedef struct sl_btmesh_evt_scheduler_server_action_changed_s sl_btmesh_evt_scheduler_server_action_changed_t`

##### Macros

`#define sl_btmesh_evt_scheduler_server_action_changed_id 0x015500a8`

**Description**: Identifier of the action_changed event.

Data structure of the action_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_action_changed_s::elem_index
```

**Details:** Scheduler server model element index

###### index (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::index
```

**Details:** Index of the Scheduler Register

###### year (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::year
```

**Details:** Scheduled year for the action

###### month (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_action_changed_s::month
```

**Details:** Scheduled month for the action

###### day (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::day
```

**Details:** Scheduled day of the month for the action

###### hour (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::hour
```

**Details:** Scheduled hour for the action

###### minute (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::minute
```

**Details:** Scheduled minute for the action

###### second (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::second
```

**Details:** Scheduled second for the action

###### day_of_week (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::day_of_week
```

**Details:** Scheduled days of the week for the action

###### action (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_changed_s::action
```

**Details:** Action to be performed at the scheduled time

###### transition_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scheduler_server_action_changed_s::transition_time_ms
```

**Details:** Transition time for this action

###### scene_number (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_action_changed_s::scene_number
```

**Details:** Scene number to be used for some actions

#### sl_btmesh_evt_scheduler_server_scene_changed

Notification that scheduled scene change took place. 

##### Modules

[sl_btmesh_evt_scheduler_server_scene_changed_s](sl-btmesh-evt-scheduler-server-scene-changed-s)

##### Typedefs

###### sl_btmesh_evt_scheduler_server_scene_changed_t

`typedef struct sl_btmesh_evt_scheduler_server_scene_changed_s sl_btmesh_evt_scheduler_server_scene_changed_t`

##### Macros

`#define sl_btmesh_evt_scheduler_server_scene_changed_id 0x025500a8`

**Description**: Identifier of the scene_changed event.

Data structure of the scene_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_scene_changed_s::elem_index
```

**Details:** Scheduler server model element index

###### transition_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scheduler_server_scene_changed_s::transition_time_ms
```

**Details:** Transition time for this action

###### scene_number (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_scene_changed_s::scene_number
```

**Details:** Scene number being activated

#### sl_btmesh_evt_scheduler_server_action_triggered

Notification about a Scheduler Action that had its deadline expired. 

##### Modules

[sl_btmesh_evt_scheduler_server_action_triggered_s](sl-btmesh-evt-scheduler-server-action-triggered-s)

##### Typedefs

###### sl_btmesh_evt_scheduler_server_action_triggered_t

`typedef struct sl_btmesh_evt_scheduler_server_action_triggered_s sl_btmesh_evt_scheduler_server_action_triggered_t`

##### Macros

`#define sl_btmesh_evt_scheduler_server_action_triggered_id 0x035500a8`

**Description**: Identifier of the action_triggered event.

Data structure of the action_triggered event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_action_triggered_s::elem_index
```

**Details:** Scheduler server model element index

###### index (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_triggered_s::index
```

**Details:** Index of the Scheduler Register

###### action (heading level 7)

```
uint8_t sl_btmesh_evt_scheduler_server_action_triggered_s::action
```

**Details:** Action to be performed at the scheduled time

###### transition_time_ms (heading level 7)

```
uint32_t sl_btmesh_evt_scheduler_server_action_triggered_s::transition_time_ms
```

**Details:** Transition time for this action

###### scene_number (heading level 7)

```
uint16_t sl_btmesh_evt_scheduler_server_action_triggered_s::scene_number
```

**Details:** Scene number to be used for some actions

### Bluetooth Mesh Firmware Update Server Model

Bluetooth Mesh Firmware Update Server Model. 

This class provides the commands and messages to interface with the Firmware Update Server model.

The MBT Server must be initialized before the Update Server. 

#### Modules

[sl_btmesh_evt_fw_update_server_check_fw_metadata_req](sl-btmesh-evt-fw-update-server-check-fw-metadata-req)

[sl_btmesh_evt_fw_update_server_update_start_req](sl-btmesh-evt-fw-update-server-update-start-req)

[sl_btmesh_evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req)

[sl_btmesh_evt_fw_update_server_apply](sl-btmesh-evt-fw-update-server-apply)

[sl_btmesh_evt_fw_update_server_update_cancelled](sl-btmesh-evt-fw-update-server-update-cancelled)

[sl_btmesh_evt_fw_update_server_distributor_self_update_req](sl-btmesh-evt-fw-update-server-distributor-self-update-req)

#### Enumerations

##### sl_btmesh_fw_update_server_update_phase_t

```
enum sl_btmesh_fw_update_server_update_phase_t {
    sl_btmesh_fw_update_server_update_phase_idle = 0x0
    sl_btmesh_fw_update_server_update_phase_transfer_error = 0x1
    sl_btmesh_fw_update_server_update_phase_transfer_in_progress = 0x2
    sl_btmesh_fw_update_server_update_phase_verifying_update = 0x3
    sl_btmesh_fw_update_server_update_phase_verification_success = 0x4
    sl_btmesh_fw_update_server_update_phase_verification_failed = 0x5
    sl_btmesh_fw_update_server_update_phase_apply_in_progress = 0x6
}
```

**Description:**

The Update Phase of the Firmware Update Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_update_server_update_phase_idle|(0x0) No firmware transfer is in progress.|
|sl_btmesh_fw_update_server_update_phase_transfer_error|(0x1) Error occurred during firmware image BLOB transfer.|
|sl_btmesh_fw_update_server_update_phase_transfer_in_progress|(0x2) Firmware image BLOB transfer is in progress.|
|sl_btmesh_fw_update_server_update_phase_verifying_update|(0x3) Firmware image transfer completed, and the node is verifying the image.|
|sl_btmesh_fw_update_server_update_phase_verification_success|(0x4) Firmware image verification succeeded.|
|sl_btmesh_fw_update_server_update_phase_verification_failed|(0x5) Firmware image verification failed.|
|sl_btmesh_fw_update_server_update_phase_apply_in_progress|(0x6) The node is applying the firmware image.|

##### sl_btmesh_fw_update_server_update_status_t

```
enum sl_btmesh_fw_update_server_update_status_t {
    sl_btmesh_fw_update_server_update_status_success = 0x0
    sl_btmesh_fw_update_server_update_status_out_of_resources = 0x1
    sl_btmesh_fw_update_server_update_status_wrong_phase = 0x2
    sl_btmesh_fw_update_server_update_status_internal_error = 0x3
    sl_btmesh_fw_update_server_update_status_wrong_fw_index = 0x4
    sl_btmesh_fw_update_server_update_status_metadata_check_failed = 0x5
    sl_btmesh_fw_update_server_update_status_temporarily_unable = 0x6
    sl_btmesh_fw_update_server_update_status_blob_transfer_busy = 0x7
}
```

**Description:**

Status codes reported by the Firmware Update Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_update_server_update_status_success|(0x0) The message was processed successfully.|
|sl_btmesh_fw_update_server_update_status_out_of_resources|(0x1) Insufficient resources on the node.|
|sl_btmesh_fw_update_server_update_status_wrong_phase|(0x2) The operation cannot be performed while the server is in the current phase.|
|sl_btmesh_fw_update_server_update_status_internal_error|(0x3) An internal error occurred on the node.|
|sl_btmesh_fw_update_server_update_status_wrong_fw_index|(0x4) The message contained a firmware index value that is not expected.|
|sl_btmesh_fw_update_server_update_status_metadata_check_failed|(0x5) The firmware metadata check failed.|
|sl_btmesh_fw_update_server_update_status_temporarily_unable|(0x6) The server cannot start a firmware update right now.|
|sl_btmesh_fw_update_server_update_status_blob_transfer_busy|(0x7) The local MBT Server model is busy with another BLOB transfer.|

##### sl_btmesh_fw_update_server_update_start_response_type_t

```
enum sl_btmesh_fw_update_server_update_start_response_type_t {
    sl_btmesh_fw_update_server_update_start_response_type_accept = 0x0
    sl_btmesh_fw_update_server_update_start_response_type_fw_already_exists = 0x1
    sl_btmesh_fw_update_server_update_start_response_type_reject_out_of_resources = 0x2
    sl_btmesh_fw_update_server_update_start_response_type_reject_internal_error = 0x3
    sl_btmesh_fw_update_server_update_start_response_type_reject_metadata_check_failed = 0x4
    sl_btmesh_fw_update_server_update_start_response_type_reject_temporarily_unable = 0x5
}
```

**Description:**

Used by the implementation to accept or reject the image and select the status code reported by the Firmware Update Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_update_server_update_start_response_type_accept|(0x0) Accept; the MBT Server will start receiving the image.|
|sl_btmesh_fw_update_server_update_start_response_type_fw_already_exists|(0x1) Accept; the MBT Server will not start receiving the image, as the image has already been received.|
|sl_btmesh_fw_update_server_update_start_response_type_reject_out_of_resources|(0x2) Reject; insufficient resources on the node.|
|sl_btmesh_fw_update_server_update_start_response_type_reject_internal_error|(0x3) Reject; An internal error occurred on the node.|
|sl_btmesh_fw_update_server_update_start_response_type_reject_metadata_check_failed|(0x4) Reject; the firmware metadata indicated that the image is not suitable for this node.|
|sl_btmesh_fw_update_server_update_start_response_type_reject_temporarily_unable|(0x5) Reject; The server cannot start a firmware update right now.|

#### Functions

##### sl_btmesh_fw_update_server_init

`sl_status_t sl_btmesh_fw_update_server_init(uint16_t elem_index, uint8_t num_installed_fw, uint8_t max_metadata_len)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|num_installed_fw|Number of installed FWs|
|uint8_t|[in]|max_metadata_len|Maximum length of metadata supported. Any request with a larger metadata value will be rejected automatically.|

Initializes the Firmware Update Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_update_server_deinit

`sl_status_t sl_btmesh_fw_update_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|

Deinitializes the Firmware Update Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_update_server_check_fw_metadata_rsp

`sl_status_t sl_btmesh_fw_update_server_check_fw_metadata_rsp(uint16_t elem_index, uint8_t response_type, uint8_t additional_information, uint8_t fw_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|response_type|Enum [sl_btmesh_fw_update_server_update_start_response_type_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-start-response-type-t). The status code to indicate to the client.|
|uint8_t|[in]|additional_information|Enum [sl_btmesh_fw_update_client_additional_info_t](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-additional-info-t). Additional information about what will happen to the node after the update is applied. 0 = no changes to DCD; 1 = DCD will change but Composition Data Refresh is not supported; 2 = DCD change and Composition Data Refresh is supported; 3 = node will become unprovisioned.|
|uint8_t|[in]|fw_index|Index of the firmware to be updated.|

Response for the [sl_btmesh_evt_fw_update_server_check_fw_metadata_req](sl-btmesh-evt-fw-update-server-check-fw-metadata-req) event. Report whether a server can accept a firmware update.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_update_server_update_start_rsp

`sl_status_t sl_btmesh_fw_update_server_update_start_rsp(uint16_t elem_index, uint8_t response_type, uint8_t additional_information)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|response_type|Enum [sl_btmesh_fw_update_server_update_start_response_type_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-start-response-type-t). Accept or reject the image.|
|uint8_t|[in]|additional_information|Enum [sl_btmesh_fw_update_client_additional_info_t](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-additional-info-t). Additional information about what will happen to the node after the update is applied. 0 = no changes to DCD; 1 = DCD will change but Composition Data Refresh is not supported; 2 = DCD change and Composition Data Refresh is supported; 3 = node will become unprovisioned.|

Response for the [sl_btmesh_evt_fw_update_server_update_start_req](sl-btmesh-evt-fw-update-server-update-start-req) event. After the firmware BLOB Transfer reception is complete, the event [sl_btmesh_evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req) will be generated.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req)

##### sl_btmesh_fw_update_server_verify_fw_rsp

`sl_status_t sl_btmesh_fw_update_server_verify_fw_rsp(uint16_t elem_index, uint8_t accept)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|accept|0 to reject the firmware image, nonzero to accept. If rejected, the server will indicate verification failure to the client when queried. If accepted, the server will wait for an apply command from the client.|

Response for the [sl_btmesh_evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req) event. If the image was accepted, the event [sl_btmesh_evt_fw_update_server_apply](sl-btmesh-evt-fw-update-server-apply) will be generated when the Update Client asks the node to apply the new firmware and reboot.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_server_apply](sl-btmesh-evt-fw-update-server-apply)

##### sl_btmesh_fw_update_server_distributor_self_update_rsp

`sl_status_t sl_btmesh_fw_update_server_distributor_self_update_rsp(uint16_t elem_index, uint8_t response_type, uint8_t additional_information)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|response_type|Enum [sl_btmesh_fw_update_server_update_start_response_type_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-start-response-type-t). Accept or reject the image.|
|uint8_t|[in]|additional_information|Enum [sl_btmesh_fw_update_client_additional_info_t](sl-btmesh-fw-update-client#sl-btmesh-fw-update-client-additional-info-t). Additional information about what will happen to the node after the update is applied. 0 = no changes to DCD; 1 = DCD will change but Composition Data Refresh is not supported; 2 = DCD change and Composition Data Refresh is supported; 3 = node will become unprovisioned.|

Response for the [sl_btmesh_evt_fw_update_server_distributor_self_update_req](sl-btmesh-evt-fw-update-server-distributor-self-update-req) event. This command can only be used if both Distribution Server and Update Server functionality are used on the same node. If the self-update is accepted, the event [sl_btmesh_evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req) will be generated to confirm that the firmware image passed the application-specific checks, just like in a regular update.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_update_server_verify_fw_req](sl-btmesh-evt-fw-update-server-verify-fw-req)

#### Macros

`#define sl_btmesh_cmd_fw_update_server_init_id 0x00570028`

`#define sl_btmesh_cmd_fw_update_server_deinit_id 0x01570028`

`#define sl_btmesh_cmd_fw_update_server_check_fw_metadata_rsp_id 0x02570028`

`#define sl_btmesh_cmd_fw_update_server_update_start_rsp_id 0x03570028`

`#define sl_btmesh_cmd_fw_update_server_verify_fw_rsp_id 0x04570028`

`#define sl_btmesh_cmd_fw_update_server_distributor_self_update_rsp_id 0x05570028`

`#define sl_btmesh_rsp_fw_update_server_init_id 0x00570028`

`#define sl_btmesh_rsp_fw_update_server_deinit_id 0x01570028`

`#define sl_btmesh_rsp_fw_update_server_check_fw_metadata_rsp_id 0x02570028`

`#define sl_btmesh_rsp_fw_update_server_update_start_rsp_id 0x03570028`

`#define sl_btmesh_rsp_fw_update_server_verify_fw_rsp_id 0x04570028`

`#define sl_btmesh_rsp_fw_update_server_distributor_self_update_rsp_id 0x05570028`

#### sl_btmesh_evt_fw_update_server_check_fw_metadata_req

The command [sl_btmesh_fw_update_server_check_fw_metadata_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-check-fw-metadata-rsp) must be issued to inform the client whether metadata looks suitable or not. 

##### Modules

[sl_btmesh_evt_fw_update_server_check_fw_metadata_req_s](sl-btmesh-evt-fw-update-server-check-fw-metadata-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_server_check_fw_metadata_req_t

`typedef struct sl_btmesh_evt_fw_update_server_check_fw_metadata_req_s sl_btmesh_evt_fw_update_server_check_fw_metadata_req_t`

##### Macros

`#define sl_btmesh_evt_fw_update_server_check_fw_metadata_req_id 0x005700a8`

**Description**: Identifier of the check_fw_metadata_req event.

Data structure of the check_fw_metadata_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_check_fw_metadata_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_check_fw_metadata_req_s::client_address
```

**Details:** Address of the Update Client

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_server_check_fw_metadata_req_s::fw_index
```

**Details:** Index of the currently installed firmware to check for updating.

###### metadata (heading level 7)

```
uint8array sl_btmesh_evt_fw_update_server_check_fw_metadata_req_s::metadata
```

**Details:** Metadata for the incoming firmware. May be zero-length.

#### sl_btmesh_evt_fw_update_server_update_start_req

The firmware update is being started. 

The command [sl_btmesh_fw_update_server_update_start_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-start-rsp) should be issued as a response. 

##### Modules

[sl_btmesh_evt_fw_update_server_update_start_req_s](sl-btmesh-evt-fw-update-server-update-start-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_server_update_start_req_t

`typedef struct sl_btmesh_evt_fw_update_server_update_start_req_s sl_btmesh_evt_fw_update_server_update_start_req_t`

##### Macros

`#define sl_btmesh_evt_fw_update_server_update_start_req_id 0x035700a8`

**Description**: Identifier of the update_start_req event.

Data structure of the update_start_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_update_start_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_update_start_req_s::client_address
```

**Details:** Address of the Update Client

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_update_server_update_start_req_s::blob_id
```

**Details:** BLOB ID of the firmware being transferred.

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_server_update_start_req_s::fw_index
```

**Details:** Index of the firmware to update

###### metadata (heading level 7)

```
uint8array sl_btmesh_evt_fw_update_server_update_start_req_s::metadata
```

**Details:** Metadata for the FWID in the following update_start_req event. May be zero-length.

#### sl_btmesh_evt_fw_update_server_verify_fw_req

The firmware has been downloaded completely, and needs to be verified. 

The application should respond with the command [sl_btmesh_fw_update_server_verify_fw_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-verify-fw-rsp) to indicate whether the image passed the application-specific checks. 

##### Modules

[sl_btmesh_evt_fw_update_server_verify_fw_req_s](sl-btmesh-evt-fw-update-server-verify-fw-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_server_verify_fw_req_t

`typedef struct sl_btmesh_evt_fw_update_server_verify_fw_req_s sl_btmesh_evt_fw_update_server_verify_fw_req_t`

##### Macros

`#define sl_btmesh_evt_fw_update_server_verify_fw_req_id 0x045700a8`

**Description**: Identifier of the verify_fw_req event.

Data structure of the verify_fw_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_verify_fw_req_s::elem_index
```

**Details:** Server model element index

#### sl_btmesh_evt_fw_update_server_apply

Apply a firmware image that has been transferred to a server. 

##### Modules

[sl_btmesh_evt_fw_update_server_apply_s](sl-btmesh-evt-fw-update-server-apply-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_server_apply_t

`typedef struct sl_btmesh_evt_fw_update_server_apply_s sl_btmesh_evt_fw_update_server_apply_t`

##### Macros

`#define sl_btmesh_evt_fw_update_server_apply_id 0x055700a8`

**Description**: Identifier of the apply event.

Data structure of the apply event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_apply_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_apply_s::client_address
```

**Details:** Address of the Update Client

#### sl_btmesh_evt_fw_update_server_update_cancelled

Cancel a firmware update and delete any stored information about the update on the server. 

##### Modules

[sl_btmesh_evt_fw_update_server_update_cancelled_s](sl-btmesh-evt-fw-update-server-update-cancelled-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_server_update_cancelled_t

`typedef struct sl_btmesh_evt_fw_update_server_update_cancelled_s sl_btmesh_evt_fw_update_server_update_cancelled_t`

##### Macros

`#define sl_btmesh_evt_fw_update_server_update_cancelled_id 0x065700a8`

**Description**: Identifier of the update_cancelled event.

Data structure of the update_cancelled event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_update_cancelled_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_update_cancelled_s::client_address
```

**Details:** Address of the Update Client

#### sl_btmesh_evt_fw_update_server_distributor_self_update_req

This event can only be generated if both Distribution Server and Update Server functionality are used on the same node. 

This event signals that the Initiator has added this node to the list of nodes to be updated; that is, the node is asked to update itself using an image already present in the Distribution Server's Firmware List. The command [sl_btmesh_fw_update_server_distributor_self_update_rsp](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-distributor-self-update-rsp) must be called to accept or reject the self-update request. 

##### Modules

[sl_btmesh_evt_fw_update_server_distributor_self_update_req_s](sl-btmesh-evt-fw-update-server-distributor-self-update-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_update_server_distributor_self_update_req_t

`typedef struct sl_btmesh_evt_fw_update_server_distributor_self_update_req_s sl_btmesh_evt_fw_update_server_distributor_self_update_req_t`

##### Macros

`#define sl_btmesh_evt_fw_update_server_distributor_self_update_req_id 0x075700a8`

**Description**: Identifier of the distributor_self_update_req event.

Data structure of the distributor_self_update_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_distributor_self_update_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_distributor_self_update_req_s::client_address
```

**Details:** Address of the Update Client; in this case it is the address of the local element on which the Distribution Server and Update Client reside. It can be the same element as the Update Server's element, or a different one.

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_update_server_distributor_self_update_req_s::fw_index
```

**Details:** Index of the firmware on the Update Server to update

###### fw_list_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_update_server_distributor_self_update_req_s::fw_list_index
```

**Details:** Index of the firmware image in the Distribution Server's Firmware List. As the Distribution Server may have multiple images in its Firmware List, this field indicates which one to use for updating.

### Bluetooth Mesh Time Server Model

Bluetooth Mesh Time Server Model. 

This class provides the commands and messages to interface with the Time Server model 

#### Modules

[sl_btmesh_evt_time_server_time_updated](sl-btmesh-evt-time-server-time-updated)

[sl_btmesh_evt_time_server_time_zone_offset_updated](sl-btmesh-evt-time-server-time-zone-offset-updated)

[sl_btmesh_evt_time_server_tai_utc_delta_updated](sl-btmesh-evt-time-server-tai-utc-delta-updated)

[sl_btmesh_evt_time_server_time_role_updated](sl-btmesh-evt-time-server-time-role-updated)

#### Functions

##### sl_btmesh_time_server_init

`sl_status_t sl_btmesh_time_server_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|

Initializes the Time Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_deinit

`sl_status_t sl_btmesh_time_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|

Deinitialize the Time Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_get_time

`sl_status_t sl_btmesh_time_server_get_time(uint16_t elem_index, uint64_t *tai_seconds, uint8_t *subsecond, uint8_t *uncertainty, uint8_t *time_authority, int16_t *time_zone_offset, int32_t *tai_utc_delta)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint64_t *|[out]|tai_seconds|The current TAI time in seconds|
|uint8_t *|[out]|subsecond|The sub-second time in units of 1/256th second|
|uint8_t *|[out]|uncertainty|The estimated uncertainty in 10 millisecond steps|
|uint8_t *|[out]|time_authority|0 = No Time Authority, 1 = Time Authority|
|int16_t *|[out]|time_zone_offset|Current local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.|
|int32_t *|[out]|tai_utc_delta|Current difference between TAI and UTC in seconds. Range is -255 to 32512.|

Get the current time from Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_set_time

`sl_status_t sl_btmesh_time_server_set_time(uint16_t elem_index, uint64_t tai_seconds, uint8_t subsecond, uint8_t uncertainty, uint8_t time_authority, int16_t time_zone_offset, int32_t tai_utc_delta)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint64_t|[in]|tai_seconds|The current TAI time in seconds|
|uint8_t|[in]|subsecond|The sub-second time in units of 1/256th second|
|uint8_t|[in]|uncertainty|The estimated uncertainty in 10 millisecond steps|
|uint8_t|[in]|time_authority|0 = No Time Authority, 1 = Time Authority|
|int16_t|[in]|time_zone_offset|Current local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.|
|int32_t|[in]|tai_utc_delta|Current difference between TAI and UTC in seconds. Range is -255 to 32512.|

Set the current time for the element.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_get_time_zone_offset_new

`sl_status_t sl_btmesh_time_server_get_time_zone_offset_new(uint16_t elem_index, int16_t *new_offset, uint64_t *tai_of_zone_change)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|int16_t *|[out]|new_offset|Upcoming local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.|
|uint64_t *|[out]|tai_of_zone_change|Absolute TAI time when the Time Zone Offset will change from Current to New|

Get the upcoming time zone offset from Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_set_time_zone_offset_new

`sl_status_t sl_btmesh_time_server_set_time_zone_offset_new(uint16_t elem_index, int16_t new_offset, uint64_t tai_of_zone_change)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|int16_t|[in]|new_offset|Upcoming local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.|
|uint64_t|[in]|tai_of_zone_change|Absolute TAI time when the Time Zone Offset will change from Current to New|

Set the upcoming time zone offset for the element

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_get_tai_utc_delta_new

`sl_status_t sl_btmesh_time_server_get_tai_utc_delta_new(uint16_t elem_index, int32_t *new_delta, uint64_t *tai_of_delta_change)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|int32_t *|[out]|new_delta|Upcoming difference between TAI and UTC in seconds|
|uint64_t *|[out]|tai_of_delta_change|Absolute TAI time when the TAI-UTC Delta will change from Current to New|

Get the upcoming TAI-UTC delta for the element

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_set_tai_utc_delta_new

`sl_status_t sl_btmesh_time_server_set_tai_utc_delta_new(uint16_t elem_index, int32_t new_delta, uint64_t tai_of_delta_change)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|int32_t|[in]|new_delta|Upcoming difference between TAI and UTC in seconds. Range is -255 to 32512.|
|uint64_t|[in]|tai_of_delta_change|Absolute TAI time when the TAI-UTC Delta will change from Current to New|

Set the upcoming TAI-UTC delta for the element

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_get_time_role

`sl_status_t sl_btmesh_time_server_get_time_role(uint16_t elem_index, uint8_t *time_role)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t *|[out]|time_role|Time Role of the element|

Get Time Role for the element

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_set_time_role

`sl_status_t sl_btmesh_time_server_set_time_role(uint16_t elem_index, uint8_t time_role)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|time_role|Time Role of the element. Range is 0 to 3.<br/><br/>- 0 = Time Role None, The element does not participate in propagation of time information.<br/>- 1 = Time Role Authority, The element publishes Time Status messages but does not process received Time Status messages.<br/>- 2 = Time Role Relay, The element processes received and publishes Time Status messages.<br/>- 3 = Time Role Client, The element does not publish but processes received Time Status messages.|

Set Time Role for the element

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_get_datetime

`sl_status_t sl_btmesh_time_server_get_datetime(uint16_t elem_index, uint16_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec, uint16_t *ms, int16_t *timezone, uint8_t *day_of_week)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t *|[out]|year|Year|
|uint8_t *|[out]|month|Month|
|uint8_t *|[out]|day|Day|
|uint8_t *|[out]|hour|Hour|
|uint8_t *|[out]|min|Minutes|
|uint8_t *|[out]|sec|Seconds|
|uint16_t *|[out]|ms|Milliseconds|
|int16_t *|[out]|timezone|Local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.|
|uint8_t *|[out]|day_of_week|Day of week, 0..6 represents Monday to Sunday|

Return the date and time from the Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_publish

`sl_status_t sl_btmesh_time_server_publish(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index of the Time Server|

Publish Time Status containing the current time. Permitted only for Time Server having the role of Time Authority.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_server_status

`sl_status_t sl_btmesh_time_server_status(uint16_t destination_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|destination_address|Destination address|
|uint16_t|[in]|elem_index|Element index of the Time Server|
|uint16_t|[in]|appkey_index|The application key index to use|

Send a Time Status message containing the current time as an unsolicited message. Permitted only for Time Server having the role of Time Authority.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_time_server_init_id 0x00520028`

`#define sl_btmesh_cmd_time_server_deinit_id 0x01520028`

`#define sl_btmesh_cmd_time_server_get_time_id 0x02520028`

`#define sl_btmesh_cmd_time_server_set_time_id 0x03520028`

`#define sl_btmesh_cmd_time_server_get_time_zone_offset_new_id 0x04520028`

`#define sl_btmesh_cmd_time_server_set_time_zone_offset_new_id 0x05520028`

`#define sl_btmesh_cmd_time_server_get_tai_utc_delta_new_id 0x06520028`

`#define sl_btmesh_cmd_time_server_set_tai_utc_delta_new_id 0x07520028`

`#define sl_btmesh_cmd_time_server_get_time_role_id 0x08520028`

`#define sl_btmesh_cmd_time_server_set_time_role_id 0x09520028`

`#define sl_btmesh_cmd_time_server_get_datetime_id 0x0a520028`

`#define sl_btmesh_cmd_time_server_publish_id 0x0b520028`

`#define sl_btmesh_cmd_time_server_status_id 0x0c520028`

`#define sl_btmesh_rsp_time_server_init_id 0x00520028`

`#define sl_btmesh_rsp_time_server_deinit_id 0x01520028`

`#define sl_btmesh_rsp_time_server_get_time_id 0x02520028`

`#define sl_btmesh_rsp_time_server_set_time_id 0x03520028`

`#define sl_btmesh_rsp_time_server_get_time_zone_offset_new_id 0x04520028`

`#define sl_btmesh_rsp_time_server_set_time_zone_offset_new_id 0x05520028`

`#define sl_btmesh_rsp_time_server_get_tai_utc_delta_new_id 0x06520028`

`#define sl_btmesh_rsp_time_server_set_tai_utc_delta_new_id 0x07520028`

`#define sl_btmesh_rsp_time_server_get_time_role_id 0x08520028`

`#define sl_btmesh_rsp_time_server_set_time_role_id 0x09520028`

`#define sl_btmesh_rsp_time_server_get_datetime_id 0x0a520028`

`#define sl_btmesh_rsp_time_server_publish_id 0x0b520028`

`#define sl_btmesh_rsp_time_server_status_id 0x0c520028`

#### sl_btmesh_evt_time_server_time_updated

Indicate that Time State has been updated by external source, either Time Set message from a Time Client, or a Time Status message. 

##### Modules

[sl_btmesh_evt_time_server_time_updated_s](sl-btmesh-evt-time-server-time-updated-s)

##### Typedefs

###### sl_btmesh_evt_time_server_time_updated_t

`typedef struct sl_btmesh_evt_time_server_time_updated_s sl_btmesh_evt_time_server_time_updated_t`

##### Macros

`#define sl_btmesh_evt_time_server_time_updated_id 0x005200a8`

**Description**: Identifier of the time_updated event.

Data structure of the time_updated event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_server_time_updated_s::elem_index
```

**Details:** Server model element index

###### tai_seconds (heading level 7)

```
uint64_t sl_btmesh_evt_time_server_time_updated_s::tai_seconds
```

**Details:** The current TAI time in seconds since the epoch, 40-bit value

###### subsecond (heading level 7)

```
uint8_t sl_btmesh_evt_time_server_time_updated_s::subsecond
```

**Details:** The sub-second in units of 1/256th second. Range is 0-255.

###### uncertainty (heading level 7)

```
uint8_t sl_btmesh_evt_time_server_time_updated_s::uncertainty
```

**Details:** The estimated uncertainty in 10-milliseconds steps. Range is 0-255, representing up 2.55 seconds.

###### time_authority (heading level 7)

```
uint8_t sl_btmesh_evt_time_server_time_updated_s::time_authority
```

**Details:** 0: No Time Authority, the element does not have a trusted source of time such as GPS or NTP. 1: Time Authority, the element has a trusted source of time or a battery-backed properly initialized RTC. Other values are prohibited.

###### tai_utc_delta (heading level 7)

```
int32_t sl_btmesh_evt_time_server_time_updated_s::tai_utc_delta
```

**Details:** Current difference between TAI and UTC in seconds. Range is -255 to 32512.

###### time_zone_offset (heading level 7)

```
int16_t sl_btmesh_evt_time_server_time_updated_s::time_zone_offset
```

**Details:** The local time zone offset in 15-minute increments. Range is -64 to 191, representing -16 to 47.75 hours.

#### sl_btmesh_evt_time_server_time_zone_offset_updated

Indicate that upcoming time zone offset change has been updated by external source. 

##### Modules

[sl_btmesh_evt_time_server_time_zone_offset_updated_s](sl-btmesh-evt-time-server-time-zone-offset-updated-s)

##### Typedefs

###### sl_btmesh_evt_time_server_time_zone_offset_updated_t

`typedef struct sl_btmesh_evt_time_server_time_zone_offset_updated_s sl_btmesh_evt_time_server_time_zone_offset_updated_t`

##### Macros

`#define sl_btmesh_evt_time_server_time_zone_offset_updated_id 0x015200a8`

**Description**: Identifier of the time_zone_offset_updated event.

Data structure of the time_zone_offset_updated event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_server_time_zone_offset_updated_s::elem_index
```

**Details:** Server model element index

###### time_zone_offset_current (heading level 7)

```
int16_t sl_btmesh_evt_time_server_time_zone_offset_updated_s::time_zone_offset_current
```

**Details:** Current local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.

###### time_zone_offset_new (heading level 7)

```
int16_t sl_btmesh_evt_time_server_time_zone_offset_updated_s::time_zone_offset_new
```

**Details:** Upcoming local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.

###### tai_of_zone_change (heading level 7)

```
uint64_t sl_btmesh_evt_time_server_time_zone_offset_updated_s::tai_of_zone_change
```

**Details:** Absolute TAI time when the Time Zone Offset will change from Current to New

#### sl_btmesh_evt_time_server_tai_utc_delta_updated

Indicate that the upcoming TAI-UTC Delta has been updated by external source. 

##### Modules

[sl_btmesh_evt_time_server_tai_utc_delta_updated_s](sl-btmesh-evt-time-server-tai-utc-delta-updated-s)

##### Typedefs

###### sl_btmesh_evt_time_server_tai_utc_delta_updated_t

`typedef struct sl_btmesh_evt_time_server_tai_utc_delta_updated_s sl_btmesh_evt_time_server_tai_utc_delta_updated_t`

##### Macros

`#define sl_btmesh_evt_time_server_tai_utc_delta_updated_id 0x025200a8`

**Description**: Identifier of the tai_utc_delta_updated event.

Data structure of the tai_utc_delta_updated event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_server_tai_utc_delta_updated_s::elem_index
```

**Details:** Server model element index

###### tai_utc_delta_current (heading level 7)

```
int32_t sl_btmesh_evt_time_server_tai_utc_delta_updated_s::tai_utc_delta_current
```

**Details:** Current difference between TAI and UTC is seconds. Range is -255 to 32512.

###### tai_utc_delta_new (heading level 7)

```
int32_t sl_btmesh_evt_time_server_tai_utc_delta_updated_s::tai_utc_delta_new
```

**Details:** Upcoming difference between TAI and UTC is seconds. Range is -255 to 32512.

###### tai_of_delta_change (heading level 7)

```
uint64_t sl_btmesh_evt_time_server_tai_utc_delta_updated_s::tai_of_delta_change
```

**Details:** TAI Seconds time of the upcoming TAI-UTC Delta change

#### sl_btmesh_evt_time_server_time_role_updated

Indicate that Time Role has been updated by external source by Time Role Set message from a Time Client. 

##### Modules

[sl_btmesh_evt_time_server_time_role_updated_s](sl-btmesh-evt-time-server-time-role-updated-s)

##### Typedefs

###### sl_btmesh_evt_time_server_time_role_updated_t

`typedef struct sl_btmesh_evt_time_server_time_role_updated_s sl_btmesh_evt_time_server_time_role_updated_t`

##### Macros

`#define sl_btmesh_evt_time_server_time_role_updated_id 0x035200a8`

**Description**: Identifier of the time_role_updated event.

Data structure of the time_role_updated event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_server_time_role_updated_s::elem_index
```

**Details:** Server model element index

###### time_role (heading level 7)

```
uint8_t sl_btmesh_evt_time_server_time_role_updated_s::time_role
```

**Details:** Time Role

### Bluetooth Mesh Time Client Model

Bluetooth Mesh Time Client Model. 

This class provides the commands and messages to interface with the Time Client model 

#### Modules

[sl_btmesh_evt_time_client_time_status](sl-btmesh-evt-time-client-time-status)

[sl_btmesh_evt_time_client_time_zone_status](sl-btmesh-evt-time-client-time-zone-status)

[sl_btmesh_evt_time_client_tai_utc_delta_status](sl-btmesh-evt-time-client-tai-utc-delta-status)

[sl_btmesh_evt_time_client_time_role_status](sl-btmesh-evt-time-client-time-role-status)

#### Enumerations

##### sl_btmesh_time_client_time_roles_t

```
enum sl_btmesh_time_client_time_roles_t {
    sl_btmesh_time_client_time_role_none = 0x0
    sl_btmesh_time_client_time_role_authority = 0x1
    sl_btmesh_time_client_time_role_relay = 0x2
    sl_btmesh_time_client_time_role_client = 0x3
}
```

**Description:**

These values define the Time Role types used by the stack.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_time_client_time_role_none|(0x0) The element does not participate in propagation of time information.|
|sl_btmesh_time_client_time_role_authority|(0x1) The element publishes Time Status messages but does not process received Time Status messages.|
|sl_btmesh_time_client_time_role_relay|(0x2) The element processes received and publishes Time Status messages.|
|sl_btmesh_time_client_time_role_client|(0x3) The element does not publish but processes received Time Status messages.|

#### Functions

##### sl_btmesh_time_client_init

`sl_status_t sl_btmesh_time_client_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Initialize the Time Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_client_deinit

`sl_status_t sl_btmesh_time_client_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Deinitialize the Time Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_time_client_get_time

`sl_status_t sl_btmesh_time_client_get_time(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|

Send a Time Get message to Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_time_status](sl-btmesh-evt-time-client-time-status)

##### sl_btmesh_time_client_set_time

`sl_status_t sl_btmesh_time_client_set_time(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint64_t tai_seconds, uint8_t subsecond, uint8_t uncertainty, uint8_t time_authority, int32_t tai_utc_delta, int16_t time_zone_offset)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint64_t|[in]|tai_seconds|The current TAI time in seconds since the epoch, 40-bit value|
|uint8_t|[in]|subsecond|The sub-second in units of 1/256th second. Range is 0-255.|
|uint8_t|[in]|uncertainty|The estimated uncertainty in 10-milliseconds steps. Range is 0-255, representing up to 2.55 seconds.|
|uint8_t|[in]|time_authority|0: No Time Authority, the element does not have a trusted source of time such as GPS or NTP. 1: Time Authority, the element has a trusted source of time or a battery-backed properly initialized RTC. Other values are prohibited.|
|int32_t|[in]|tai_utc_delta|Current difference between TAI and UTC in seconds. Range is -255 to 32512.|
|int16_t|[in]|time_zone_offset|The local time zone offset in 15-minute increments. Range is -64 to 191, representing -16 to 47.75 hours.|

Send a Time Set message to Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_time_status](sl-btmesh-evt-time-client-time-status)

##### sl_btmesh_time_client_get_time_zone

`sl_status_t sl_btmesh_time_client_get_time_zone(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|

Send a Time Zone Get message to Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_time_zone_status](sl-btmesh-evt-time-client-time-zone-status)

##### sl_btmesh_time_client_set_time_zone

`sl_status_t sl_btmesh_time_client_set_time_zone(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, int16_t time_zone_offset_new, uint64_t tai_of_zone_change)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|int16_t|[in]|time_zone_offset_new|Upcoming local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.|
|uint64_t|[in]|tai_of_zone_change|TAI Seconds time of upcoming Time Zone offset change|

Send a Time Zone Set message to Time Server to set the Time Zone New state

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_time_zone_status](sl-btmesh-evt-time-client-time-zone-status)

##### sl_btmesh_time_client_get_tai_utc_delta

`sl_status_t sl_btmesh_time_client_get_tai_utc_delta(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|

Send a TAI-UTC Delta Get message to Time Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_tai_utc_delta_status](sl-btmesh-evt-time-client-tai-utc-delta-status)

##### sl_btmesh_time_client_set_tai_utc_delta

`sl_status_t sl_btmesh_time_client_set_tai_utc_delta(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, int32_t tai_utc_delta_new, uint64_t tai_of_delta_change)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|int32_t|[in]|tai_utc_delta_new|Upcoming difference between TAI and UTC is seconds. Range is -255 to 32512.|
|uint64_t|[in]|tai_of_delta_change|TAI Seconds time of the upcoming TAI-UTC Delta change|

Send a TAI-UTC Delta Set message to Time Server, which responds with a TAI-UTC Delta Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_tai_utc_delta_status](sl-btmesh-evt-time-client-tai-utc-delta-status)

##### sl_btmesh_time_client_get_time_role

`sl_status_t sl_btmesh_time_client_get_time_role(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|

Send a Time Role Get message to Time Server, which responds with a Time Role Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_time_role_status](sl-btmesh-evt-time-client-time-role-status)

##### sl_btmesh_time_client_set_time_role

`sl_status_t sl_btmesh_time_client_set_time_role(uint16_t server_address, uint16_t elem_index, uint16_t appkey_index, uint8_t time_role)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|server_address|Destination server model address|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|The application key index to use.|
|uint8_t|[in]|time_role|The Time Role for the element. Range is 0 to 3.<br/><br/>- 0 = Time Role None, The element does not participate in propagation of time information.<br/>- 1 = Time Role Authority, The element publishes Time Status messages but does not process received Time Status messages.<br/>- 2 = Time Role Relay, The element processes received and publishes Time Status messages.<br/>- 3 = Time Role Client, The element does not publish but processes received Time Status messages.|

Send Time Role Set message to Time Server, which responds with a Time Role Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_time_client_time_role_status](sl-btmesh-evt-time-client-time-role-status)

#### Macros

`#define sl_btmesh_cmd_time_client_init_id 0x00530028`

`#define sl_btmesh_cmd_time_client_deinit_id 0x01530028`

`#define sl_btmesh_cmd_time_client_get_time_id 0x02530028`

`#define sl_btmesh_cmd_time_client_set_time_id 0x03530028`

`#define sl_btmesh_cmd_time_client_get_time_zone_id 0x04530028`

`#define sl_btmesh_cmd_time_client_set_time_zone_id 0x05530028`

`#define sl_btmesh_cmd_time_client_get_tai_utc_delta_id 0x06530028`

`#define sl_btmesh_cmd_time_client_set_tai_utc_delta_id 0x07530028`

`#define sl_btmesh_cmd_time_client_get_time_role_id 0x08530028`

`#define sl_btmesh_cmd_time_client_set_time_role_id 0x09530028`

`#define sl_btmesh_rsp_time_client_init_id 0x00530028`

`#define sl_btmesh_rsp_time_client_deinit_id 0x01530028`

`#define sl_btmesh_rsp_time_client_get_time_id 0x02530028`

`#define sl_btmesh_rsp_time_client_set_time_id 0x03530028`

`#define sl_btmesh_rsp_time_client_get_time_zone_id 0x04530028`

`#define sl_btmesh_rsp_time_client_set_time_zone_id 0x05530028`

`#define sl_btmesh_rsp_time_client_get_tai_utc_delta_id 0x06530028`

`#define sl_btmesh_rsp_time_client_set_tai_utc_delta_id 0x07530028`

`#define sl_btmesh_rsp_time_client_get_time_role_id 0x08530028`

`#define sl_btmesh_rsp_time_client_set_time_role_id 0x09530028`

#### sl_btmesh_evt_time_client_time_status

Time Status event, response to [sl_btmesh_time_client_set_time](sl-btmesh-time-client#sl-btmesh-time-client-set-time) or [sl_btmesh_time_client_get_time](sl-btmesh-time-client#sl-btmesh-time-client-get-time) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_time_client_time_status_s](sl-btmesh-evt-time-client-time-status-s)

##### Typedefs

###### sl_btmesh_evt_time_client_time_status_t

`typedef struct sl_btmesh_evt_time_client_time_status_s sl_btmesh_evt_time_client_time_status_t`

##### Macros

`#define sl_btmesh_evt_time_client_time_status_id 0x005300a8`

**Description**: Identifier of the time_status event.

Data structure of the time_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_status_s::client_address
```

**Details:** Client address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_status_s::server_address
```

**Details:** Unicast address of the server

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_status_s::appkey_index
```

**Details:** App key index.

###### tai_seconds (heading level 7)

```
uint64_t sl_btmesh_evt_time_client_time_status_s::tai_seconds
```

**Details:** The current TAI time in seconds

###### subsecond (heading level 7)

```
uint8_t sl_btmesh_evt_time_client_time_status_s::subsecond
```

**Details:** The sub-second time in units of 1/256th second

###### uncertainty (heading level 7)

```
uint8_t sl_btmesh_evt_time_client_time_status_s::uncertainty
```

**Details:** The estimated uncertainty in 10-millisecond steps

###### time_authority (heading level 7)

```
uint8_t sl_btmesh_evt_time_client_time_status_s::time_authority
```

**Details:** 0 = No Time Authority, 1 = Time Authority

###### tai_utc_delta (heading level 7)

```
int32_t sl_btmesh_evt_time_client_time_status_s::tai_utc_delta
```

**Details:** Current difference between TAI and UTC in seconds. Range is -255 to 32512.

###### time_zone_offset (heading level 7)

```
int16_t sl_btmesh_evt_time_client_time_status_s::time_zone_offset
```

**Details:** The local time zone offset in 15-minute increments. Range is -64 to 191, representing -16 to 47.75 hours.

#### sl_btmesh_evt_time_client_time_zone_status

Time Zone Status event, response to [sl_btmesh_time_client_set_time_zone](sl-btmesh-time-client#sl-btmesh-time-client-set-time-zone) or [sl_btmesh_time_client_get_time_zone](sl-btmesh-time-client#sl-btmesh-time-client-get-time-zone) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_time_client_time_zone_status_s](sl-btmesh-evt-time-client-time-zone-status-s)

##### Typedefs

###### sl_btmesh_evt_time_client_time_zone_status_t

`typedef struct sl_btmesh_evt_time_client_time_zone_status_s sl_btmesh_evt_time_client_time_zone_status_t`

##### Macros

`#define sl_btmesh_evt_time_client_time_zone_status_id 0x015300a8`

**Description**: Identifier of the time_zone_status event.

Data structure of the time_zone_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_zone_status_s::client_address
```

**Details:** Client address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_zone_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_zone_status_s::server_address
```

**Details:** Unicast address of the server

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_zone_status_s::appkey_index
```

**Details:** App key index.

###### time_zone_offset_current (heading level 7)

```
int16_t sl_btmesh_evt_time_client_time_zone_status_s::time_zone_offset_current
```

**Details:** Current local time zone offset. Range is -64 to 191, representing -16 to 47.75 hours.

###### time_zone_offset_new (heading level 7)

```
int16_t sl_btmesh_evt_time_client_time_zone_status_s::time_zone_offset_new
```

**Details:** Upcoming local time zone offset

###### tai_of_zone_change (heading level 7)

```
uint64_t sl_btmesh_evt_time_client_time_zone_status_s::tai_of_zone_change
```

**Details:** TAI seconds time of the upcoming Time Zone offset change

#### sl_btmesh_evt_time_client_tai_utc_delta_status

TAI-UTC Delta Status event, response to [sl_btmesh_time_client_set_tai_utc_delta](sl-btmesh-time-client#sl-btmesh-time-client-set-tai-utc-delta) or [sl_btmesh_time_client_get_tai_utc_delta](sl-btmesh-time-client#sl-btmesh-time-client-get-tai-utc-delta) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_time_client_tai_utc_delta_status_s](sl-btmesh-evt-time-client-tai-utc-delta-status-s)

##### Typedefs

###### sl_btmesh_evt_time_client_tai_utc_delta_status_t

`typedef struct sl_btmesh_evt_time_client_tai_utc_delta_status_s sl_btmesh_evt_time_client_tai_utc_delta_status_t`

##### Macros

`#define sl_btmesh_evt_time_client_tai_utc_delta_status_id 0x025300a8`

**Description**: Identifier of the tai_utc_delta_status event.

Data structure of the tai_utc_delta_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::client_address
```

**Details:** Client address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::server_address
```

**Details:** Unicast address of the server

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::appkey_index
```

**Details:** App key index.

###### tai_utc_delta_current (heading level 7)

```
int32_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::tai_utc_delta_current
```

**Details:** Current difference between TAI and UTC. Range is -255 to 32512.

###### tai_utc_delta_new (heading level 7)

```
int32_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::tai_utc_delta_new
```

**Details:** Upcoming difference between TAI and UTC in seconds. Range is -255 to 32512.

###### tai_of_delta_change (heading level 7)

```
uint64_t sl_btmesh_evt_time_client_tai_utc_delta_status_s::tai_of_delta_change
```

**Details:** TAI seconds time of the upcoming TAI-UTC delta change

#### sl_btmesh_evt_time_client_time_role_status

Time Role Status event, response to [sl_btmesh_time_client_set_time_role](sl-btmesh-time-client#sl-btmesh-time-client-set-time-role) or [sl_btmesh_time_client_get_time_role](sl-btmesh-time-client#sl-btmesh-time-client-get-time-role) command or unsolicited message. 

##### Modules

[sl_btmesh_evt_time_client_time_role_status_s](sl-btmesh-evt-time-client-time-role-status-s)

##### Typedefs

###### sl_btmesh_evt_time_client_time_role_status_t

`typedef struct sl_btmesh_evt_time_client_time_role_status_s sl_btmesh_evt_time_client_time_role_status_t`

##### Macros

`#define sl_btmesh_evt_time_client_time_role_status_id 0x035300a8`

**Description**: Identifier of the time_role_status event.

Data structure of the time_role_status event. 

###### Public Attributes

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_role_status_s::client_address
```

**Details:** Client address

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_role_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_role_status_s::server_address
```

**Details:** Unicast address of the server

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_time_client_time_role_status_s::appkey_index
```

**Details:** App key index.

###### time_role (heading level 7)

```
uint8_t sl_btmesh_evt_time_client_time_role_status_s::time_role
```

**Details:** The Time Role for the element

### Bluetooth Mesh Firmware Distribution Server Model

Bluetooth Mesh Firmware Distribution Server Model. 

The Bluetooth Mesh Firmware Distribution Server Model is used to receive new firmware images from the Firmware Distribution Client model and distribute them to Target Nodes. As a transport layer Bluetooth Mesh BLOB Transfer (MBT) models are in use. 

#### Modules

[sl_btmesh_evt_fw_dist_server_nodes_added](sl-btmesh-evt-fw-dist-server-nodes-added)

[sl_btmesh_evt_fw_dist_server_nodes_deleted](sl-btmesh-evt-fw-dist-server-nodes-deleted)

[sl_btmesh_evt_fw_dist_server_dist_start_req](sl-btmesh-evt-fw-dist-server-dist-start-req)

[sl_btmesh_evt_fw_dist_server_dist_cancel](sl-btmesh-evt-fw-dist-server-dist-cancel)

[sl_btmesh_evt_fw_dist_server_dist_cancel_complete](sl-btmesh-evt-fw-dist-server-dist-cancel-complete)

[sl_btmesh_evt_fw_dist_server_upload_start_metadata](sl-btmesh-evt-fw-dist-server-upload-start-metadata)

[sl_btmesh_evt_fw_dist_server_upload_start_req](sl-btmesh-evt-fw-dist-server-upload-start-req)

[sl_btmesh_evt_fw_dist_server_upload_cancel](sl-btmesh-evt-fw-dist-server-upload-cancel)

[sl_btmesh_evt_fw_dist_server_dist_state_changed](sl-btmesh-evt-fw-dist-server-dist-state-changed)

[sl_btmesh_evt_fw_dist_server_node_failed](sl-btmesh-evt-fw-dist-server-node-failed)

[sl_btmesh_evt_fw_dist_server_upload_complete_metadata](sl-btmesh-evt-fw-dist-server-upload-complete-metadata)

[sl_btmesh_evt_fw_dist_server_upload_complete](sl-btmesh-evt-fw-dist-server-upload-complete)

[sl_btmesh_evt_fw_dist_server_upload_failed](sl-btmesh-evt-fw-dist-server-upload-failed)

[sl_btmesh_evt_fw_dist_server_upload_oob_start_uri](sl-btmesh-evt-fw-dist-server-upload-oob-start-uri)

[sl_btmesh_evt_fw_dist_server_upload_oob_start_req](sl-btmesh-evt-fw-dist-server-upload-oob-start-req)

[sl_btmesh_evt_fw_dist_server_fw_delete_req](sl-btmesh-evt-fw-dist-server-fw-delete-req)

[sl_btmesh_evt_fw_dist_server_fw_delete_all_req](sl-btmesh-evt-fw-dist-server-fw-delete-all-req)

[sl_btmesh_evt_fw_dist_server_dist_suspend](sl-btmesh-evt-fw-dist-server-dist-suspend)

[sl_btmesh_evt_fw_dist_server_resume_req](sl-btmesh-evt-fw-dist-server-resume-req)

#### Enumerations

##### sl_btmesh_fw_dist_server_dist_step_t

```
enum sl_btmesh_fw_dist_server_dist_step_t {
    sl_btmesh_fw_dist_server_dist_step_idle = 0x0
    sl_btmesh_fw_dist_server_dist_step_starting_update = 0x1
    sl_btmesh_fw_dist_server_dist_step_transferring_image = 0x2
    sl_btmesh_fw_dist_server_dist_step_checking_verification = 0x3
    sl_btmesh_fw_dist_server_dist_step_waiting_for_apply = 0x4
    sl_btmesh_fw_dist_server_dist_step_applying_update = 0x5
    sl_btmesh_fw_dist_server_dist_step_checking_update_result = 0x6
    sl_btmesh_fw_dist_server_dist_step_completed = 0x7
    sl_btmesh_fw_dist_server_dist_step_failed = 0x8
    sl_btmesh_fw_dist_server_dist_step_cancelling = 0x9
    sl_btmesh_fw_dist_server_dist_step_suspended = 0xa
}
```

**Description:**

The state machine states of the Distribution Server's distribution procedure.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_server_dist_step_idle|(0x0) No distribution is active.|
|sl_btmesh_fw_dist_server_dist_step_starting_update|(0x1) Sending Update Start messages.|
|sl_btmesh_fw_dist_server_dist_step_transferring_image|(0x2) Firmware image BLOB transfer is in progress.|
|sl_btmesh_fw_dist_server_dist_step_checking_verification|(0x3) Sending Update Get messages to check verification status.|
|sl_btmesh_fw_dist_server_dist_step_waiting_for_apply|(0x4) Park state if Update Policy is Verify Only: wait for Distribution Apply. If the policy is Verify and Apply, this state is skipped.|
|sl_btmesh_fw_dist_server_dist_step_applying_update|(0x5) Sending Update Apply messages.|
|sl_btmesh_fw_dist_server_dist_step_checking_update_result|(0x6) Sending Information Get messages to determine if new firmware was applied.|
|sl_btmesh_fw_dist_server_dist_step_completed|(0x7) Completed successfully for at least one Target Node.|
|sl_btmesh_fw_dist_server_dist_step_failed|(0x8) Distribution failed for all Target Nodes.|
|sl_btmesh_fw_dist_server_dist_step_cancelling|(0x9) Cancelling an ongoing distribution.|
|sl_btmesh_fw_dist_server_dist_step_suspended|(0xa) Firmware image BLOB transfer is temporarily suspended.|

##### sl_btmesh_fw_dist_server_dfu_policy_t

```
enum sl_btmesh_fw_dist_server_dfu_policy_t {
    sl_btmesh_fw_dist_server_dfu_policy_verify_only = 0x0
    sl_btmesh_fw_dist_server_dfu_policy_verify_and_apply = 0x1
}
```

**Description:**

The Update Policy determines whether the Distribution Server will send Update Apply messages to the Target Nodes immediately, or wait for the Distribution Client to send it the Distribution Apply message.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_server_dfu_policy_verify_only|(0x0) The Distribution Server will wait for the Distribution Apply message, and then send the Update Apply messages.|
|sl_btmesh_fw_dist_server_dfu_policy_verify_and_apply|(0x1) The Distribution Server will send the Update Apply messages immediately, after the firmware image verification is complete.|

##### sl_btmesh_fw_dist_server_dist_node_phase_t

```
enum sl_btmesh_fw_dist_server_dist_node_phase_t {
    sl_btmesh_fw_dist_server_dist_node_phase_idle = 0x0
    sl_btmesh_fw_dist_server_dist_node_phase_transfer_error = 0x1
    sl_btmesh_fw_dist_server_dist_node_phase_transfer_in_progress = 0x2
    sl_btmesh_fw_dist_server_dist_node_phase_verifying_update = 0x3
    sl_btmesh_fw_dist_server_dist_node_phase_verification_success = 0x4
    sl_btmesh_fw_dist_server_dist_node_phase_verification_failed = 0x5
    sl_btmesh_fw_dist_server_dist_node_phase_apply_in_progress = 0x6
    sl_btmesh_fw_dist_server_dist_node_phase_transfer_cancelled = 0x7
    sl_btmesh_fw_dist_server_dist_node_phase_apply_success = 0x8
    sl_btmesh_fw_dist_server_dist_node_phase_apply_failed = 0x9
    sl_btmesh_fw_dist_server_dist_node_phase_unknown = 0xa
}
```

**Description:**

The phase of the Target Node as determined by the Distribution Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_server_dist_node_phase_idle|(0x0) No firmware transfer is in progress.|
|sl_btmesh_fw_dist_server_dist_node_phase_transfer_error|(0x1) Error occurred during firmware image BLOB transfer.|
|sl_btmesh_fw_dist_server_dist_node_phase_transfer_in_progress|(0x2) Firmware image BLOB transfer is in progress.|
|sl_btmesh_fw_dist_server_dist_node_phase_verifying_update|(0x3) Firmware image transfer completed, and the node is verifying the image.|
|sl_btmesh_fw_dist_server_dist_node_phase_verification_success|(0x4) Firmware image verification succeeded.|
|sl_btmesh_fw_dist_server_dist_node_phase_verification_failed|(0x5) Firmware image verification failed.|
|sl_btmesh_fw_dist_server_dist_node_phase_apply_in_progress|(0x6) The node is applying the firmware update.|
|sl_btmesh_fw_dist_server_dist_node_phase_transfer_cancelled|(0x7) Firmware transfer was cancelled.|
|sl_btmesh_fw_dist_server_dist_node_phase_apply_success|(0x8) Firmware was applied successfully.|
|sl_btmesh_fw_dist_server_dist_node_phase_apply_failed|(0x9) Firmware applying failed.|
|sl_btmesh_fw_dist_server_dist_node_phase_unknown|(0xa) The phase of the node has not been retrieved yet.|

##### sl_btmesh_fw_dist_server_dist_status_t

```
enum sl_btmesh_fw_dist_server_dist_status_t {
    sl_btmesh_fw_dist_server_dist_status_success = 0x0
    sl_btmesh_fw_dist_server_dist_status_out_of_resources = 0x1
    sl_btmesh_fw_dist_server_dist_status_wrong_phase = 0x2
    sl_btmesh_fw_dist_server_dist_status_internal_error = 0x3
    sl_btmesh_fw_dist_server_dist_status_fwid_not_found = 0x4
    sl_btmesh_fw_dist_server_dist_status_invalid_appkey_index = 0x5
    sl_btmesh_fw_dist_server_dist_status_receivers_list_empty = 0x6
    sl_btmesh_fw_dist_server_dist_status_busy_with_distribution = 0x7
    sl_btmesh_fw_dist_server_dist_status_busy_with_upload = 0x8
    sl_btmesh_fw_dist_server_dist_status_uri_not_supported = 0x9
    sl_btmesh_fw_dist_server_dist_status_uri_malformed = 0xa
    sl_btmesh_fw_dist_server_dist_status_uri_unreachable = 0xb
    sl_btmesh_fw_dist_server_dist_status_new_fw_not_available = 0xc
    sl_btmesh_fw_dist_server_dist_status_suspend_failed = 0xd
}
```

**Description:**

Status codes reported by the Firmware Distribution Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_server_dist_status_success|(0x0) The message was processed successfully.|
|sl_btmesh_fw_dist_server_dist_status_out_of_resources|(0x1) Insufficient resources on the node.|
|sl_btmesh_fw_dist_server_dist_status_wrong_phase|(0x2) The operation cannot be performed while the server is in the current phase.|
|sl_btmesh_fw_dist_server_dist_status_internal_error|(0x3) An internal error occurred on the node.|
|sl_btmesh_fw_dist_server_dist_status_fwid_not_found|(0x4) The requested firmware image is not stored on the server.|
|sl_btmesh_fw_dist_server_dist_status_invalid_appkey_index|(0x5) The appkey identified by the appkey index is not known.|
|sl_btmesh_fw_dist_server_dist_status_receivers_list_empty|(0x6) There are no Target Nodes in the Distribution Receivers List.|
|sl_btmesh_fw_dist_server_dist_status_busy_with_distribution|(0x7) Another distribution is already in progress.|
|sl_btmesh_fw_dist_server_dist_status_busy_with_upload|(0x8) Another upload is already in progress.|
|sl_btmesh_fw_dist_server_dist_status_uri_not_supported|(0x9) The URI scheme name indicated by the URI is not supported.|
|sl_btmesh_fw_dist_server_dist_status_uri_malformed|(0xa) The format of the URI is invalid.|
|sl_btmesh_fw_dist_server_dist_status_uri_unreachable|(0xb) The URI is currently unreachable.|
|sl_btmesh_fw_dist_server_dist_status_new_fw_not_available|(0xc) No new firmware was available with given the URI + Current FWID.|
|sl_btmesh_fw_dist_server_dist_status_suspend_failed|(0xd) Suspending a distribution failed.|

#### Functions

##### sl_btmesh_fw_dist_server_init

`sl_status_t sl_btmesh_fw_dist_server_init(uint16_t elem_index, uint16_t max_node_list_size, uint16_t max_fw_entries, uint32_t max_fw_size, uint32_t total_store_size, uint16_t multicast_threshold, size_t oob_supported_uri_scheme_names_len, const uint8_t *oob_supported_uri_scheme_names)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|max_node_list_size|Maximum number of nodes that can be updated simultaneously|
|uint16_t|[in]|max_fw_entries|Maximum number of firmware images that can be stored|
|uint32_t|[in]|max_fw_size|Maximum size of a single firmware image|
|uint32_t|[in]|total_store_size|Maximum combined size of all firmware images|
|uint16_t|[in]|multicast_threshold|This value will be passed to the MBT Client. If the number of servers for any step exceeds or is equal to this number, the group address will be used. Otherwise, servers will be looped through one by one. Value of 0 disables the feature.|
|size_t|[in]|oob_supported_uri_scheme_names_len|Length of data in `oob_supported_uri_scheme_names`|
|const uint8_t *|[in]|oob_supported_uri_scheme_names|To indicate Upload OOB support, list the supported URI Scheme Names UTF-8 code points here (see [https://www.bluetooth.com/specifications/assigned-numbers/uri-scheme-name-string-mapping/](https://www.bluetooth.com/specifications/assigned-numbers/uri-scheme-name-string-mapping/)). To indicate Upload OOB is not supported, give a zero-length string.|

Initializes the Firmware Distribution Server model. Before initializing the Distribution Server model, the Update Client and MBT Server models on the same element must be initialized.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_deinit

`sl_status_t sl_btmesh_fw_dist_server_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|

Deinitializes the Firmware Distribution Server model. The corresponding Update Client and MBT Server models can be deinitialized before or after this model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_upload_start_rsp

`sl_status_t sl_btmesh_fw_dist_server_upload_start_rsp(uint16_t elem_index, uint8_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|status|Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code to the client|

Response for the upload_start_req event

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_execute_distribution_step

`sl_status_t sl_btmesh_fw_dist_server_execute_distribution_step(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|

Execute the next action for the distribution state machine.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_upload_oob_start_rsp

`sl_status_t sl_btmesh_fw_dist_server_upload_oob_start_rsp(uint16_t elem_index, uint8_t status_code, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|status_code|Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code to use for the response. Must be one of the following:<br/><br/>- **0:** success - retrieving the firmware archive was started or will start shortly<br/>- **1:** out of resources<br/>- **3:** internal error occurred<br/>- **9:** URI scheme name not supported<br/>- **10:** URI malformed<br/>- **11:** URI was unreachable<br/>- **12:** No new firmware was available<br/><br/>All other status codes are reserved or automatically sent by the stack.|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the image that will be retrieved OOB. The Firmware ID is retrieved by executing the Check Firmware OOB procedure.|

Response to the [sl_btmesh_evt_fw_dist_server_upload_oob_start_req](sl-btmesh-evt-fw-dist-server-upload-oob-start-req) event. The application should run the Check Firmware OOB procedure (as detailed in the specification) in order to check that the given URI is reachable, and a new firmware image is available.

When the size of the image is known, [sl_btmesh_fw_dist_server_set_upload_oob_image_size](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-image-size) must be called to inform the stack about the size of the image.

If the image has an associated set of metadata, [sl_btmesh_fw_dist_server_set_upload_oob_metadata](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-metadata) must be called to inform the stack about the image metadata.

The command [sl_btmesh_fw_dist_server_set_upload_oob_progress](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-progress) must be called at minimum when the transfer completes or an error is encountered. It can be called earlier to inform the stack about the transfer progress.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_set_upload_oob_metadata

`sl_status_t sl_btmesh_fw_dist_server_set_upload_oob_metadata(uint16_t elem_index, size_t metadata_len, const uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|size_t|[in]|metadata_len|Length of data in `metadata`|
|const uint8_t *|[in]|metadata|Metadata of the image. May be zero-length.|

Set the metadata of an image retrieved via OOB Upload. This command can be used after [sl_btmesh_fw_dist_server_upload_oob_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-upload-oob-start-rsp), and cannot be used after the OOB Upload completes. If the uploaded firmware image has no associated metadata, this command does not need to be called.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_set_upload_oob_image_size

`sl_status_t sl_btmesh_fw_dist_server_set_upload_oob_image_size(uint16_t elem_index, uint32_t size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint32_t|[in]|size|Size of the new firmware image|

Set the size of the image being retrieved via OOB Upload. This command must be used after [sl_btmesh_fw_dist_server_upload_oob_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-upload-oob-start-rsp), as soon as the size of the image is known. The upload cannot be completed with [sl_btmesh_fw_dist_server_set_upload_oob_progress](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-set-upload-oob-progress) before the size is set.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_set_upload_oob_progress

`sl_status_t sl_btmesh_fw_dist_server_set_upload_oob_progress(uint16_t elem_index, uint8_t error, uint8_t progress, uint16_t *fw_list_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint8_t|[in]|error|Set to zero if no error occurred. If nonzero, the transfer will be considered a failure, and the Upload Phase will be set to Transfer Error. A nonzero value cannot be used in conjuction with progress 100.<br/><br/>Note that there is no way in the specification to indicate what kind of error occurred during the OOB retrieval. Only the initial start request can be rejected with a specific error code; see [sl_btmesh_fw_dist_server_upload_oob_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-upload-oob-start-rsp).|
|uint8_t|[in]|progress|Progress of the transfer, in percentage. Range: 0-100. If set 100, the upload will be completed, and the fw_list_index return parameter is populated with the Firmware List Index that was assigned to the new image.|
|uint16_t *|[out]|fw_list_index|Firmware List Index that was assigned to the image, if progress was set to 100. Otherwise will be set to 0xffff, and should be ignored.|

Set the progress of the Upload OOB image retrieval. Used to inform the stack about the progress, and to indicate when the process is complete.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_get_node_status_by_index

`sl_status_t sl_btmesh_fw_dist_server_get_node_status_by_index(uint16_t elem_index, uint16_t entry_index, uint16_t *address, uint8_t *retrieved_phase, uint8_t *update_server_status, uint8_t *mbt_server_status, uint8_t *transfer_progress, uint8_t *fw_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|entry_index|Node entry index|
|uint16_t *|[out]|address|Address of the Update Server|
|uint8_t *|[out]|retrieved_phase|Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Phase of the Update Server|
|uint8_t *|[out]|update_server_status|Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Last Update Status message received from the Update Server|
|uint8_t *|[out]|mbt_server_status|Enum [sl_btmesh_mbt_server_status_t](sl-btmesh-mbt-server#sl-btmesh-mbt-server-status-t). Last Transfer Status message received from the BLOB Transfer Server|
|uint8_t *|[out]|transfer_progress|0-100, percentage of BLOB Transfer octets delivered and confirmed|
|uint8_t *|[out]|fw_index|Index of the firmware being updated|

Retrieve information about the ongoing update on a node

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_get_node_status_by_address

`sl_status_t sl_btmesh_fw_dist_server_get_node_status_by_address(uint16_t elem_index, uint16_t node_address, uint16_t *address, uint8_t *retrieved_phase, uint8_t *update_server_status, uint8_t *mbt_server_status, uint8_t *transfer_progress, uint8_t *fw_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|node_address|Node mesh address|
|uint16_t *|[out]|address|Address of the Update Server|
|uint8_t *|[out]|retrieved_phase|Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Phase of the Update Server|
|uint8_t *|[out]|update_server_status|Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Last Update Status message received from the Update Server|
|uint8_t *|[out]|mbt_server_status|Enum [sl_btmesh_mbt_server_status_t](sl-btmesh-mbt-server#sl-btmesh-mbt-server-status-t). Last Transfer Status message received from the BLOB Transfer Server|
|uint8_t *|[out]|transfer_progress|0-100, percentage of BLOB Transfer octets delivered and confirmed|
|uint8_t *|[out]|fw_index|Index of the firmware being updated|

Retrieve information about the ongoing update by a node address

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_delete_rsp

`sl_status_t sl_btmesh_fw_dist_server_delete_rsp(uint16_t elem_index, uint16_t status, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|status|Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code to use for the response. Must be one of the following:<br/><br/>- **0:** success - requested firmware entry deleted by the application<br/>- **1:** out of resources<br/>- **3:** internal error occurred<br/><br/>All other status codes are reserved or automatically sent by the stack.|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the image that was requested to be deleted.|

Response to the [sl_btmesh_evt_fw_dist_server_fw_delete_req](sl-btmesh-evt-fw-dist-server-fw-delete-req) event. The application should check that requested firmware image exists and can be deleted. The stack will ignore incoming [sl_btmesh_fw_dist_client_start_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-distribution), [sl_btmesh_fw_dist_client_start_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-upload), [sl_btmesh_fw_dist_client_get_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw), [sl_btmesh_fw_dist_client_get_fw_by_index](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw-by-index), [sl_btmesh_fw_dist_client_delete_all_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-delete-all-fw) commands until the response is called.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_dist_start_rsp

`sl_status_t sl_btmesh_fw_dist_server_dist_start_rsp(uint16_t elem_index, uint16_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|status|mesh_dfu_dist_status_success to accept, mesh_dfu_dist_status_internal_error to reject|

Response to the [sl_btmesh_evt_fw_dist_server_dist_start_req](sl-btmesh-evt-fw-dist-server-dist-start-req) event. The stack will ignore incoming [sl_btmesh_fw_dist_client_start_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-distribution), [sl_btmesh_fw_dist_client_start_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-upload), [sl_btmesh_fw_dist_client_get_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw), [sl_btmesh_fw_dist_client_get_fw_by_index](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw-by-index), [sl_btmesh_fw_dist_client_delete_all_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-delete-all-fw) commands until the response is called.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_set_multicast_threshold

`sl_status_t sl_btmesh_fw_dist_server_set_multicast_threshold(uint16_t elem_index, uint16_t multicast_threshold)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|multicast_threshold|This value will be passed to the MBT Client. If the number of servers for any step exceeds or is equal to this number, the group address will be used. Otherwise, servers will be looped through one by one. Value of 0 disables the feature.|

Set the multicast threshold value.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_delete_all_rsp

`sl_status_t sl_btmesh_fw_dist_server_delete_all_rsp(uint16_t elem_index, uint16_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|status|Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code to use for the response. Must be one of the following:<br/><br/>- **0:** success - firmware entries deleted by the application<br/>- **1:** out of resources<br/>- **3:** internal error occurred<br/><br/>All other status codes are reserved or automatically sent by the stack.|

Response to the [sl_btmesh_evt_fw_dist_server_fw_delete_all_req](sl-btmesh-evt-fw-dist-server-fw-delete-all-req) event. The application should check that all firmware images can be deleted. The stack will ignore incoming [sl_btmesh_fw_dist_client_start_distribution](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-distribution), [sl_btmesh_fw_dist_client_start_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-upload), [sl_btmesh_fw_dist_client_get_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw), [sl_btmesh_fw_dist_client_get_fw_by_index](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-fw-by-index), [sl_btmesh_fw_dist_client_delete_all_fw](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-delete-all-fw) commands until the response is called.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_resume_rsp

`sl_status_t sl_btmesh_fw_dist_server_resume_rsp(uint16_t elem_index, uint16_t status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|status|Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code to use for the response. Must be one of the following:<br/><br/>- **0:** success - resume distribution<br/>- **1:** out of resources<br/>- **3:** internal error occurred<br/><br/>All other status codes are reserved or automatically sent by the stack.|

Response to the [sl_btmesh_evt_fw_dist_server_resume_req](sl-btmesh-evt-fw-dist-server-resume-req) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_server_configure_throttle

`sl_status_t sl_btmesh_fw_dist_server_configure_throttle(uint16_t elem_index, uint16_t throttle_delay_ms, uint8_t throttle_concurrent)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|throttle_delay_ms|Controls the delay in milliseconds between batches of messages. Works in conjunction with `throttle_concurrent` to control message sending rate. When the first transmission in the current batch completes, the sender will wait for this delay before refilling the batch up to the `throttle_concurrent` limit with new transmissions.|
|uint8_t|[in]|throttle_concurrent|Defines how many messages are being sent concurrently. If set to 0, the maximum supported value is used.|

Configure the sender parameters for the Distributor Server. This command is used to set the parameters that will be used when sending messages to the Target Nodes.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_fw_dist_server_init_id 0x00580028`

`#define sl_btmesh_cmd_fw_dist_server_deinit_id 0x01580028`

`#define sl_btmesh_cmd_fw_dist_server_upload_start_rsp_id 0x02580028`

`#define sl_btmesh_cmd_fw_dist_server_execute_distribution_step_id 0x03580028`

`#define sl_btmesh_cmd_fw_dist_server_upload_oob_start_rsp_id 0x08580028`

`#define sl_btmesh_cmd_fw_dist_server_set_upload_oob_metadata_id 0x09580028`

`#define sl_btmesh_cmd_fw_dist_server_set_upload_oob_image_size_id 0x0a580028`

`#define sl_btmesh_cmd_fw_dist_server_set_upload_oob_progress_id 0x0b580028`

`#define sl_btmesh_cmd_fw_dist_server_get_node_status_by_index_id 0x0c580028`

`#define sl_btmesh_cmd_fw_dist_server_get_node_status_by_address_id 0x0d580028`

`#define sl_btmesh_cmd_fw_dist_server_delete_rsp_id 0x0e580028`

`#define sl_btmesh_cmd_fw_dist_server_dist_start_rsp_id 0x13580028`

`#define sl_btmesh_cmd_fw_dist_server_set_multicast_threshold_id 0x14580028`

`#define sl_btmesh_cmd_fw_dist_server_delete_all_rsp_id 0x0f580028`

`#define sl_btmesh_cmd_fw_dist_server_resume_rsp_id 0x10580028`

`#define sl_btmesh_cmd_fw_dist_server_configure_throttle_id 0x15580028`

`#define sl_btmesh_rsp_fw_dist_server_init_id 0x00580028`

`#define sl_btmesh_rsp_fw_dist_server_deinit_id 0x01580028`

`#define sl_btmesh_rsp_fw_dist_server_upload_start_rsp_id 0x02580028`

`#define sl_btmesh_rsp_fw_dist_server_execute_distribution_step_id 0x03580028`

`#define sl_btmesh_rsp_fw_dist_server_upload_oob_start_rsp_id 0x08580028`

`#define sl_btmesh_rsp_fw_dist_server_set_upload_oob_metadata_id 0x09580028`

`#define sl_btmesh_rsp_fw_dist_server_set_upload_oob_image_size_id 0x0a580028`

`#define sl_btmesh_rsp_fw_dist_server_set_upload_oob_progress_id 0x0b580028`

`#define sl_btmesh_rsp_fw_dist_server_get_node_status_by_index_id 0x0c580028`

`#define sl_btmesh_rsp_fw_dist_server_get_node_status_by_address_id 0x0d580028`

`#define sl_btmesh_rsp_fw_dist_server_delete_rsp_id 0x0e580028`

`#define sl_btmesh_rsp_fw_dist_server_dist_start_rsp_id 0x13580028`

`#define sl_btmesh_rsp_fw_dist_server_set_multicast_threshold_id 0x14580028`

`#define sl_btmesh_rsp_fw_dist_server_delete_all_rsp_id 0x0f580028`

`#define sl_btmesh_rsp_fw_dist_server_resume_rsp_id 0x10580028`

`#define sl_btmesh_rsp_fw_dist_server_configure_throttle_id 0x15580028`

#### sl_btmesh_evt_fw_dist_server_nodes_added

Event indicating nodes were added to the Distributor Server's Nodes List. 

##### Modules

[sl_btmesh_evt_fw_dist_server_nodes_added_s](sl-btmesh-evt-fw-dist-server-nodes-added-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_nodes_added_t

`typedef struct sl_btmesh_evt_fw_dist_server_nodes_added_s sl_btmesh_evt_fw_dist_server_nodes_added_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_nodes_added_id 0x005800a8`

**Description**: Identifier of the nodes_added event.

Data structure of the nodes_added event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_nodes_added_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_nodes_added_s::client_address
```

**Details:** Address of the Distribution Client

###### total_nodes (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_nodes_added_s::total_nodes
```

**Details:** Total number of nodes now on the list

###### num_added_nodes (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_nodes_added_s::num_added_nodes
```

**Details:** Number of nodes added

###### added_nodes (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_nodes_added_s::added_nodes
```

**Details:** Address - firmware index pairs that were added

#### sl_btmesh_evt_fw_dist_server_nodes_deleted

Event indicating the Nodes List was cleared. 

##### Modules

[sl_btmesh_evt_fw_dist_server_nodes_deleted_s](sl-btmesh-evt-fw-dist-server-nodes-deleted-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_nodes_deleted_t

`typedef struct sl_btmesh_evt_fw_dist_server_nodes_deleted_s sl_btmesh_evt_fw_dist_server_nodes_deleted_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_nodes_deleted_id 0x015800a8`

**Description**: Identifier of the nodes_deleted event.

Data structure of the nodes_deleted event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_nodes_deleted_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_nodes_deleted_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_fw_dist_server_dist_start_req

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_dist_start_req_s](sl-btmesh-evt-fw-dist-server-dist-start-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_dist_start_req_t

`typedef struct sl_btmesh_evt_fw_dist_server_dist_start_req_s sl_btmesh_evt_fw_dist_server_dist_start_req_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_dist_start_req_id 0x025800a8`

**Description**: Identifier of the dist_start_req event.

Data structure of the dist_start_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::client_address
```

**Details:** Address of the Distribution Client

###### group_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::group_address
```

**Details:** Group address of the distribution

###### virtual_address (heading level 7)

```
uuid_128 sl_btmesh_evt_fw_dist_server_dist_start_req_s::virtual_address
```

**Details:** If the group address is a VA hash, this contains the full virtual address label UUID of the distribution. Otherwise, the value of this field should be ignored.

###### ttl (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::ttl
```

**Details:** Distribution TTL

###### apply_immediately (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::apply_immediately
```

**Details:** Enum [sl_btmesh_fw_dist_server_dfu_policy_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dfu-policy-t). 1 if the Update Policy is Verify and Apply, otherwise 0.

###### fw_list_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::fw_list_index
```

**Details:** Index of the firmware in the Distributor's FW List

###### timeout_base (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::timeout_base
```

**Details:** Timeout base

###### transfer_mode (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_dist_start_req_s::transfer_mode
```

**Details:** Transfer Mode to use in the distribution

#### sl_btmesh_evt_fw_dist_server_dist_cancel

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_dist_cancel_s](sl-btmesh-evt-fw-dist-server-dist-cancel-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_dist_cancel_t

`typedef struct sl_btmesh_evt_fw_dist_server_dist_cancel_s sl_btmesh_evt_fw_dist_server_dist_cancel_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_dist_cancel_id 0x035800a8`

**Description**: Identifier of the dist_cancel event.

Data structure of the dist_cancel event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_cancel_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_cancel_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_fw_dist_server_dist_cancel_complete

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_dist_cancel_complete_s](sl-btmesh-evt-fw-dist-server-dist-cancel-complete-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_dist_cancel_complete_t

`typedef struct sl_btmesh_evt_fw_dist_server_dist_cancel_complete_s sl_btmesh_evt_fw_dist_server_dist_cancel_complete_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_dist_cancel_complete_id 0x045800a8`

**Description**: Identifier of the dist_cancel_complete event.

Data structure of the dist_cancel_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_cancel_complete_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_cancel_complete_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_fw_dist_server_upload_start_metadata

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_start_metadata_s](sl-btmesh-evt-fw-dist-server-upload-start-metadata-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_start_metadata_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_start_metadata_s sl_btmesh_evt_fw_dist_server_upload_start_metadata_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_start_metadata_id 0x055800a8`

**Description**: Identifier of the upload_start_metadata event.

Data structure of the upload_start_metadata event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_start_metadata_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_start_metadata_s::client_address
```

**Details:** Address of the Distribution Client

###### metadata (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_start_metadata_s::metadata
```

**Details:** Metadata of the FW

#### sl_btmesh_evt_fw_dist_server_upload_start_req

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_start_req_s](sl-btmesh-evt-fw-dist-server-upload-start-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_start_req_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_start_req_s sl_btmesh_evt_fw_dist_server_upload_start_req_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_start_req_id 0x065800a8`

**Description**: Identifier of the upload_start_req event.

Data structure of the upload_start_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_start_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_start_req_s::client_address
```

**Details:** Address of the Distribution Client

###### size (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_server_upload_start_req_s::size
```

**Details:** Upload size

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_dist_server_upload_start_req_s::blob_id
```

**Details:** BLOB ID

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_start_req_s::fwid
```

**Details:** FWID of the firmware image

#### sl_btmesh_evt_fw_dist_server_upload_cancel

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_cancel_s](sl-btmesh-evt-fw-dist-server-upload-cancel-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_cancel_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_cancel_s sl_btmesh_evt_fw_dist_server_upload_cancel_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_cancel_id 0x085800a8`

**Description**: Identifier of the upload_cancel event.

Data structure of the upload_cancel event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_cancel_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_cancel_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_fw_dist_server_dist_state_changed

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_dist_state_changed_s](sl-btmesh-evt-fw-dist-server-dist-state-changed-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_dist_state_changed_t

`typedef struct sl_btmesh_evt_fw_dist_server_dist_state_changed_s sl_btmesh_evt_fw_dist_server_dist_state_changed_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_dist_state_changed_id 0x0b5800a8`

**Description**: Identifier of the dist_state_changed event.

Data structure of the dist_state_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_state_changed_s::elem_index
```

**Details:** Server model element index

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_dist_state_changed_s::state
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_step_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-step-t). New state of the Distribution

###### num_active_nodes (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_state_changed_s::num_active_nodes
```

**Details:** Number of active nodes

#### sl_btmesh_evt_fw_dist_server_node_failed

Indicates that an Target Node failed, either due to an error or due to timeout. 

##### Modules

[sl_btmesh_evt_fw_dist_server_node_failed_s](sl-btmesh-evt-fw-dist-server-node-failed-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_node_failed_t

`typedef struct sl_btmesh_evt_fw_dist_server_node_failed_s sl_btmesh_evt_fw_dist_server_node_failed_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_node_failed_id 0x0c5800a8`

**Description**: Identifier of the node_failed event.

Data structure of the node_failed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_node_failed_s::elem_index
```

**Details:** Server model element index

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_node_failed_s::address
```

**Details:** Address of the Update Server

###### update_phase (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_node_failed_s::update_phase
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Update Phase of the Update Server. 0xa if not known yet.

###### update_status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_node_failed_s::update_status
```

**Details:** Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Last Update Status message received from the Update Server

###### mbt_status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_node_failed_s::mbt_status
```

**Details:** Last status code received from the MBT Server. 0xa if not known yet.

###### progress (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_node_failed_s::progress
```

**Details:** 0-100, percentage of BLOB Transfer octets delivered and confirmed

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_server_node_failed_s::fw_index
```

**Details:** Index of the firmware being updated

#### sl_btmesh_evt_fw_dist_server_upload_complete_metadata

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_complete_metadata_s](sl-btmesh-evt-fw-dist-server-upload-complete-metadata-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_complete_metadata_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_complete_metadata_s sl_btmesh_evt_fw_dist_server_upload_complete_metadata_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_complete_metadata_id 0x0d5800a8`

**Description**: Identifier of the upload_complete_metadata event.

Data structure of the upload_complete_metadata event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_complete_metadata_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_complete_metadata_s::client_address
```

**Details:** Address of the Distribution Client

###### metadata (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_complete_metadata_s::metadata
```

**Details:** Metadata of the firmware image

#### sl_btmesh_evt_fw_dist_server_upload_complete

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_complete_s](sl-btmesh-evt-fw-dist-server-upload-complete-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_complete_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_complete_s sl_btmesh_evt_fw_dist_server_upload_complete_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_complete_id 0x0e5800a8`

**Description**: Identifier of the upload_complete event.

Data structure of the upload_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_complete_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_complete_s::client_address
```

**Details:** Address of the Distribution Client

###### size (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_server_upload_complete_s::size
```

**Details:** Upload size

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_dist_server_upload_complete_s::blob_id
```

**Details:** BLOB ID

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_complete_s::fwid
```

**Details:** FWID of the firmware image

#### sl_btmesh_evt_fw_dist_server_upload_failed

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_failed_s](sl-btmesh-evt-fw-dist-server-upload-failed-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_failed_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_failed_s sl_btmesh_evt_fw_dist_server_upload_failed_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_failed_id 0x0f5800a8`

**Description**: Identifier of the upload_failed event.

Data structure of the upload_failed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_failed_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_failed_s::client_address
```

**Details:** Address of the Distribution Client

###### size (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_server_upload_failed_s::size
```

**Details:** Upload size

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_dist_server_upload_failed_s::blob_id
```

**Details:** BLOB ID

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_failed_s::fwid
```

**Details:** FWID of the firmware image

#### sl_btmesh_evt_fw_dist_server_upload_oob_start_uri

URI for the Upload OOB Start request event [sl_btmesh_evt_fw_dist_server_upload_oob_start_req](sl-btmesh-evt-fw-dist-server-upload-oob-start-req) that follows. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_s](sl-btmesh-evt-fw-dist-server-upload-oob-start-uri-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_s sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_id 0x105800a8`

**Description**: Identifier of the upload_oob_start_uri event.

Data structure of the upload_oob_start_uri event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_s::client_address
```

**Details:** Address of the Distribution Client

###### uri (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_s::uri
```

**Details:** URI to use for retrieving a new firmware image

#### sl_btmesh_evt_fw_dist_server_upload_oob_start_req

Upload OOB Start request. 

The preceding event [sl_btmesh_evt_fw_dist_server_upload_oob_start_uri](sl-btmesh-evt-fw-dist-server-upload-oob-start-uri) contains the URI to use in combination with the FWID of this event. The application should execute the Check Firmware OOB procedure and then respond to this event with the command [sl_btmesh_fw_dist_server_upload_oob_start_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-upload-oob-start-rsp) according to the information received OOB. 

##### Modules

[sl_btmesh_evt_fw_dist_server_upload_oob_start_req_s](sl-btmesh-evt-fw-dist-server-upload-oob-start-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_upload_oob_start_req_t

`typedef struct sl_btmesh_evt_fw_dist_server_upload_oob_start_req_s sl_btmesh_evt_fw_dist_server_upload_oob_start_req_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_upload_oob_start_req_id 0x115800a8`

**Description**: Identifier of the upload_oob_start_req event.

Data structure of the upload_oob_start_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_oob_start_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_upload_oob_start_req_s::client_address
```

**Details:** Address of the Distribution Client

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_upload_oob_start_req_s::fwid
```

**Details:** FWID to use for retrieving a new firmware image

#### sl_btmesh_evt_fw_dist_server_fw_delete_req

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_fw_delete_req_s](sl-btmesh-evt-fw-dist-server-fw-delete-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_fw_delete_req_t

`typedef struct sl_btmesh_evt_fw_dist_server_fw_delete_req_s sl_btmesh_evt_fw_dist_server_fw_delete_req_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_fw_delete_req_id 0x125800a8`

**Description**: Identifier of the fw_delete_req event.

Data structure of the fw_delete_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_fw_delete_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_fw_delete_req_s::client_address
```

**Details:** Address of the Distribution Client

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_server_fw_delete_req_s::fwid
```

**Details:** FWID of the firmware that was deleted

#### sl_btmesh_evt_fw_dist_server_fw_delete_all_req

None. 

##### Modules

[sl_btmesh_evt_fw_dist_server_fw_delete_all_req_s](sl-btmesh-evt-fw-dist-server-fw-delete-all-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_fw_delete_all_req_t

`typedef struct sl_btmesh_evt_fw_dist_server_fw_delete_all_req_s sl_btmesh_evt_fw_dist_server_fw_delete_all_req_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_fw_delete_all_req_id 0x135800a8`

**Description**: Identifier of the fw_delete_all_req event.

Data structure of the fw_delete_all_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_fw_delete_all_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_fw_delete_all_req_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_fw_dist_server_dist_suspend

The distribution was suspended temporarily. 

##### Modules

[sl_btmesh_evt_fw_dist_server_dist_suspend_s](sl-btmesh-evt-fw-dist-server-dist-suspend-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_dist_suspend_t

`typedef struct sl_btmesh_evt_fw_dist_server_dist_suspend_s sl_btmesh_evt_fw_dist_server_dist_suspend_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_dist_suspend_id 0x155800a8`

**Description**: Identifier of the dist_suspend event.

Data structure of the dist_suspend event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_suspend_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_dist_suspend_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_fw_dist_server_resume_req

The distribution resuming is requested. 

##### Modules

[sl_btmesh_evt_fw_dist_server_resume_req_s](sl-btmesh-evt-fw-dist-server-resume-req-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_server_resume_req_t

`typedef struct sl_btmesh_evt_fw_dist_server_resume_req_s sl_btmesh_evt_fw_dist_server_resume_req_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_server_resume_req_id 0x165800a8`

**Description**: Identifier of the resume_req event.

Data structure of the resume_req event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::client_address
```

**Details:** Address of the Distribution Client

###### group_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::group_address
```

**Details:** Group address to use for the distribution

###### app_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::app_index
```

**Details:** Appkey index to use for the distribution

###### ttl (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::ttl
```

**Details:** TTL to use for the distribution

###### update_policy (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::update_policy
```

**Details:** Update Policy to use for the distribution

###### fw_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::fw_index
```

**Details:** Distribution Server's Firmware Image List Index of the image to transfer

###### timeout_base (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::timeout_base
```

**Details:** Timeout Base to use for the distribution

###### transfer_mode (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_server_resume_req_s::transfer_mode
```

**Details:** BLOB Transfer Mode to use for transferring the image

### Bluetooth Mesh Firmware Distribution Client Model

Bluetooth Mesh Firmware Distribution Client Model. 

The Bluetooth Mesh Firmware Distribution Client Model is used to transfer new firmware images to Bluetooth Mesh Firmware Distribution Server Model and monitor progress of a firmware update. As a transport layer Bluetooth Mesh BLOB Transfer (MBT) models are in use. 

#### Modules

[sl_btmesh_evt_fw_dist_client_receivers_status](sl-btmesh-evt-fw-dist-client-receivers-status)

[sl_btmesh_evt_fw_dist_client_receivers_list](sl-btmesh-evt-fw-dist-client-receivers-list)

[sl_btmesh_evt_fw_dist_client_receivers_list_end](sl-btmesh-evt-fw-dist-client-receivers-list-end)

[sl_btmesh_evt_fw_dist_client_capabilities_status](sl-btmesh-evt-fw-dist-client-capabilities-status)

[sl_btmesh_evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)

[sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status)

[sl_btmesh_evt_fw_dist_client_fw_status](sl-btmesh-evt-fw-dist-client-fw-status)

[sl_btmesh_evt_fw_dist_client_upload_complete](sl-btmesh-evt-fw-dist-client-upload-complete)

[sl_btmesh_evt_fw_dist_client_upload_failed](sl-btmesh-evt-fw-dist-client-upload-failed)

#### Enumerations

##### sl_btmesh_fw_dist_client_upload_phase_t

```
enum sl_btmesh_fw_dist_client_upload_phase_t {
    sl_btmesh_fw_dist_client_upload_phase_idle = 0x0
    sl_btmesh_fw_dist_client_upload_phase_transfer_in_progress = 0x1
    sl_btmesh_fw_dist_client_upload_phase_transfer_error = 0x2
    sl_btmesh_fw_dist_client_upload_phase_transfer_completed = 0x3
}
```

**Description:**

The Upload Phase of the Firmware Distribution Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_client_upload_phase_idle|(0x0) No Upload in progress.|
|sl_btmesh_fw_dist_client_upload_phase_transfer_in_progress|(0x1) Upload in progress.|
|sl_btmesh_fw_dist_client_upload_phase_transfer_error|(0x2) Upload or Upload OOB encountered a transfer error.|
|sl_btmesh_fw_dist_client_upload_phase_transfer_completed|(0x3) Upload or Upload OOB completed successfully.|

##### sl_btmesh_fw_dist_client_dist_upload_type_t

```
enum sl_btmesh_fw_dist_client_dist_upload_type_t {
    sl_btmesh_fw_dist_client_dist_upload_type_in_band = 0x0
    sl_btmesh_fw_dist_client_dist_upload_type_out_of_band = 0x1
}
```

**Description:**

The Upload Type of an ongoing or finished upload.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_client_dist_upload_type_in_band|(0x0) In-band upload via BLOB Transfer.|
|sl_btmesh_fw_dist_client_dist_upload_type_out_of_band|(0x1) Out-of-band upload.|

##### sl_btmesh_fw_dist_client_dist_oob_t

```
enum sl_btmesh_fw_dist_client_dist_oob_t {
    sl_btmesh_fw_dist_client_dist_oob_not_supported = 0x0
    sl_btmesh_fw_dist_client_dist_oob_supported = 0x1
}
```

**Description:**

Distribution Server OOB Support capability values.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_client_dist_oob_not_supported|(0x0) Upload OOB not supported.|
|sl_btmesh_fw_dist_client_dist_oob_supported|(0x1) Upload OOB supported.|

##### sl_btmesh_fw_dist_client_dist_phase_t

```
enum sl_btmesh_fw_dist_client_dist_phase_t {
    sl_btmesh_fw_dist_client_dist_phase_idle = 0x0
    sl_btmesh_fw_dist_client_dist_phase_active = 0x1
    sl_btmesh_fw_dist_client_dist_phase_transferred = 0x2
    sl_btmesh_fw_dist_client_dist_phase_applying = 0x3
    sl_btmesh_fw_dist_client_dist_phase_completed = 0x4
    sl_btmesh_fw_dist_client_dist_phase_failed = 0x5
    sl_btmesh_fw_dist_client_dist_phase_cancelling = 0x6
    sl_btmesh_fw_dist_client_dist_phase_suspended = 0x7
}
```

**Description:**

The Distribution Phase of the Firmware Distribution Server.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_fw_dist_client_dist_phase_idle|(0x0) No firmware distribution is in progress.|
|sl_btmesh_fw_dist_client_dist_phase_active|(0x1) Firmware distribution in progress; sending Update Start or BLOB Transfer messages.|
|sl_btmesh_fw_dist_client_dist_phase_transferred|(0x2) Firmware distribution in progress; BLOB Transfer is complete, waiting for verification. If the Update Policy is Verify Only, the Distribution Server will park here until it receives a Distribution Apply message from the Distribution Client.|
|sl_btmesh_fw_dist_client_dist_phase_applying|(0x3) Firmware distribution in progress; sending Update Apply messages.|
|sl_btmesh_fw_dist_client_dist_phase_completed|(0x4) Firmware distribution completed successfully for at least one Target Node.|
|sl_btmesh_fw_dist_client_dist_phase_failed|(0x5) Firmware distribution failed for all Target Nodes.|
|sl_btmesh_fw_dist_client_dist_phase_cancelling|(0x6) Cancelling firmware distribution.|
|sl_btmesh_fw_dist_client_dist_phase_suspended|(0x7) Firmware distribution is temporarily suspended.|

#### Functions

##### sl_btmesh_fw_dist_client_init

`sl_status_t sl_btmesh_fw_dist_client_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Initialize the Firmware Distribution Client model. An MBT Client on the same element must have been initialized prior to making this call.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_deinit

`sl_status_t sl_btmesh_fw_dist_client_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Deinitialize the Firmware Distribution Client model. The corresponding MBT Client instance can be deinitialized before or after the Distribution Client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_setup

`sl_status_t sl_btmesh_fw_dist_client_setup(uint16_t elem_index, uint16_t appkey_index, uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|appkey_index|Application key index|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|

Set up the communication parameters for a Distribution Client instance.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_setup_upload

`sl_status_t sl_btmesh_fw_dist_client_setup_upload(uint16_t elem_index, uint16_t server_address, uint8_t ttl, uint16_t timeout_base, sl_bt_uuid_64_t blob_id, uint32_t size, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|server_address|Address of the target Distributor|
|uint8_t|[in]|ttl|The time-to-live value to use for the upload. Valid values: 0, range:[2-127] and 255.|
|uint16_t|[in]|timeout_base|Timeout Base value for the BLOB Transfer|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t)|[in]|blob_id|BLOB ID to use|
|uint32_t|[in]|size|Size of the firmware image|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the firmware image|

Set up an in-band Upload of a firmware image. Note that only one upload can be executed at a time. This command must be used before setting the upload image metadata via [sl_btmesh_fw_dist_client_set_upload_metadata](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-set-upload-metadata).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_set_upload_metadata

`sl_status_t sl_btmesh_fw_dist_client_set_upload_metadata(uint16_t elem_index, size_t metadata_len, const uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|size_t|[in]|metadata_len|Length of data in `metadata`|
|const uint8_t *|[in]|metadata|Metadata for the firmware image|

Set the metadata for an in-band Upload of a firmware image.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_get_receivers

`sl_status_t sl_btmesh_fw_dist_client_get_receivers(uint16_t elem_index, uint16_t dst, uint16_t start_index, uint16_t max_entries)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|
|uint16_t|[in]|start_index|Starting index of node statuses to request|
|uint16_t|[in]|max_entries|Maximum number of node statuses to request|

Send a Receivers Get message. This function is used to get a slice of the Receivers List on the Distribution Server. The response is a Receivers List message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_receivers_list](sl-btmesh-evt-fw-dist-client-receivers-list)
- [sl_btmesh_evt_fw_dist_client_receivers_list_end](sl-btmesh-evt-fw-dist-client-receivers-list-end)

##### sl_btmesh_fw_dist_client_get

`sl_status_t sl_btmesh_fw_dist_client_get(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Distribution Get message. This function is used to determine the parameters of an ongoing distribution, if any. The response is a Distribution Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)

##### sl_btmesh_fw_dist_client_start_distribution

`sl_status_t sl_btmesh_fw_dist_client_start_distribution(uint16_t elem_index, uint16_t dst, uint16_t dist_appkey_index, uint8_t dist_ttl, uint16_t dist_timeout_base, uint8_t transfer_mode, uint8_t update_policy, uint16_t fw_list_index, uint16_t group_address, uuid_128 virtual_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|
|uint16_t|[in]|dist_appkey_index|Application key to use for the communication between the Distributor and Target Nodes|
|uint8_t|[in]|dist_ttl|The time-to-live value for the Distributor to use when communicating with the Target Nodes. Valid values: 0, range:[2-127] and 255|
|uint16_t|[in]|dist_timeout_base|The Timeout Base value to use in the firmware image BLOB Transfer|
|uint8_t|[in]|transfer_mode|1 = use Push Mode, 2 = use Pull Mode (typically for LPNs)|
|uint8_t|[in]|update_policy|Enum [sl_btmesh_fw_dist_server_dfu_policy_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dfu-policy-t). 0 = Verify Only (Initiator sends Distribution Apply to Distributor to apply the update), 1 = Verify and Apply (Distributor applies update automatically)|
|uint16_t|[in]|fw_list_index|Index of the firmware image in the Distributor's Firmware List|
|uint16_t|[in]|group_address|Group address to use. Zero to only use unicast.|
|[uuid_128](uuid-128)|[in]|virtual_address|If the group address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|

Send a Distribution Start message. This function is used to start a new distribution process. The Receivers List must have been populated via [sl_btmesh_fw_dist_client_add_receivers](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-add-receivers), and the firmware image must have been uploaded to the Distribution Server. The response is a Distribution Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)

##### sl_btmesh_fw_dist_client_cancel_distribution

`sl_status_t sl_btmesh_fw_dist_client_cancel_distribution(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Distribution Cancel message. This function is used to cancel a distribution process. The response is a Distribution Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)

##### sl_btmesh_fw_dist_client_apply_distribution

`sl_status_t sl_btmesh_fw_dist_client_apply_distribution(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Distribution Apply message. This function is used to trigger applying the firmware update on the Target Nodes. This should only be used if the Update Policy of the distribution is Verify Only. The response is a Distribution Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)

##### sl_btmesh_fw_dist_client_suspend_distribution

`sl_status_t sl_btmesh_fw_dist_client_suspend_distribution(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Distribution Suspend message. This function is used to suspend a distribution when the BLOB Transfer is still in progress. It cannot be used after the image has already been fully transferred. The response is a Distribution Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_distribution_status](sl-btmesh-evt-fw-dist-client-distribution-status)

##### sl_btmesh_fw_dist_client_add_receivers

`sl_status_t sl_btmesh_fw_dist_client_add_receivers(uint16_t elem_index, uint16_t dst, size_t nodes_len, const uint8_t *nodes)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|
|size_t|[in]|nodes_len|Length of data in `nodes`|
|const uint8_t *|[in]|nodes|List of (address [uint16], fw_index [uint8]) pairs.|

Send a Receivers Add message. This function is used to add Target Nodes to the Distribution Server's Receivers List. The response is a Receivers Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_receivers_status](sl-btmesh-evt-fw-dist-client-receivers-status)

##### sl_btmesh_fw_dist_client_delete_all_receivers

`sl_status_t sl_btmesh_fw_dist_client_delete_all_receivers(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Receivers Delete All message. This function is used to clear the Receivers List on the Distribution Server. The response is a Receivers Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_receivers_status](sl-btmesh-evt-fw-dist-client-receivers-status)

##### sl_btmesh_fw_dist_client_get_capabilities

`sl_status_t sl_btmesh_fw_dist_client_get_capabilities(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Capabilities Get message. This function is used to determine the Distribution Capabilities of a Distribution Server. The response is a Capabilities Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_capabilities_status](sl-btmesh-evt-fw-dist-client-capabilities-status)

##### sl_btmesh_fw_dist_client_get_upload

`sl_status_t sl_btmesh_fw_dist_client_get_upload(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send an Upload Get message. This function is used to check if an upload is ongoing, and what its progress is. The response is an Upload Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status)

##### sl_btmesh_fw_dist_client_start_upload

`sl_status_t sl_btmesh_fw_dist_client_start_upload(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Start an upload previously set up with [sl_btmesh_fw_dist_client_setup_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-setup-upload). Calling this function will send an Upload Start message. The response is an Upload Status message. Note that if the remote end does not respond, this function may need to be retried. Note that upon sending the Upload Start message a response timer is started for a time frame of: (10000 * (timeout_base + 2)) + (100 * ttl) in units of ms.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status)
- [sl_btmesh_evt_fw_dist_client_upload_failed](sl-btmesh-evt-fw-dist-client-upload-failed)

##### sl_btmesh_fw_dist_client_cancel_upload

`sl_status_t sl_btmesh_fw_dist_client_cancel_upload(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Cancel an upload previously started with [sl_btmesh_fw_dist_client_start_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-upload).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status)

##### sl_btmesh_fw_dist_client_get_fw

`sl_status_t sl_btmesh_fw_dist_client_get_fw(uint16_t elem_index, uint16_t dst, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the firmware image|

Send a Firmware Get message. This function is used to check if a firmware image with the given FWID exists on the Distribution Server, and if it does, to retrieve its Firmware List Index. The response is a Firmware Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_fw_status](sl-btmesh-evt-fw-dist-client-fw-status)

##### sl_btmesh_fw_dist_client_get_fw_by_index

`sl_status_t sl_btmesh_fw_dist_client_get_fw_by_index(uint16_t elem_index, uint16_t dst, uint16_t index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|
|uint16_t|[in]|index|Index to check|

Send a Firmware Get By Index message. This function is used to check if a firmware with a particular index exists on the Distribution Server, and if it does, to retrieve its FWID. The response is a Firmware Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_fw_status](sl-btmesh-evt-fw-dist-client-fw-status)

##### sl_btmesh_fw_dist_client_delete_fw

`sl_status_t sl_btmesh_fw_dist_client_delete_fw(uint16_t elem_index, uint16_t dst, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the firmware image|

Send a Firmware Delete message. This function is used to delete a particular firmware on the Distribution Server. The response is a Firmware Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_fw_status](sl-btmesh-evt-fw-dist-client-fw-status)

##### sl_btmesh_fw_dist_client_delete_all_fw

`sl_status_t sl_btmesh_fw_dist_client_delete_all_fw(uint16_t elem_index, uint16_t dst)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Address of the Distributor|

Send a Firmware Delete All message. This function is used to delete all firmware images on the Distribution Server. The response is a Firmware Status message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_fw_status](sl-btmesh-evt-fw-dist-client-fw-status)

##### sl_btmesh_fw_dist_client_prepare_oob_upload

`sl_status_t sl_btmesh_fw_dist_client_prepare_oob_upload(uint16_t elem_index, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|FWID used to form the query string for the Distribution Server's Check Firmware OOB and Store Firmware OOB procedures.|

Prepare an OOB Upload. This must be called before calling the [sl_btmesh_fw_dist_client_start_oob_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-oob-upload) command. Calling this multiple times will overwrite the state of the previous OOB Upload.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_start_oob_upload

`sl_status_t sl_btmesh_fw_dist_client_start_oob_upload(uint16_t elem_index, uint16_t dst, uint16_t appkey_index, uint8_t ttl, size_t uri_len, const uint8_t *uri)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|dst|Destination address|
|uint16_t|[in]|appkey_index|Application key index to use for encrypting the message.|
|uint8_t|[in]|ttl|The time-to-live value to use. Valid values: 0, range:[2-127] and 255.|
|size_t|[in]|uri_len|Length of data in `uri`|
|const uint8_t *|[in]|uri|URI used to form the query string for the Distribution Server's Check Firmware OOB and Store Firmware OOB procedures.|

Start an OOB Upload. The response is an [sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status) event. This command must be repeated by the application if the remote end does not respond. If the event's status field is zero, the request was accepted; otherwise it was rejected. If the event indicates that the request was accepted, the type field will be set to 1 to denote an out-of-band upload.

[sl_btmesh_fw_dist_client_prepare_oob_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-prepare-oob-upload) must have been called prior to using this command.

To poll the status of the OOB Upload, the application can either repeat this command, or use the command [sl_btmesh_fw_dist_client_get_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-get-upload).

When a [sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status) event with type set to 1 and progress set to 100 is received, the application can consider the upload complete.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_dist_client_upload_status](sl-btmesh-evt-fw-dist-client-upload-status)

##### sl_btmesh_fw_dist_client_suspend_upload

`sl_status_t sl_btmesh_fw_dist_client_suspend_upload(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Suspend an Upload's BLOB Transfer. An Upload that isn't yet in the BLOB Transfer phase, or which has failed, cannot be suspended. The suspension is entirely local; there is no message sent over the air. The remote receiver's BLOB Transfer Server will go to the suspended phase when the Upload Timeout timer expires. When the Upload is resumed, it will continue from where it previously left off.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_dist_client_resume_upload

`sl_status_t sl_btmesh_fw_dist_client_resume_upload(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Resume a suspended upload. The command [sl_btmesh_fw_dist_client_start_upload](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-start-upload) must be used after this command, and it may need to be repeated if the remote end does not respond. When the Upload is resumed, the BLOB Transfer will continue from where it previously left off.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_fw_dist_client_init_id 0x00590028`

`#define sl_btmesh_cmd_fw_dist_client_deinit_id 0x01590028`

`#define sl_btmesh_cmd_fw_dist_client_setup_id 0x02590028`

`#define sl_btmesh_cmd_fw_dist_client_setup_upload_id 0x03590028`

`#define sl_btmesh_cmd_fw_dist_client_set_upload_metadata_id 0x04590028`

`#define sl_btmesh_cmd_fw_dist_client_get_receivers_id 0x0e590028`

`#define sl_btmesh_cmd_fw_dist_client_get_id 0x0d590028`

`#define sl_btmesh_cmd_fw_dist_client_start_distribution_id 0x0f590028`

`#define sl_btmesh_cmd_fw_dist_client_cancel_distribution_id 0x10590028`

`#define sl_btmesh_cmd_fw_dist_client_apply_distribution_id 0x11590028`

`#define sl_btmesh_cmd_fw_dist_client_suspend_distribution_id 0x12590028`

`#define sl_btmesh_cmd_fw_dist_client_add_receivers_id 0x13590028`

`#define sl_btmesh_cmd_fw_dist_client_delete_all_receivers_id 0x14590028`

`#define sl_btmesh_cmd_fw_dist_client_get_capabilities_id 0x15590028`

`#define sl_btmesh_cmd_fw_dist_client_get_upload_id 0x16590028`

`#define sl_btmesh_cmd_fw_dist_client_start_upload_id 0x17590028`

`#define sl_btmesh_cmd_fw_dist_client_cancel_upload_id 0x19590028`

`#define sl_btmesh_cmd_fw_dist_client_get_fw_id 0x1a590028`

`#define sl_btmesh_cmd_fw_dist_client_get_fw_by_index_id 0x1b590028`

`#define sl_btmesh_cmd_fw_dist_client_delete_fw_id 0x1c590028`

`#define sl_btmesh_cmd_fw_dist_client_delete_all_fw_id 0x1d590028`

`#define sl_btmesh_cmd_fw_dist_client_prepare_oob_upload_id 0x1e590028`

`#define sl_btmesh_cmd_fw_dist_client_start_oob_upload_id 0x1f590028`

`#define sl_btmesh_cmd_fw_dist_client_suspend_upload_id 0x20590028`

`#define sl_btmesh_cmd_fw_dist_client_resume_upload_id 0x21590028`

`#define sl_btmesh_rsp_fw_dist_client_init_id 0x00590028`

`#define sl_btmesh_rsp_fw_dist_client_deinit_id 0x01590028`

`#define sl_btmesh_rsp_fw_dist_client_setup_id 0x02590028`

`#define sl_btmesh_rsp_fw_dist_client_setup_upload_id 0x03590028`

`#define sl_btmesh_rsp_fw_dist_client_set_upload_metadata_id 0x04590028`

`#define sl_btmesh_rsp_fw_dist_client_get_receivers_id 0x0e590028`

`#define sl_btmesh_rsp_fw_dist_client_get_id 0x0d590028`

`#define sl_btmesh_rsp_fw_dist_client_start_distribution_id 0x0f590028`

`#define sl_btmesh_rsp_fw_dist_client_cancel_distribution_id 0x10590028`

`#define sl_btmesh_rsp_fw_dist_client_apply_distribution_id 0x11590028`

`#define sl_btmesh_rsp_fw_dist_client_suspend_distribution_id 0x12590028`

`#define sl_btmesh_rsp_fw_dist_client_add_receivers_id 0x13590028`

`#define sl_btmesh_rsp_fw_dist_client_delete_all_receivers_id 0x14590028`

`#define sl_btmesh_rsp_fw_dist_client_get_capabilities_id 0x15590028`

`#define sl_btmesh_rsp_fw_dist_client_get_upload_id 0x16590028`

`#define sl_btmesh_rsp_fw_dist_client_start_upload_id 0x17590028`

`#define sl_btmesh_rsp_fw_dist_client_cancel_upload_id 0x19590028`

`#define sl_btmesh_rsp_fw_dist_client_get_fw_id 0x1a590028`

`#define sl_btmesh_rsp_fw_dist_client_get_fw_by_index_id 0x1b590028`

`#define sl_btmesh_rsp_fw_dist_client_delete_fw_id 0x1c590028`

`#define sl_btmesh_rsp_fw_dist_client_delete_all_fw_id 0x1d590028`

`#define sl_btmesh_rsp_fw_dist_client_prepare_oob_upload_id 0x1e590028`

`#define sl_btmesh_rsp_fw_dist_client_start_oob_upload_id 0x1f590028`

`#define sl_btmesh_rsp_fw_dist_client_suspend_upload_id 0x20590028`

`#define sl_btmesh_rsp_fw_dist_client_resume_upload_id 0x21590028`

#### sl_btmesh_evt_fw_dist_client_receivers_status

Firmware Distribution Nodes Status. 

##### Modules

[sl_btmesh_evt_fw_dist_client_receivers_status_s](sl-btmesh-evt-fw-dist-client-receivers-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_receivers_status_t

`typedef struct sl_btmesh_evt_fw_dist_client_receivers_status_s sl_btmesh_evt_fw_dist_client_receivers_status_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_receivers_status_id 0x035900a8`

**Description**: Identifier of the receivers_status event.

Data structure of the receivers_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_status_s::server_address
```

**Details:** Unicast address of the server

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_receivers_status_s::status
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code returned

###### nodes_list_size (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_status_s::nodes_list_size
```

**Details:** Number of entries currently in the node list

#### sl_btmesh_evt_fw_dist_client_receivers_list

Firmware Distribution Node List item. 

##### Modules

[sl_btmesh_evt_fw_dist_client_receivers_list_s](sl-btmesh-evt-fw-dist-client-receivers-list-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_receivers_list_t

`typedef struct sl_btmesh_evt_fw_dist_client_receivers_list_s sl_btmesh_evt_fw_dist_client_receivers_list_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_receivers_list_id 0x045900a8`

**Description**: Identifier of the receivers_list event.

Data structure of the receivers_list event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_s::server_address
```

**Details:** Unicast address of the server

###### index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_s::index
```

**Details:** Index of the entry reported

###### nodes_list_size (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_s::nodes_list_size
```

**Details:** Number of entries currently in the node list

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_s::address
```

**Details:** Address of the Update Server

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_receivers_list_s::phase
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Phase of the Update Server

###### update_status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_receivers_list_s::update_status
```

**Details:** Last Update Status message received from the Update Server

###### transfer_status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_receivers_list_s::transfer_status
```

**Details:** Last Transfer Status message received from the BLOB Transfer Server

###### progress (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_receivers_list_s::progress
```

**Details:** 0-100, percentage of BLOB Transfer octets delivered and confirmed

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_receivers_list_s::fw_index
```

**Details:** Index of the firmware being updated

#### sl_btmesh_evt_fw_dist_client_receivers_list_end

Firmware Distribution Node List end. 

##### Modules

[sl_btmesh_evt_fw_dist_client_receivers_list_end_s](sl-btmesh-evt-fw-dist-client-receivers-list-end-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_receivers_list_end_t

`typedef struct sl_btmesh_evt_fw_dist_client_receivers_list_end_s sl_btmesh_evt_fw_dist_client_receivers_list_end_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_receivers_list_end_id 0x055900a8`

**Description**: Identifier of the receivers_list_end event.

Data structure of the receivers_list_end event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_end_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_end_s::server_address
```

**Details:** Unicast address of the server

###### start_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_end_s::start_index
```

**Details:** Starting index

###### num_reported (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_end_s::num_reported
```

**Details:** Number of entries reported

###### nodes_list_size (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_receivers_list_end_s::nodes_list_size
```

**Details:** Number of entries currently in the node list

#### sl_btmesh_evt_fw_dist_client_capabilities_status

Firmware Distribution Capabilities Status. 

##### Modules

[sl_btmesh_evt_fw_dist_client_capabilities_status_s](sl-btmesh-evt-fw-dist-client-capabilities-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_capabilities_status_t

`typedef struct sl_btmesh_evt_fw_dist_client_capabilities_status_s sl_btmesh_evt_fw_dist_client_capabilities_status_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_capabilities_status_id 0x065900a8`

**Description**: Identifier of the capabilities_status event.

Data structure of the capabilities_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::server_address
```

**Details:** Unicast address of the server

###### max_nodes_list_size (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::max_nodes_list_size
```

**Details:** Maximum number of entries the node list can contain

###### max_fw_list_size (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::max_fw_list_size
```

**Details:** Maximum number of entries the Firmware List can contain

###### max_fw_size (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::max_fw_size
```

**Details:** Maximum size of a single firmware image

###### max_upload_space (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::max_upload_space
```

**Details:** Maximum number of bytes for firmware images

###### remaining_upload_space (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::remaining_upload_space
```

**Details:** Remaining number of bytes for firmware images

###### oob_supported (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_capabilities_status_s::oob_supported
```

**Details:** Enum [sl_btmesh_fw_dist_client_dist_oob_t](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-dist-oob-t). OOB firmware retrieval (using the Update URI received from an Update Server) supported

###### uri_scheme_names (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_client_capabilities_status_s::uri_scheme_names
```

**Details:** Supported URI scheme names. Empty if OOB is not supported.

#### sl_btmesh_evt_fw_dist_client_distribution_status

Firmware Distribution Status. 

##### Modules

[sl_btmesh_evt_fw_dist_client_distribution_status_s](sl-btmesh-evt-fw-dist-client-distribution-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_distribution_status_t

`typedef struct sl_btmesh_evt_fw_dist_client_distribution_status_s sl_btmesh_evt_fw_dist_client_distribution_status_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_distribution_status_id 0x075900a8`

**Description**: Identifier of the distribution_status event.

Data structure of the distribution_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_distribution_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_distribution_status_s::server_address
```

**Details:** Unicast address of the server

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_distribution_status_s::status
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code returned

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_distribution_status_s::phase
```

**Details:** Enum [sl_btmesh_fw_dist_client_dist_phase_t](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-dist-phase-t). Phase of the Distribution Server

###### group_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_distribution_status_s::group_address
```

**Details:** Distribution group address. Ignore if no distribution is active.

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_distribution_status_s::appkey_index
```

**Details:** Distribution app key index. Ignore if no distribution is active.

###### distributor_ttl (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_distribution_status_s::distributor_ttl
```

**Details:** TTL used by the Distributor. Ignore if no distribution is active.

###### timeout_base (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_distribution_status_s::timeout_base
```

**Details:** Timeout Base value used in BLOB Transfer

###### transfer_mode (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_distribution_status_s::transfer_mode
```

**Details:** Transfer Mode used in BLOB Transfer

###### apply_immediately (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_distribution_status_s::apply_immediately
```

**Details:** 1 if the Update Policy is Verify and Apply, otherwise 0. Ignore if no distribution is active.

###### fw_list_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_distribution_status_s::fw_list_index
```

**Details:** Index of the firmware in the Distributor's Firmware List

#### sl_btmesh_evt_fw_dist_client_upload_status

Firmware Distribution Upload Status. 

##### Modules

[sl_btmesh_evt_fw_dist_client_upload_status_s](sl-btmesh-evt-fw-dist-client-upload-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_upload_status_t

`typedef struct sl_btmesh_evt_fw_dist_client_upload_status_s sl_btmesh_evt_fw_dist_client_upload_status_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_upload_status_id 0x085900a8`

**Description**: Identifier of the upload_status event.

Data structure of the upload_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_upload_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_upload_status_s::server_address
```

**Details:** Unicast address of the server

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_status_s::status
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code returned

###### phase (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_status_s::phase
```

**Details:** Upload Phase of the Distribution Server

###### type (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_status_s::type
```

**Details:** Enum [sl_btmesh_fw_dist_client_dist_upload_type_t](sl-btmesh-fw-dist-client#sl-btmesh-fw-dist-client-dist-upload-type-t). Upload Type of an upload (0:in-band 1:out-of-band). Ignore if no upload is active.

###### progress (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_status_s::progress
```

**Details:** 0-100, percentage of BLOB Transfer octets or out-of-band data delivered and confirmed. Ignore if no upload is active.

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_client_upload_status_s::fwid
```

**Details:** FWID of the firmware being transferred. Empty if no upload is active.

#### sl_btmesh_evt_fw_dist_client_fw_status

Firmware Distribution Firmware Status. 

##### Modules

[sl_btmesh_evt_fw_dist_client_fw_status_s](sl-btmesh-evt-fw-dist-client-fw-status-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_fw_status_t

`typedef struct sl_btmesh_evt_fw_dist_client_fw_status_s sl_btmesh_evt_fw_dist_client_fw_status_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_fw_status_id 0x095900a8`

**Description**: Identifier of the fw_status event.

Data structure of the fw_status event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_fw_status_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_fw_status_s::server_address
```

**Details:** Unicast address of the server

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_fw_status_s::status
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_status_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-status-t). Status code returned

###### num_entries (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_fw_status_s::num_entries
```

**Details:** Number of images stored on the Distributor

###### index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_fw_status_s::index
```

**Details:** Index of the queried firmware on the server. 0xffff if not found.

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_client_fw_status_s::fwid
```

**Details:** FWID of the firmware that was queried. Empty if get_by_index was used and no such index exists.

#### sl_btmesh_evt_fw_dist_client_upload_complete

Firmware Distribution Upload procedure was completed successfully. 

##### Modules

[sl_btmesh_evt_fw_dist_client_upload_complete_s](sl-btmesh-evt-fw-dist-client-upload-complete-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_upload_complete_t

`typedef struct sl_btmesh_evt_fw_dist_client_upload_complete_s sl_btmesh_evt_fw_dist_client_upload_complete_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_upload_complete_id 0x0a5900a8`

**Description**: Identifier of the upload_complete event.

Data structure of the upload_complete event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_upload_complete_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_upload_complete_s::server_address
```

**Details:** Unicast address of the server

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_dist_client_upload_complete_s::blob_id
```

**Details:** The ID of the BLOB.

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_client_upload_complete_s::blob_size
```

**Details:** The size of the BLOB.

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_client_upload_complete_s::fwid
```

**Details:** FWID of the firmware that was uploaded.

#### sl_btmesh_evt_fw_dist_client_upload_failed

Firmware Distribution Upload procedure failed. 

##### Modules

[sl_btmesh_evt_fw_dist_client_upload_failed_s](sl-btmesh-evt-fw-dist-client-upload-failed-s)

##### Typedefs

###### sl_btmesh_evt_fw_dist_client_upload_failed_t

`typedef struct sl_btmesh_evt_fw_dist_client_upload_failed_s sl_btmesh_evt_fw_dist_client_upload_failed_t`

##### Macros

`#define sl_btmesh_evt_fw_dist_client_upload_failed_id 0x0b5900a8`

**Description**: Identifier of the upload_failed event.

Data structure of the upload_failed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_upload_failed_s::elem_index
```

**Details:** Client model element index

###### server_address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_dist_client_upload_failed_s::server_address
```

**Details:** Unicast address of the server

###### status_code (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_failed_s::status_code
```

**Details:** Reason for failure: BLOB Transfer status code, or 0xff for timeout, 0 if a DFU layer error happened (failure result in dist_status_code)

###### dist_status_code (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_failed_s::dist_status_code
```

**Details:** Reason for failure: Distribution status code, or 0xff for timeout, 0 if a MBT layer error happened (failure result in status_code)

###### progress (heading level 7)

```
uint8_t sl_btmesh_evt_fw_dist_client_upload_failed_s::progress
```

**Details:** 0-100, percentage of BLOB Transfer octets data delivered and confirmed.

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_fw_dist_client_upload_failed_s::blob_id
```

**Details:** The ID of the BLOB.

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_evt_fw_dist_client_upload_failed_s::blob_size
```

**Details:** The size of the BLOB.

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_fw_dist_client_upload_failed_s::fwid
```

**Details:** FWID of the firmware which uploading failed.

### Bluetooth Mesh Remote Provisioning Client Model

Bluetooth Mesh Remote Provisioning Client Model. 

Remote Provisioning Client model is used to provision devices which are not within one hop from the provisioner. 

#### Modules

[sl_btmesh_evt_remote_provisioning_client_scan_capabilities](sl-btmesh-evt-remote-provisioning-client-scan-capabilities)

[sl_btmesh_evt_remote_provisioning_client_scan_status](sl-btmesh-evt-remote-provisioning-client-scan-status)

[sl_btmesh_evt_remote_provisioning_client_scan_report](sl-btmesh-evt-remote-provisioning-client-scan-report)

[sl_btmesh_evt_remote_provisioning_client_extended_scan_report](sl-btmesh-evt-remote-provisioning-client-extended-scan-report)

[sl_btmesh_evt_remote_provisioning_client_link_status](sl-btmesh-evt-remote-provisioning-client-link-status)

[sl_btmesh_evt_remote_provisioning_client_link_report](sl-btmesh-evt-remote-provisioning-client-link-report)

#### Enumerations

##### sl_btmesh_remote_provisioning_client_link_state_t

```
enum sl_btmesh_remote_provisioning_client_link_state_t {
    sl_btmesh_remote_provisioning_client_link_state_idle = 0x0
    sl_btmesh_remote_provisioning_client_link_state_opening = 0x1
    sl_btmesh_remote_provisioning_client_link_state_active = 0x2
    sl_btmesh_remote_provisioning_client_link_state_outbound_packet_transfer = 0x3
    sl_btmesh_remote_provisioning_client_link_state_closing = 0x4
}
```

**Description:**

Possible remote provisioning link states.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_remote_provisioning_client_link_state_idle|(0x0) Idle state|
|sl_btmesh_remote_provisioning_client_link_state_opening|(0x1) Link Opening|
|sl_btmesh_remote_provisioning_client_link_state_active|(0x2) Link active|
|sl_btmesh_remote_provisioning_client_link_state_outbound_packet_transfer|(0x3) Outbound packet transfer|
|sl_btmesh_remote_provisioning_client_link_state_closing|(0x4) Link Closing|

##### sl_btmesh_remote_provisioning_client_nppi_operation_t

```
enum sl_btmesh_remote_provisioning_client_nppi_operation_t {
    sl_btmesh_remote_provisioning_client_nppi_device_key_update = 0x0
    sl_btmesh_remote_provisioning_client_nppi_address_update = 0x1
    sl_btmesh_remote_provisioning_client_nppi_dcd_update = 0x2
    sl_btmesh_remote_provisioning_client_remote_provisioning = 0xff
}
```

**Description:**

NPPI operation type.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_remote_provisioning_client_nppi_device_key_update|(0x0) Update Device Key|
|sl_btmesh_remote_provisioning_client_nppi_address_update|(0x1) Update device address. Note that also DCD will be updated if updated DCD is available|
|sl_btmesh_remote_provisioning_client_nppi_dcd_update|(0x2) Update device DCD|
|sl_btmesh_remote_provisioning_client_remote_provisioning|(0xff) Provision a remote device.|

#### Functions

##### sl_btmesh_remote_provisioning_client_init

`sl_status_t sl_btmesh_remote_provisioning_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the remote provisioning client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_remote_provisioning_client_get_scan_capabilities

`sl_status_t sl_btmesh_remote_provisioning_client_get_scan_capabilities(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|

Get the value of the Remote Provisioning Scan Capabilities state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_scan_capabilities](sl-btmesh-evt-remote-provisioning-client-scan-capabilities)

##### sl_btmesh_remote_provisioning_client_start_scan

`sl_status_t sl_btmesh_remote_provisioning_client_start_scan(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index, uint8_t item_limit, uint8_t timeout_sec, uint8_t single_scan, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address|
|uint16_t|[in]|elem_index|Client element index|
|uint8_t|[in]|item_limit|Maximum number of scanned items to be reported.|
|uint8_t|[in]|timeout_sec|Time limit for a scan (in seconds). Valid value range: [1 - 255].|
|uint8_t|[in]|single_scan|Whether to perform single UUID scan or multiple target scan.|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device to scan. Valid only for single UUID scan|

Start scanning for remote unprovisioned devices, within immediate radio range of the Remote Provisioning Server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_scan_status](sl-btmesh-evt-remote-provisioning-client-scan-status)
- [sl_btmesh_evt_remote_provisioning_client_scan_report](sl-btmesh-evt-remote-provisioning-client-scan-report)

##### sl_btmesh_remote_provisioning_client_get_scan_status

`sl_status_t sl_btmesh_remote_provisioning_client_get_scan_status(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|

Request scan status.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_scan_status](sl-btmesh-evt-remote-provisioning-client-scan-status)

##### sl_btmesh_remote_provisioning_client_stop_scan

`sl_status_t sl_btmesh_remote_provisioning_client_stop_scan(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|

Stop Remote Provisioning Scan procedure.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_scan_status](sl-btmesh-evt-remote-provisioning-client-scan-status)

##### sl_btmesh_remote_provisioning_client_start_extended_scan

`sl_status_t sl_btmesh_remote_provisioning_client_start_extended_scan(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index, uint8_t timeout_sec, uint8_t mode, uuid_128 uuid, size_t ad_types_len, const uint8_t *ad_types)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|
|uint8_t|[in]|timeout_sec|Time limit for a scan (in seconds). Used only if selected mode is 1 and then valid value range: [1 - 5].|
|uint8_t|[in]|mode|If 1 request additional information about a specific unprovisioned device. If 0 request additional information about the Remote Provisioning Server itself.|
|[uuid_128](uuid-128)|[in]|uuid|If mode is 1 identifies the Device UUID of the unprovisioned device for which additional information is requested.|
|size_t|[in]|ad_types_len|Length of data in `ad_types`|
|const uint8_t *|[in]|ad_types|list AD_types to be reported. List maximun size being 16. See [https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/](https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/).|

Request additional information about a specific unprovisioned device or about the Remote Provisioning Server itself.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_extended_scan_report](sl-btmesh-evt-remote-provisioning-client-extended-scan-report)

##### sl_btmesh_remote_provisioning_client_open_link

`sl_status_t sl_btmesh_remote_provisioning_client_open_link(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index, uint8_t timeout_sec, uint8_t dkri, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|
|uint8_t|[in]|timeout_sec|Time limit for a scan (in seconds).|
|uint8_t|[in]|dkri|Enum [sl_btmesh_remote_provisioning_client_nppi_operation_t](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-nppi-operation-t). Selection of Network Interface Operation or remote provisioning.|
|[uuid_128](uuid-128)|[in]|uuid|UUID of the device to provision. Valid if NPPI(dkri) procedure is not [sl_btmesh_remote_provisioning_client_remote_provisioning](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-remote-provisioning)|

Establish the provisioning bearer between a node supporting the Remote Provisioning Server model and an unprovisioned device, or to open the Node Provisioning Protocol Interface.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_link_status](sl-btmesh-evt-remote-provisioning-client-link-status)

##### sl_btmesh_remote_provisioning_client_get_link_status

`sl_status_t sl_btmesh_remote_provisioning_client_get_link_status(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|

Get the Remote Provisioning Link state of a Remote Provisioning Server model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_link_status](sl-btmesh-evt-remote-provisioning-client-link-status)

##### sl_btmesh_remote_provisioning_client_close_link

`sl_status_t sl_btmesh_remote_provisioning_client_close_link(uint16_t enc_netkey_index, uint16_t server, uint16_t elem_index, uint8_t reason)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server|Server address.|
|uint16_t|[in]|elem_index|Client element index|
|uint8_t|[in]|reason|0: success, 2:procedure failed, other not allowed.|

Close remote provisioning link.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_remote_provisioning_client_link_status](sl-btmesh-evt-remote-provisioning-client-link-status)

#### Macros

`#define sl_btmesh_cmd_remote_provisioning_client_init_id 0x00300028`

`#define sl_btmesh_cmd_remote_provisioning_client_get_scan_capabilities_id 0x01300028`

`#define sl_btmesh_cmd_remote_provisioning_client_start_scan_id 0x02300028`

`#define sl_btmesh_cmd_remote_provisioning_client_get_scan_status_id 0x03300028`

`#define sl_btmesh_cmd_remote_provisioning_client_stop_scan_id 0x04300028`

`#define sl_btmesh_cmd_remote_provisioning_client_start_extended_scan_id 0x05300028`

`#define sl_btmesh_cmd_remote_provisioning_client_open_link_id 0x06300028`

`#define sl_btmesh_cmd_remote_provisioning_client_get_link_status_id 0x07300028`

`#define sl_btmesh_cmd_remote_provisioning_client_close_link_id 0x08300028`

`#define sl_btmesh_rsp_remote_provisioning_client_init_id 0x00300028`

`#define sl_btmesh_rsp_remote_provisioning_client_get_scan_capabilities_id 0x01300028`

`#define sl_btmesh_rsp_remote_provisioning_client_start_scan_id 0x02300028`

`#define sl_btmesh_rsp_remote_provisioning_client_get_scan_status_id 0x03300028`

`#define sl_btmesh_rsp_remote_provisioning_client_stop_scan_id 0x04300028`

`#define sl_btmesh_rsp_remote_provisioning_client_start_extended_scan_id 0x05300028`

`#define sl_btmesh_rsp_remote_provisioning_client_open_link_id 0x06300028`

`#define sl_btmesh_rsp_remote_provisioning_client_get_link_status_id 0x07300028`

`#define sl_btmesh_rsp_remote_provisioning_client_close_link_id 0x08300028`

#### sl_btmesh_evt_remote_provisioning_client_scan_capabilities

Scan capabilities of the remote provisioning server. 

##### Modules

[sl_btmesh_evt_remote_provisioning_client_scan_capabilities_s](sl-btmesh-evt-remote-provisioning-client-scan-capabilities-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_client_scan_capabilities_t

`typedef struct sl_btmesh_evt_remote_provisioning_client_scan_capabilities_s sl_btmesh_evt_remote_provisioning_client_scan_capabilities_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_client_scan_capabilities_id 0x003000a8`

**Description**: Identifier of the scan_capabilities event.

Data structure of the scan_capabilities event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_scan_capabilities_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_scan_capabilities_s::server
```

**Details:** Server address.

###### max_items (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_scan_capabilities_s::max_items
```

**Details:** The maximum number of UUIDs that can be reported during scanning.

###### active (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_scan_capabilities_s::active
```

**Details:** Indication if active scan is supported.

#### sl_btmesh_evt_remote_provisioning_client_scan_status

The Remote Provisioning Scan Status. 

##### Modules

[sl_btmesh_evt_remote_provisioning_client_scan_status_s](sl-btmesh-evt-remote-provisioning-client-scan-status-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_client_scan_status_t

`typedef struct sl_btmesh_evt_remote_provisioning_client_scan_status_s sl_btmesh_evt_remote_provisioning_client_scan_status_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_client_scan_status_id 0x013000a8`

**Description**: Identifier of the scan_status event.

Data structure of the scan_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_scan_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_scan_status_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_scan_status_s::status
```

**Details:** Enum [sl_btmesh_remote_provisioning_server_status_t](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-status-t). server status.

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_scan_status_s::state
```

**Details:** Enum [sl_btmesh_remote_provisioning_server_scan_state_t](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-scan-state-t). Scan state.

###### max_reports (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_scan_status_s::max_reports
```

**Details:** Maximum number of scanned items to be reported.

###### timeout_sec (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_scan_status_s::timeout_sec
```

**Details:** Maximum available time for time left until the end of the Remote Provisioning Scan procedure.

#### sl_btmesh_evt_remote_provisioning_client_scan_report

The Remote Provisioning Scan Report. 

##### Modules

[sl_btmesh_evt_remote_provisioning_client_scan_report_s](sl-btmesh-evt-remote-provisioning-client-scan-report-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_client_scan_report_t

`typedef struct sl_btmesh_evt_remote_provisioning_client_scan_report_s sl_btmesh_evt_remote_provisioning_client_scan_report_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_client_scan_report_id 0x023000a8`

**Description**: Identifier of the scan_report event.

Data structure of the scan_report event. 

###### Public Attributes

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_scan_report_s::server
```

**Details:** Server address.

###### rssi (heading level 7)

```
int8_t sl_btmesh_evt_remote_provisioning_client_scan_report_s::rssi
```

**Details:** measured signal stength in dBm.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_remote_provisioning_client_scan_report_s::uuid
```

**Details:** UUID of the unprovisioned device found

###### oob (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_scan_report_s::oob
```

**Details:** OOB information.

###### uri (heading level 7)

```
uint32_t sl_btmesh_evt_remote_provisioning_client_scan_report_s::uri
```

**Details:** Hash of the out-of-band URI, which is received in [a separate event](#evt_mesh_prov_uri) . If the URI bit (bit 1) is not set in the OOB capabilities bitfield, this field is ignored.

#### sl_btmesh_evt_remote_provisioning_client_extended_scan_report

Remote Provisioning Server report of the advertising data requested by the client. 

##### Modules

[sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s](sl-btmesh-evt-remote-provisioning-client-extended-scan-report-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_client_extended_scan_report_t

`typedef struct sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s sl_btmesh_evt_remote_provisioning_client_extended_scan_report_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_client_extended_scan_report_id 0x033000a8`

**Description**: Identifier of the extended_scan_report event.

Data structure of the extended_scan_report event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s::status
```

**Details:** Enum [sl_btmesh_remote_provisioning_server_status_t](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-status-t). server status.

###### uuid (heading level 7)

```
uuid_128 sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s::uuid
```

**Details:** UUID of the unprovisioned device found

###### oob (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s::oob
```

**Details:** OOB information. 0 if not present

###### ad_structures (heading level 7)

```
uint8array sl_btmesh_evt_remote_provisioning_client_extended_scan_report_s::ad_structures
```

**Details:** Concatenated list of AD Structures that match the AD Types requested by the client.

#### sl_btmesh_evt_remote_provisioning_client_link_status

Remote Provisioning link Status. 

##### Modules

[sl_btmesh_evt_remote_provisioning_client_link_status_s](sl-btmesh-evt-remote-provisioning-client-link-status-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_client_link_status_t

`typedef struct sl_btmesh_evt_remote_provisioning_client_link_status_s sl_btmesh_evt_remote_provisioning_client_link_status_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_client_link_status_id 0x053000a8`

**Description**: Identifier of the link_status event.

Data structure of the link_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_link_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_link_status_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_link_status_s::status
```

**Details:** Enum [sl_btmesh_remote_provisioning_server_status_t](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-status-t). server status.

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_link_status_s::state
```

**Details:** Enum [sl_btmesh_remote_provisioning_client_link_state_t](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-link-state-t). link state.

#### sl_btmesh_evt_remote_provisioning_client_link_report

Remote Provisioning link report. 

Used by the Remote Provisioning Server to report the state change of a provisioning bearer link or the Node Provisioning Protocol Interface. 

##### Modules

[sl_btmesh_evt_remote_provisioning_client_link_report_s](sl-btmesh-evt-remote-provisioning-client-link-report-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_client_link_report_t

`typedef struct sl_btmesh_evt_remote_provisioning_client_link_report_s sl_btmesh_evt_remote_provisioning_client_link_report_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_client_link_report_id 0x063000a8`

**Description**: Identifier of the link_report event.

Data structure of the link_report event. 

###### Public Attributes

###### server (heading level 7)

```
uint16_t sl_btmesh_evt_remote_provisioning_client_link_report_s::server
```

**Details:** Server address.

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_link_report_s::status
```

**Details:** Enum [sl_btmesh_remote_provisioning_server_status_t](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-status-t). server status.

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_link_report_s::state
```

**Details:** Enum [sl_btmesh_remote_provisioning_client_link_state_t](sl-btmesh-remote-provisioning-client#sl-btmesh-remote-provisioning-client-link-state-t). link state.

###### reason (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_client_link_report_s::reason
```

**Details:** 0: success, 1: procedure timeout 2:procedure failed, 0xff not available.

### Bluetooth Mesh Remote Provisioning Server Model

Bluetooth Mesh Remote Provisioning Server Model. 

Remote Provisioning Server model provides tunneling of the provisioning commands for the provisioning process. 

#### Modules

[sl_btmesh_evt_remote_provisioning_server_link_open_request](sl-btmesh-evt-remote-provisioning-server-link-open-request)

[sl_btmesh_evt_remote_provisioning_server_link_close_request](sl-btmesh-evt-remote-provisioning-server-link-close-request)

#### Enumerations

##### sl_btmesh_remote_provisioning_server_scan_state_t

```
enum sl_btmesh_remote_provisioning_server_scan_state_t {
    sl_btmesh_remote_provisioning_server_idle = 0x0
    sl_btmesh_remote_provisioning_server_multiple = 0x1
    sl_btmesh_remote_provisioning_server_single = 0x2
}
```

**Description:**

Remote provisionin scan states.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_remote_provisioning_server_idle|(0x0) Idle state|
|sl_btmesh_remote_provisioning_server_multiple|(0x1) Multiple Devices Scan|
|sl_btmesh_remote_provisioning_server_single|(0x2) Single Device Scan|

##### sl_btmesh_remote_provisioning_server_status_t

```
enum sl_btmesh_remote_provisioning_server_status_t {
    sl_btmesh_remote_provisioning_server_success = 0x0
    sl_btmesh_remote_provisioning_server_scan_cannot_Start = 0x1
    sl_btmesh_remote_provisioning_server_invalid_state = 0x2
    sl_btmesh_remote_provisioning_server_limited_resources = 0x3
    sl_btmesh_remote_provisioning_server_link_cannot_open = 0x4
    sl_btmesh_remote_provisioning_server_link_open_failed = 0x5
    sl_btmesh_remote_provisioning_server_link_closed_by_device = 0x6
    sl_btmesh_remote_provisioning_server_link_closed_by_server = 0x7
    sl_btmesh_remote_provisioning_server_link_closed_by_client = 0x8
    sl_btmesh_remote_provisioning_server_link_closed_as_cannot_receive_pdu = 0x9
    sl_btmesh_remote_provisioning_server_link_closed_as_cannot_send_pdu = 0xa
    sl_btmesh_remote_provisioning_server_link_closed_as_cannot_deliver_pdu_report = 0xb
}
```

**Description:**

Remote provisionnin server status.

**Enumerator:**

|   |   |
|---|---|
|sl_btmesh_remote_provisioning_server_success|(0x0) Success|
|sl_btmesh_remote_provisioning_server_scan_cannot_Start|(0x1) Scanning Cannot Start|
|sl_btmesh_remote_provisioning_server_invalid_state|(0x2) Invalid State|
|sl_btmesh_remote_provisioning_server_limited_resources|(0x3) Limited Resources|
|sl_btmesh_remote_provisioning_server_link_cannot_open|(0x4) Link Cannot Open|
|sl_btmesh_remote_provisioning_server_link_open_failed|(0x5) Link open failed|
|sl_btmesh_remote_provisioning_server_link_closed_by_device|(0x6) Link Closed by Device|
|sl_btmesh_remote_provisioning_server_link_closed_by_server|(0x7) Link closed by server|
|sl_btmesh_remote_provisioning_server_link_closed_by_client|(0x8) Link closed by client|
|sl_btmesh_remote_provisioning_server_link_closed_as_cannot_receive_pdu|(0x9) Link closed as cannot receive PDU|
|sl_btmesh_remote_provisioning_server_link_closed_as_cannot_send_pdu|(0xa) Link closed as cannot send PDU|
|sl_btmesh_remote_provisioning_server_link_closed_as_cannot_deliver_pdu_report|(0xb) Link closed as cannot deliver PDU report|

#### Functions

##### sl_btmesh_remote_provisioning_server_init

`sl_status_t sl_btmesh_remote_provisioning_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the remote provisioning server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_remote_provisioning_server_open_link

`sl_status_t sl_btmesh_remote_provisioning_server_open_link(uint8_t connection)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|connection|Handle that was assigned to the connection|

This command is used to pass connction handle to the remote provisioning server after having received [sl_btmesh_evt_remote_provisioning_server_link_open_request](sl-btmesh-evt-remote-provisioning-server-link-open-request) event.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

##### sl_btmesh_remote_provisioning_server_set_default_bearer

`sl_status_t sl_btmesh_remote_provisioning_server_set_default_bearer(uint8_t bearer)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|bearer|Default bearer for provisioning.<br/><br/>- **1** PB-ADV<br/>- **2** PB-GATT|

Set default bearer to be used in remote provisioning.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

#### Macros

`#define sl_btmesh_cmd_remote_provisioning_server_init_id 0x00310028`

`#define sl_btmesh_cmd_remote_provisioning_server_open_link_id 0x01310028`

`#define sl_btmesh_cmd_remote_provisioning_server_set_default_bearer_id 0x02310028`

`#define sl_btmesh_rsp_remote_provisioning_server_init_id 0x00310028`

`#define sl_btmesh_rsp_remote_provisioning_server_open_link_id 0x01310028`

`#define sl_btmesh_rsp_remote_provisioning_server_set_default_bearer_id 0x02310028`

#### sl_btmesh_evt_remote_provisioning_server_link_open_request

This event indicates that server has received link-open request and stack needs an LE-Connection. 

This should be provided by the [sl_btmesh_remote_provisioning_server_open_link](sl-btmesh-remote-provisioning-server#sl-btmesh-remote-provisioning-server-open-link) command. 

##### Modules

[sl_btmesh_evt_remote_provisioning_server_link_open_request_s](sl-btmesh-evt-remote-provisioning-server-link-open-request-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_server_link_open_request_t

`typedef struct sl_btmesh_evt_remote_provisioning_server_link_open_request_s sl_btmesh_evt_remote_provisioning_server_link_open_request_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_server_link_open_request_id 0x003100a8`

**Description**: Identifier of the link_open_request event.

Data structure of the link_open_request event. 

###### Public Attributes

###### address (heading level 7)

```
bd_addr sl_btmesh_evt_remote_provisioning_server_link_open_request_s::address
```

**Details:** Address of the device to connect to

###### address_type (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_server_link_open_request_s::address_type
```

**Details:** Provisinee device address type. Values:

- **0:** Public address
- **1:** Random address

#### sl_btmesh_evt_remote_provisioning_server_link_close_request

Request to close LE-Connection. 

##### Modules

[sl_btmesh_evt_remote_provisioning_server_link_close_request_s](sl-btmesh-evt-remote-provisioning-server-link-close-request-s)

##### Typedefs

###### sl_btmesh_evt_remote_provisioning_server_link_close_request_t

`typedef struct sl_btmesh_evt_remote_provisioning_server_link_close_request_s sl_btmesh_evt_remote_provisioning_server_link_close_request_t`

##### Macros

`#define sl_btmesh_evt_remote_provisioning_server_link_close_request_id 0x013100a8`

**Description**: Identifier of the link_close_request event.

Data structure of the link_close_request event. 

###### Public Attributes

###### connection (heading level 7)

```
uint8_t sl_btmesh_evt_remote_provisioning_server_link_close_request_s::connection
```

**Details:** Handle that was assigned to the remote provisioning and can now be closed

### Bluetooth Mesh Standalone Updater

Bluetooth Mesh Standalone Updater. 

The Standalone Updater combines the functionality of a local Distribution Server and an external Distribution Client. It uses an Update Client and MBT Client model internally to distribute firmware images to Target Nodes.

The Standalone Updater is not a model per se. It achieves the same functionality as a Distribution Client controlling a Distribution Server via the local loopback interface, but without the ovearhead of any message handling. 

#### Modules

[sl_btmesh_evt_fw_standalone_updater_dist_state_changed](sl-btmesh-evt-fw-standalone-updater-dist-state-changed)

[sl_btmesh_evt_fw_standalone_updater_node_failed](sl-btmesh-evt-fw-standalone-updater-node-failed)

#### Functions

##### sl_btmesh_fw_standalone_updater_init

`sl_status_t sl_btmesh_fw_standalone_updater_init(uint16_t elem_index, uint16_t max_node_list_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Standalone Updater element index (that is, the element index of the Update Client and MBT Client)|
|uint16_t|[in]|max_node_list_size|Maximum number of nodes that can be updated simultaneously|

Initializes the Standalone Updater. Before initializing the Standalone Updater, the Update Client and MBT Client models on the same element must be initialized.

The Distribution Server is not supported on the same element at the same time.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_deinit

`sl_status_t sl_btmesh_fw_standalone_updater_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|

Deinitializes the Standalone Updater. The corresponding Update Client and MBT Client models can be deinitialized before or after this model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_setup

`sl_status_t sl_btmesh_fw_standalone_updater_setup(uint16_t elem_index, uint32_t fw_size, sl_bt_uuid_64_t blob_id, size_t fwid_len, const uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint32_t|[in]|fw_size|Firmware image size|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t)|[in]|blob_id|BLOB ID to use for the image|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the firmware image|

Set up parameters for a firmware distribution

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_set_metadata

`sl_status_t sl_btmesh_fw_standalone_updater_set_metadata(uint16_t elem_index, size_t metadata_len, const uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|size_t|[in]|metadata_len|Length of data in `metadata`|
|const uint8_t *|[in]|metadata|Metadata of the image. May be zero-length.|

Set the metadata of the image to be distributed. Should be called after the [sl_btmesh_fw_standalone_updater_setup](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-setup) command. Cannot be called after the distribution is started.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_set_multicast_threshold

`sl_status_t sl_btmesh_fw_standalone_updater_set_multicast_threshold(uint16_t elem_index, uint16_t multicast_threshold)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|multicast_threshold|This value will be passed to the MBT Client. If the number of servers for any step exceeds or is equal to this number, the group address will be used. Otherwise, servers will be looped through one by one. Value of 0 disables the feature.|

Set the multicast threshold value.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_add_receiver

`sl_status_t sl_btmesh_fw_standalone_updater_add_receiver(uint16_t elem_index, uint16_t address, uint8_t fw_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|address|Address of the Target Node|
|uint8_t|[in]|fw_index|Index of the firmware on the Target Node to update|

Add a receiver to the distribution

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_delete_all_receivers

`sl_status_t sl_btmesh_fw_standalone_updater_delete_all_receivers(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|

Clears the list of receivers

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_start

`sl_status_t sl_btmesh_fw_standalone_updater_start(uint16_t elem_index, uint16_t dist_appkey_index, uint8_t dist_ttl, uint16_t dist_timeout_base, uint8_t transfer_mode, uint16_t group_address, uuid_128 virtual_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|dist_appkey_index|Application key index to use when communicating with the Target Nodes|
|uint8_t|[in]|dist_ttl|The time-to-live value to use when communicating with the Target Nodes. Valid values: 0, range:[2-127] and 255.|
|uint16_t|[in]|dist_timeout_base|The Timeout Base value to use in the firmware image BLOB Transfer and Update Client operations|
|uint8_t|[in]|transfer_mode|1 = use Push Mode, 2 = use Pull Mode (typically for LPNs)|
|uint16_t|[in]|group_address|Group address to use. Zero to only use unicast.|
|[uuid_128](uuid-128)|[in]|virtual_address|If the group address is a VA hash, this needs to contain the full virtual address label UUID. Otherwise, the value of this field will be ignored.|

Start the firmware image distribution. The command [sl_btmesh_fw_standalone_updater_execute_distribution_step](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-execute-distribution-step) is used to progress through the procedures.

The Receivers List must have been populated via the [sl_btmesh_fw_standalone_updater_add_receiver](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-add-receiver) command. The distribution parameters must have been set via the [sl_btmesh_fw_standalone_updater_setup](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-setup) and [sl_btmesh_fw_standalone_updater_set_metadata](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-set-metadata) commands.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_fw_standalone_updater_dist_state_changed](sl-btmesh-evt-fw-standalone-updater-dist-state-changed)
- [sl_btmesh_evt_fw_standalone_updater_node_failed](sl-btmesh-evt-fw-standalone-updater-node-failed)

##### sl_btmesh_fw_standalone_updater_execute_distribution_step

`sl_status_t sl_btmesh_fw_standalone_updater_execute_distribution_step(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|

Execute the next action for the distribution state machine. Must be repeated by the application if the Target Nodes do not respond in a timely manner. Calling this function sends out the necessary messages to all nodes that have not responded. Note that the distribution step dist_step_transferring_image is executed via the MBT Client API, and thus the command does not need to be called in that state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_apply

`sl_status_t sl_btmesh_fw_standalone_updater_apply(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|

Enter the apply step after the distribution is in the "verification complete" step. The Standalone Updater can proceed to the apply step immediately after the verification is complete. This state transition exists only for keeping the API as similar as possible to the Distribution Server. The execute_distribution_step command must be called to send out the Update Apply messages.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_get_state

`sl_status_t sl_btmesh_fw_standalone_updater_get_state(uint16_t elem_index, uint8_t *state, uint16_t *total_nodes, uint16_t *num_active_nodes)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint8_t *|[out]|state|Current state of the distribution|
|uint16_t *|[out]|total_nodes|Number of nodes originally in the Receivers List|
|uint16_t *|[out]|num_active_nodes|Number of active nodes|

Get the current state of the distribution process. If an error is returned, the other return values should be ignored.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_get_node_status_by_index

`sl_status_t sl_btmesh_fw_standalone_updater_get_node_status_by_index(uint16_t elem_index, uint16_t entry_index, uint16_t *address, uint8_t *retrieved_phase, uint8_t *update_server_status, uint8_t *mbt_server_status, uint8_t *transfer_progress, uint8_t *fw_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|entry_index|Node entry index|
|uint16_t *|[out]|address|Address of the Update Server|
|uint8_t *|[out]|retrieved_phase|Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Phase of the Update Server|
|uint8_t *|[out]|update_server_status|Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Last Update Status message received from the Update Server|
|uint8_t *|[out]|mbt_server_status|Enum [sl_btmesh_mbt_server_status_t](sl-btmesh-mbt-server#sl-btmesh-mbt-server-status-t). Last Transfer Status message received from the BLOB Transfer Server|
|uint8_t *|[out]|transfer_progress|0-100, percentage of BLOB Transfer octets delivered and confirmed|
|uint8_t *|[out]|fw_index|Index of the firmware being updated|

Retrieve information about the ongoing update on a node

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_get_node_status_by_address

`sl_status_t sl_btmesh_fw_standalone_updater_get_node_status_by_address(uint16_t elem_index, uint16_t node_address, uint16_t *address, uint8_t *retrieved_phase, uint8_t *update_server_status, uint8_t *mbt_server_status, uint8_t *transfer_progress, uint8_t *fw_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|node_address|Node mesh address|
|uint16_t *|[out]|address|Address of the Update Server|
|uint8_t *|[out]|retrieved_phase|Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Phase of the Update Server|
|uint8_t *|[out]|update_server_status|Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Last Update Status message received from the Update Server|
|uint8_t *|[out]|mbt_server_status|Enum [sl_btmesh_mbt_server_status_t](sl-btmesh-mbt-server#sl-btmesh-mbt-server-status-t). Last Transfer Status message received from the BLOB Transfer Server|
|uint8_t *|[out]|transfer_progress|0-100, percentage of BLOB Transfer octets delivered and confirmed|
|uint8_t *|[out]|fw_index|Index of the firmware being updated|

Retrieve information about the ongoing update by a node address

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_cancel

`sl_status_t sl_btmesh_fw_standalone_updater_cancel(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|

Cancel a distribution process and clear any information about receivers. If the current distribution was not started, or it is completed or failed, a transition to the idle state will be made immediately. If the receivers need to be informed about the cancellation, a transition to the cancelling state will be made. The [sl_btmesh_fw_standalone_updater_execute_distribution_step](sl-btmesh-fw-standalone-updater#sl-btmesh-fw-standalone-updater-execute-distribution-step) function should be called to send out the cancellation messages to the receivers.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_fw_standalone_updater_configure_throttle

`sl_status_t sl_btmesh_fw_standalone_updater_configure_throttle(uint16_t elem_index, uint16_t throttle_delay_ms, uint8_t throttle_concurrent)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Element index|
|uint16_t|[in]|throttle_delay_ms|Controls the delay in milliseconds between batches of messages. Works in conjunction with `throttle_concurrent` to control message sending rate. When the first transmission in the current batch completes, the sender will wait for this delay before refilling the batch up to the `throttle_concurrent` limit with new transmissions.|
|uint8_t|[in]|throttle_concurrent|Defines how many messages are being sent concurrently. If set to 0, the maximum supported value is used.|

Configure the sender parameters for the Standalone Updater. This command is used to set the parameters that will be used when sending messages to the Target Nodes.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_fw_standalone_updater_init_id 0x005a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_deinit_id 0x015a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_setup_id 0x025a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_set_metadata_id 0x035a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_set_multicast_threshold_id 0x045a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_add_receiver_id 0x055a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_delete_all_receivers_id 0x065a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_start_id 0x075a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_execute_distribution_step_id 0x085a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_apply_id 0x095a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_get_state_id 0x0a5a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_get_node_status_by_index_id 0x0b5a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_get_node_status_by_address_id 0x0c5a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_cancel_id 0x0d5a0028`

`#define sl_btmesh_cmd_fw_standalone_updater_configure_throttle_id 0x0e5a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_init_id 0x005a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_deinit_id 0x015a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_setup_id 0x025a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_set_metadata_id 0x035a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_set_multicast_threshold_id 0x045a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_add_receiver_id 0x055a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_delete_all_receivers_id 0x065a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_start_id 0x075a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_execute_distribution_step_id 0x085a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_apply_id 0x095a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_get_state_id 0x0a5a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_get_node_status_by_index_id 0x0b5a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_get_node_status_by_address_id 0x0c5a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_cancel_id 0x0d5a0028`

`#define sl_btmesh_rsp_fw_standalone_updater_configure_throttle_id 0x0e5a0028`

#### sl_btmesh_evt_fw_standalone_updater_dist_state_changed

Distribution state changed. 

##### Modules

[sl_btmesh_evt_fw_standalone_updater_dist_state_changed_s](sl-btmesh-evt-fw-standalone-updater-dist-state-changed-s)

##### Typedefs

###### sl_btmesh_evt_fw_standalone_updater_dist_state_changed_t

`typedef struct sl_btmesh_evt_fw_standalone_updater_dist_state_changed_s sl_btmesh_evt_fw_standalone_updater_dist_state_changed_t`

##### Macros

`#define sl_btmesh_evt_fw_standalone_updater_dist_state_changed_id 0x005a00a8`

**Description**: Identifier of the dist_state_changed event.

Data structure of the dist_state_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_standalone_updater_dist_state_changed_s::elem_index
```

**Details:** Element index

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_fw_standalone_updater_dist_state_changed_s::state
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_step_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-step-t). New state of the Distribution

###### num_active_nodes (heading level 7)

```
uint16_t sl_btmesh_evt_fw_standalone_updater_dist_state_changed_s::num_active_nodes
```

**Details:** Number of active nodes

#### sl_btmesh_evt_fw_standalone_updater_node_failed

Indicates that an Target Node failed, either due to an error or due to timeout. 

##### Modules

[sl_btmesh_evt_fw_standalone_updater_node_failed_s](sl-btmesh-evt-fw-standalone-updater-node-failed-s)

##### Typedefs

###### sl_btmesh_evt_fw_standalone_updater_node_failed_t

`typedef struct sl_btmesh_evt_fw_standalone_updater_node_failed_s sl_btmesh_evt_fw_standalone_updater_node_failed_t`

##### Macros

`#define sl_btmesh_evt_fw_standalone_updater_node_failed_id 0x015a00a8`

**Description**: Identifier of the node_failed event.

Data structure of the node_failed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::elem_index
```

**Details:** Element index

###### address (heading level 7)

```
uint16_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::address
```

**Details:** Address of the Update Server

###### update_phase (heading level 7)

```
uint8_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::update_phase
```

**Details:** Enum [sl_btmesh_fw_dist_server_dist_node_phase_t](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-dist-node-phase-t). Update Phase of the Update Server. 0xa if not known yet.

###### update_status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::update_status
```

**Details:** Enum [sl_btmesh_fw_update_server_update_status_t](sl-btmesh-fw-update-server#sl-btmesh-fw-update-server-update-status-t). Last Update Status message received from the Update Server

###### mbt_status (heading level 7)

```
uint8_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::mbt_status
```

**Details:** Last status code received from the MBT Server. 0xa if not known yet.

###### progress (heading level 7)

```
uint8_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::progress
```

**Details:** 0-100, percentage of BLOB Transfer octets delivered and confirmed

###### fw_index (heading level 7)

```
uint8_t sl_btmesh_evt_fw_standalone_updater_node_failed_s::fw_index
```

**Details:** Index of the firmware being updated

### NCP firmware list cache

NCP firmware list cache. 

These commands can be used to manipulate the Firmware List cache.

This class is only intended for testing and development purposes with an NCP target. The Distributor SoC example application contains a proper implementation of the Firmware List.

The elem_index parameter in all of the commands and events is the element index of the Distribution Server. This class handles firmware deletion automatically as a response to [sl_btmesh_evt_fw_dist_server_fw_delete_req](sl-btmesh-evt-fw-dist-server-fw-delete-req) and [sl_btmesh_evt_fw_dist_server_fw_delete_all_req](sl-btmesh-evt-fw-dist-server-fw-delete-all-req). Thus, the [sl_btmesh_fw_dist_server_delete_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-delete-rsp) and [sl_btmesh_fw_dist_server_delete_all_rsp](sl-btmesh-fw-dist-server#sl-btmesh-fw-dist-server-delete-all-rsp) should not be called explicitly. This class handles adding firmware images automatically as a response to [sl_btmesh_evt_fw_dist_server_upload_complete](sl-btmesh-evt-fw-dist-server-upload-complete). Thus, when an upload completes, [sl_btmesh_ncp_fw_list_add_fw](sl-btmesh-ncp-fw-list#sl-btmesh-ncp-fw-list-add-fw) does not need to be called. 

#### Modules

[sl_btmesh_evt_ncp_fw_list_fw_deleted](sl-btmesh-evt-ncp-fw-list-fw-deleted)

[sl_btmesh_evt_ncp_fw_list_fw_all_deleted](sl-btmesh-evt-ncp-fw-list-fw-all-deleted)

[sl_btmesh_evt_ncp_fw_list_fw_added](sl-btmesh-evt-ncp-fw-list-fw-added)

#### Functions

##### sl_btmesh_ncp_fw_list_init

`sl_status_t sl_btmesh_ncp_fw_list_init(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution Server model element index|

Initializes the Firmware List. Before initializing the Firmware List, the Distribution Server model must have been initialized.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_ncp_fw_list_deinit

`sl_status_t sl_btmesh_ncp_fw_list_deinit(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution Server model element index|

Deinitializes the Firmware List.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_ncp_fw_list_get_fw_info_by_index

`sl_status_t sl_btmesh_ncp_fw_list_get_fw_info_by_index(uint16_t elem_index, uint16_t index, uint32_t *size, sl_bt_uuid_64_t *blob_id, size_t max_fwid_size, size_t *fwid_len, uint8_t *fwid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|index|Firmware list index to check|
|uint32_t *|[out]|size|Firmware image size|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t) *|[out]|blob_id|BLOB ID that will be used to transmit the image|
|size_t|[in]|max_fwid_size|Size of output buffer passed in `fwid`|
|size_t *|[out]|fwid_len|On return, set to the length of output data written to `fwid`|
|uint8_t *|[out]|fwid|Firmware ID of the image|

Retrieve information about a stored firmware in the Firmware List.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_ncp_fw_list_get_fw_metadata_by_index

`sl_status_t sl_btmesh_ncp_fw_list_get_fw_metadata_by_index(uint16_t elem_index, uint16_t index, size_t max_metadata_size, size_t *metadata_len, uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|index|Firmware list index to check|
|size_t|[in]|max_metadata_size|Size of output buffer passed in `metadata`|
|size_t *|[out]|metadata_len|On return, set to the length of output data written to `metadata`|
|uint8_t *|[out]|metadata|Metadata of firmware image|

Retrieve information about a stored firmware metadata in the Firmware List.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_ncp_fw_list_add_fw

`sl_status_t sl_btmesh_ncp_fw_list_add_fw(uint16_t elem_index, uint32_t size, sl_bt_uuid_64_t blob_id, size_t fwid_len, const uint8_t *fwid, uint16_t *fw_list_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint32_t|[in]|size|Size of the image|
|[sl_bt_uuid_64_t](sl-bt-uuid-64-t)|[in]|blob_id|BLOB ID that will be used to transmit the image|
|size_t|[in]|fwid_len|Length of data in `fwid`|
|const uint8_t *|[in]|fwid|Firmware ID of the image|
|uint16_t *|[out]|fw_list_index|Firmware List Index that was assigned to the image|

Add a firmware image to the Firmware List. This command is used to inform the stack that a image already exists on the local device. For example, it may have been stored via Upload previously, and the device has been reset.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_ncp_fw_list_set_fw_metadata

`sl_status_t sl_btmesh_ncp_fw_list_set_fw_metadata(uint16_t elem_index, uint16_t fw_list_index, size_t metadata_len, const uint8_t *metadata)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Server model element index|
|uint16_t|[in]|fw_list_index|Firmware List Index for which to set the metadata|
|size_t|[in]|metadata_len|Length of data in `metadata`|
|const uint8_t *|[in]|metadata|Metadata of the image. May be zero-length.|

Set the metadata of a image in the Firmware List. This command is used to set the metadata for images added with the add_fw command. NOTE: this should not be used to modify the metadata of images received via Upload!

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_ncp_fw_list_init_id 0x00610028`

`#define sl_btmesh_cmd_ncp_fw_list_deinit_id 0x01610028`

`#define sl_btmesh_cmd_ncp_fw_list_get_fw_info_by_index_id 0x02610028`

`#define sl_btmesh_cmd_ncp_fw_list_get_fw_metadata_by_index_id 0x03610028`

`#define sl_btmesh_cmd_ncp_fw_list_add_fw_id 0x04610028`

`#define sl_btmesh_cmd_ncp_fw_list_set_fw_metadata_id 0x05610028`

`#define sl_btmesh_rsp_ncp_fw_list_init_id 0x00610028`

`#define sl_btmesh_rsp_ncp_fw_list_deinit_id 0x01610028`

`#define sl_btmesh_rsp_ncp_fw_list_get_fw_info_by_index_id 0x02610028`

`#define sl_btmesh_rsp_ncp_fw_list_get_fw_metadata_by_index_id 0x03610028`

`#define sl_btmesh_rsp_ncp_fw_list_add_fw_id 0x04610028`

`#define sl_btmesh_rsp_ncp_fw_list_set_fw_metadata_id 0x05610028`

#### sl_btmesh_evt_ncp_fw_list_fw_deleted

An image was deleted via a message received by the Distribution Server. 

##### Modules

[sl_btmesh_evt_ncp_fw_list_fw_deleted_s](sl-btmesh-evt-ncp-fw-list-fw-deleted-s)

##### Typedefs

###### sl_btmesh_evt_ncp_fw_list_fw_deleted_t

`typedef struct sl_btmesh_evt_ncp_fw_list_fw_deleted_s sl_btmesh_evt_ncp_fw_list_fw_deleted_t`

##### Macros

`#define sl_btmesh_evt_ncp_fw_list_fw_deleted_id 0x086100a8`

**Description**: Identifier of the fw_deleted event.

Data structure of the fw_deleted event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_ncp_fw_list_fw_deleted_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_ncp_fw_list_fw_deleted_s::client_address
```

**Details:** Address of the Distribution Client

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_ncp_fw_list_fw_deleted_s::fwid
```

**Details:** FWID of the firmware that was deleted

#### sl_btmesh_evt_ncp_fw_list_fw_all_deleted

All images were deleted via a message received by the Distribution Server. 

##### Modules

[sl_btmesh_evt_ncp_fw_list_fw_all_deleted_s](sl-btmesh-evt-ncp-fw-list-fw-all-deleted-s)

##### Typedefs

###### sl_btmesh_evt_ncp_fw_list_fw_all_deleted_t

`typedef struct sl_btmesh_evt_ncp_fw_list_fw_all_deleted_s sl_btmesh_evt_ncp_fw_list_fw_all_deleted_t`

##### Macros

`#define sl_btmesh_evt_ncp_fw_list_fw_all_deleted_id 0x096100a8`

**Description**: Identifier of the fw_all_deleted event.

Data structure of the fw_all_deleted event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_ncp_fw_list_fw_all_deleted_s::elem_index
```

**Details:** Server model element index

###### client_address (heading level 7)

```
uint16_t sl_btmesh_evt_ncp_fw_list_fw_all_deleted_s::client_address
```

**Details:** Address of the Distribution Client

#### sl_btmesh_evt_ncp_fw_list_fw_added

A new image was added via the Distribution Server. 

##### Modules

[sl_btmesh_evt_ncp_fw_list_fw_added_s](sl-btmesh-evt-ncp-fw-list-fw-added-s)

##### Typedefs

###### sl_btmesh_evt_ncp_fw_list_fw_added_t

`typedef struct sl_btmesh_evt_ncp_fw_list_fw_added_s sl_btmesh_evt_ncp_fw_list_fw_added_t`

##### Macros

`#define sl_btmesh_evt_ncp_fw_list_fw_added_id 0x0a6100a8`

**Description**: Identifier of the fw_added event.

Data structure of the fw_added event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_evt_ncp_fw_list_fw_added_s::elem_index
```

**Details:** Server model element index

###### size (heading level 7)

```
uint32_t sl_btmesh_evt_ncp_fw_list_fw_added_s::size
```

**Details:** Size of the image

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_evt_ncp_fw_list_fw_added_s::blob_id
```

**Details:** BLOB ID that will be used to transmit the image

###### fwid (heading level 7)

```
uint8array sl_btmesh_evt_ncp_fw_list_fw_added_s::fwid
```

**Details:** Firmware ID of the image

### Bluetooth Mesh SAR Configuration Client Model

Bluetooth Mesh SAR Configuration Client Model. 

SAR Configuration Client model, used to configure the behavior of the lower transport layer of a node that that supports the SAR Configuration Server 

#### Modules

[sl_btmesh_evt_sar_config_client_sar_transmitter_status](sl-btmesh-evt-sar-config-client-sar-transmitter-status)

[sl_btmesh_evt_sar_config_client_sar_receiver_status](sl-btmesh-evt-sar-config-client-sar-receiver-status)

#### Functions

##### sl_btmesh_sar_config_client_init

`sl_status_t sl_btmesh_sar_config_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the SAR Configuration Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_client_deinit

`sl_status_t sl_btmesh_sar_config_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the SAR Configuration Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_client_get_sar_transmitter

`sl_status_t sl_btmesh_sar_config_client_get_sar_transmitter(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Query the SAR Transmitter state of a node

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sar_config_client_sar_transmitter_status](sl-btmesh-evt-sar-config-client-sar-transmitter-status)

##### sl_btmesh_sar_config_client_set_sar_transmitter

`sl_status_t sl_btmesh_sar_config_client_set_sar_transmitter(uint16_t enc_netkey_index, uint16_t server_address, uint8_t segment_interval_step, uint8_t unicast_retrans_count, uint8_t unicast_retrans_wo_progress_count, uint16_t unicast_retrans_interval_step, uint16_t unicast_retrans_interval_increment, uint8_t multicast_retrans_count, uint16_t multicast_retrans_interval_step, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|segment_interval_step|SAR Segment Interval Step<br/><br/>The Segment Interval Step controls the interval between transmissions of segments of a segmented message in milliseconds. The value is the range of 10ms to 160ms in 10ms steps, intermediate values are rounded down to the nearest multiple of 10. Default value is 20ms.|
|uint8_t|[in]|unicast_retrans_count|SAR Unicast Retransmissions Count<br/><br/>The SAR Unicast Retransmission Count controls the maximum number of transmissions of segments of segmented messages to a unicast destination. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 7, resulting in 8 transmissions total.|
|uint8_t|[in]|unicast_retrans_wo_progress_count|SAR Unicast Retransmissions Without Progress Count<br/><br/>The SAR Unicase Retransmissions Without Progress Count controls the maximum number of retransmissions of segments of segmented messages to a unicast destination without progress (without marking newly marking any segments acknowledged). Valid range is 0 - 15, where 0 represents a single transmission. The default value is 2, resulting in 3 transmissions. The value of this state should be set to a value greater by two or more than the value of the SAR Acknowledgement Retransmissions Count on a peer node. This helps prevent the SAR transmitter from abandoning the SAR prematurely.|
|uint16_t|[in]|unicast_retrans_interval_step|SAR Unicast Retransmissions Interval Step<br/><br/>The SAR Unicast Retransmissions Interval Step state controls the minimum interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 200ms.|
|uint16_t|[in]|unicast_retrans_interval_increment|SAR Unicast Retransmissions Interval Increment<br/><br/>The SAR Unicast Retransmissions Interval Increment state controls the incremental component of the interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 50ms.|
|uint8_t|[in]|multicast_retrans_count|SAR Multicast Retransmissions Count<br/><br/>The SAR Multicast Retransmissions Count state controls the maximum number of transmissions of segments of segmented messages to a group address or a virtual address. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 1, resulting in 2 transmissions.|
|uint16_t|[in]|multicast_retrans_interval_step|SAR Multicast Retransmissions Interval<br/><br/>The SAR Multicast Retransmissions Interval Step state controls the interval between retransmissions of segments of a segmented message for a destination that is a group address or a virtual address in 25ms steps. Valid range is 25-400ms, intermediate values are rounded down to the nearest multiple of 25. Default values is 100ms.|
|uint32_t *|[out]|handle|Request handle|

Set the SAR Tranmitter state of a node

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sar_config_client_sar_transmitter_status](sl-btmesh-evt-sar-config-client-sar-transmitter-status)

##### sl_btmesh_sar_config_client_get_sar_receiver

`sl_status_t sl_btmesh_sar_config_client_get_sar_receiver(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Query the SAR Receiver state of a node

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sar_config_client_sar_receiver_status](sl-btmesh-evt-sar-config-client-sar-receiver-status)

##### sl_btmesh_sar_config_client_set_sar_receiver

`sl_status_t sl_btmesh_sar_config_client_set_sar_receiver(uint16_t enc_netkey_index, uint16_t server_address, uint8_t segments_threshold, uint8_t ack_delay_increment, uint32_t discard_timeout, uint8_t segment_interval_step, uint8_t ack_retrans_count, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|segments_threshold|SAR Segments Threshold<br/><br/>The SAR Segments Threshold state represents the size of a segmented message in number of segments above which the Segment Acknowledgment messages are enabled. Valid range is 0 - 31, the default value is 3.|
|uint8_t|[in]|ack_delay_increment|SAR Acknowledgment Delay Increment<br/><br/>The SAR Acknowledgment Delay Increment state control the interval between the reception of a new segment of a segmented message for a destination that is a unicast address and the transmission of the Segment Acknowledgment for that message. Valid range is 0 - 7, default is 2.|
|uint32_t|[in]|discard_timeout|SAR Discard Timeout<br/><br/>The SAR Discard Timeout state controls the time that the lower transport layer waits after receiving unique segments of a segmented message before discarding that segmented message in 5s steps. Valid range is 5000 - 80000ms, intermediate values are rounded down to the nearest multiple of 5s. The default value is 10000ms.|
|uint8_t|[in]|segment_interval_step|SAR Discard Timeout<br/><br/>The SAR Discard Timeout state controls the time that the lower transport layer waits after receiving unique segments of a segmented message before discarding that segmented message in 5s steps. Valid range is 5000 - 80000ms, intermediate values are rounded down to the nearest multiple of 5s. The default value is 10000ms.|
|uint8_t|[in]|ack_retrans_count|SAR Acknowledgment Retransmissions Count<br/><br/>The SAR Acknowledgment Retransmissions Count state controls the maximum number of retransmissions of Segment Acknowledgment messages sent by the lower transport layer. Valid range is 0 - 3. The default value is 2, representing 2 retransmissions or 3 in total.|
|uint32_t *|[out]|handle|Request handle|

Set the SAR Receiver state of a node

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_sar_config_client_sar_receiver_status](sl-btmesh-evt-sar-config-client-sar-receiver-status)

#### Macros

`#define sl_btmesh_cmd_sar_config_client_init_id 0x01620028`

`#define sl_btmesh_cmd_sar_config_client_deinit_id 0x02620028`

`#define sl_btmesh_cmd_sar_config_client_get_sar_transmitter_id 0x03620028`

`#define sl_btmesh_cmd_sar_config_client_set_sar_transmitter_id 0x04620028`

`#define sl_btmesh_cmd_sar_config_client_get_sar_receiver_id 0x05620028`

`#define sl_btmesh_cmd_sar_config_client_set_sar_receiver_id 0x06620028`

`#define sl_btmesh_rsp_sar_config_client_init_id 0x01620028`

`#define sl_btmesh_rsp_sar_config_client_deinit_id 0x02620028`

`#define sl_btmesh_rsp_sar_config_client_get_sar_transmitter_id 0x03620028`

`#define sl_btmesh_rsp_sar_config_client_set_sar_transmitter_id 0x04620028`

`#define sl_btmesh_rsp_sar_config_client_get_sar_receiver_id 0x05620028`

`#define sl_btmesh_rsp_sar_config_client_set_sar_receiver_id 0x06620028`

#### sl_btmesh_evt_sar_config_client_sar_transmitter_status

SAR Transmitter state parameters, reply for a [sl_btmesh_sar_config_client_get_sar_transmitter](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-get-sar-transmitter) or [sl_btmesh_sar_config_client_set_sar_transmitter](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-set-sar-transmitter) command. 

##### Modules

[sl_btmesh_evt_sar_config_client_sar_transmitter_status_s](sl-btmesh-evt-sar-config-client-sar-transmitter-status-s)

##### Typedefs

###### sl_btmesh_evt_sar_config_client_sar_transmitter_status_t

`typedef struct sl_btmesh_evt_sar_config_client_sar_transmitter_status_s sl_btmesh_evt_sar_config_client_sar_transmitter_status_t`

##### Macros

`#define sl_btmesh_evt_sar_config_client_sar_transmitter_status_id 0x016200a8`

**Description**: Identifier of the sar_transmitter_status event.

Data structure of the sar_transmitter_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::handle
```

**Details:** Request handle

###### segment_interval_step (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::segment_interval_step
```

**Details:** SAR Segment Interval Step

The Segment Interval Step controls the interval between transmissions of segments of a segmented message in milliseconds. The value is the range of 10ms to 160ms in 10ms steps, intermediate values are rounded down to the nearest multiple of 10. Default value is 20ms.

###### unicast_retrans_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::unicast_retrans_count
```

**Details:** SAR Unicast Retransmissions Count

The SAR Unicast Retransmission Count controls the maximum number of transmissions of segments of segmented messages to a unicast destination. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 7, resulting in 8 transmissions.

###### unicast_retrans_wo_progress_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::unicast_retrans_wo_progress_count
```

**Details:** SAR Unicast Retransmissions Without Progress Count

The SAR Unicase Retransmissions Without Progress Count controls the maximum number of retransmissions of segments of segmented messages to a unicast destination without progress (without marking newly marking any segments acknowledged). Valid range is 0 - 15, where 0 represents a single transmission. The default value is 2, resulting in 3 transmissions. The value of this state should be set to a value greater by two or more than the value of the SAR Acknowledgement Retransmissions Count on a peer node. This helps prevent the SAR transmitter from abandoning the SAR prematurely.

###### unicast_retrans_interval_step (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::unicast_retrans_interval_step
```

**Details:** SAR Unicast Retransmissions Interval Step

The SAR Unicast Retransmissions Interval Step state controls the minimum interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 200ms.

###### unicast_retrans_interval_increment (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::unicast_retrans_interval_increment
```

**Details:** SAR Unicast Retransmissions Interval Increment

The SAR Unicast Retransmissions Interval Increment state controls the incremental component of the interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 50ms.

###### multicast_retrans_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::multicast_retrans_count
```

**Details:** SAR Multicast Retransmissions Count

The SAR Multicast Retransmissions Count state controls the maximum number of transmissions of segments of segmented messages to a group address or a virtual address. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 1, resulting in 2 transmissions.

###### multicast_retrans_interval_step (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_client_sar_transmitter_status_s::multicast_retrans_interval_step
```

**Details:** SAR Multicast Retransmissions Interval

The SAR Multicast Retransmissions Interval Step state controls the interval between retransmissions of segments of a segmented message for a destination that is a group address or a virtual address in 25ms steps. Valid range is 25-400ms, intermediate values are rounded down to the nearest multiple of 25. Default values is 100ms.

#### sl_btmesh_evt_sar_config_client_sar_receiver_status

SAR Reveiver state parameters, reply for a [sl_btmesh_sar_config_client_get_sar_receiver](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-get-sar-receiver) or [sl_btmesh_sar_config_client_set_sar_receiver](sl-btmesh-sar-config-client#sl-btmesh-sar-config-client-set-sar-receiver) command. 

##### Modules

[sl_btmesh_evt_sar_config_client_sar_receiver_status_s](sl-btmesh-evt-sar-config-client-sar-receiver-status-s)

##### Typedefs

###### sl_btmesh_evt_sar_config_client_sar_receiver_status_t

`typedef struct sl_btmesh_evt_sar_config_client_sar_receiver_status_s sl_btmesh_evt_sar_config_client_sar_receiver_status_t`

##### Macros

`#define sl_btmesh_evt_sar_config_client_sar_receiver_status_id 0x026200a8`

**Description**: Identifier of the sar_receiver_status event.

Data structure of the sar_receiver_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::handle
```

**Details:** Request handle

###### segments_threshold (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::segments_threshold
```

**Details:** SAR Segments Threshold

The SAR Segments Threshold state represents the size of a segmented message in number of segments above which the Segment Acknowledgment messages are enabled. Valid range is 0 - 31, the default value is 3.

###### ack_delay_increment (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::ack_delay_increment
```

**Details:** SAR Acknowledgment Delay Increment

The SAR Acknowledgment Delay Increment state control the interval between the reception of a new segment of a segmented message for a destination that is a unicast address and the transmission of the Segment Acknowledgment for that message. Valid range is 0 - 7, default is

1.

###### discard_timeout (heading level 7)

```
uint32_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::discard_timeout
```

**Details:** SAR Discard Timeout

The SAR Discard Timeout state controls the time that the lower transport layer waits after receiving unique segments of a segmented message before discarding that segmented message in 5s steps. Valid range is 5000 - 80000ms, intermediate values are rounded down to the nearest multiple of 5s. The default value is 10000s.

###### segment_interval_step (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::segment_interval_step
```

**Details:** SAR Receiver Segment Interval Step

The SAR Receiver Segment Interval Step state indicates the interval between received segments of a segmented message in milliseconds. This is used to control rate of transmission of Segment Acknowledgment messages. Valid range is 10 - 160, intermediate values are rounded down to the nearest multiple of 10. The default value is 20ms.

###### ack_retrans_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_client_sar_receiver_status_s::ack_retrans_count
```

**Details:** SAR Acknowledgment Retransmissions Count

The SAR Acknowledgment Retransmissions Count state controls the maximum number of retransmissions of Segment Acknowledgment messages sent by the lower transport layer. Valid range is 0 - 3. The default value is 2, representing 2 retransmissions or 3 in total.

### Bluetooth Mesh SAR Configuration Server Model

Bluetooth Mesh SAR Configuration Server Model. 

SAR Configuration Server, control the segmentation and reassembly behavior of the node 

#### Modules

[sl_btmesh_evt_sar_config_server_sar_transmitter_set](sl-btmesh-evt-sar-config-server-sar-transmitter-set)

[sl_btmesh_evt_sar_config_server_sar_receiver_set](sl-btmesh-evt-sar-config-server-sar-receiver-set)

#### Functions

##### sl_btmesh_sar_config_server_init

`sl_status_t sl_btmesh_sar_config_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the SAR Configuration Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_server_deinit

`sl_status_t sl_btmesh_sar_config_server_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialie the SAR Configuration Server

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_server_get_sar_transmitter

`sl_status_t sl_btmesh_sar_config_server_get_sar_transmitter(uint8_t *segment_interval_step, uint8_t *unicast_retrans_count, uint8_t *unicast_retrans_wo_progress_count, uint16_t *unicast_retrans_interval_step, uint16_t *unicast_retrans_interval_increment, uint8_t *multicast_retrans_count, uint16_t *multicast_retrans_interval_step)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|segment_interval_step|SAR Segment Interval Step in milliseconds|
|uint8_t *|[out]|unicast_retrans_count|SAR Unicast Retransmissions Count|
|uint8_t *|[out]|unicast_retrans_wo_progress_count|SAR Unicast Retransmissions Without Progress Count|
|uint16_t *|[out]|unicast_retrans_interval_step|SAR Unicast Retransmissions Interval Step in milliseconds|
|uint16_t *|[out]|unicast_retrans_interval_increment|SAR Unicast Retransmissions Interval Increment|
|uint8_t *|[out]|multicast_retrans_count|SAR Multicast Retransmissions Count|
|uint16_t *|[out]|multicast_retrans_interval_step|SAR Multicast Retransmissions Interval in milliseconds|

Query the local SAR Transmitter configuration

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_server_set_sar_transmitter

`sl_status_t sl_btmesh_sar_config_server_set_sar_transmitter(uint8_t segment_interval_step, uint8_t unicast_retrans_count, uint8_t unicast_retrans_wo_progress_count, uint16_t unicast_retrans_interval_step, uint16_t unicast_retrans_interval_increment, uint8_t multicast_retrans_count, uint16_t multicast_retrans_interval_step)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|segment_interval_step|SAR Segment Interval Step<br/><br/>The Segment Interval Step controls the interval between transmissions of segments of a segmented message in milliseconds. The value is the range of 10ms to 160ms in 10ms steps, intermediate values are rounded down to the nearest multiple of 10. Default value is 20ms.|
|uint8_t|[in]|unicast_retrans_count|SAR Unicast Retransmissions Count<br/><br/>The SAR Unicast Retransmission Count controls the maximum number of transmissions of segments of segmented messages to a unicast destination. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 7, resulting in 8 transmissions total.|
|uint8_t|[in]|unicast_retrans_wo_progress_count|SAR Unicast Retransmissions Without Progress Count<br/><br/>The SAR Unicase Retransmissions Without Progress Count controls the maximum number of retransmissions of segments of segmented messages to a unicast destination without progress (without marking newly marking any segments acknowledged). Valid range is 0 - 15, where 0 represents a single transmission. The default value is 2, resulting in 3 transmissions. The value of this state should be set to a value greater by two or more than the value of the SAR Acknowledgement Retransmissions Count on a peer node. This helps prevent the SAR transmitter from abandoning the SAR prematurely.|
|uint16_t|[in]|unicast_retrans_interval_step|SAR Unicast Retransmissions Interval Step<br/><br/>The SAR Unicast Retransmissions Interval Step state controls the minimum interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 200ms.|
|uint16_t|[in]|unicast_retrans_interval_increment|SAR Unicast Retransmissions Interval Increment<br/><br/>The SAR Unicast Retransmissions Interval Increment state controls the incremental component of the interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 50ms.|
|uint8_t|[in]|multicast_retrans_count|SAR Multicast Retransmissions Count<br/><br/>The SAR Multicast Retransmissions Count state controls the maximum number of transmissions of segments of segmented messages to a group address or a virtual address. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 1, resulting in 2 transmissions.|
|uint16_t|[in]|multicast_retrans_interval_step|SAR Multicast Retransmissions Interval<br/><br/>The SAR Multicast Retransmissions Interval Step state controls the interval between retransmissions of segments of a segmented message for a destination that is a group address or a virtual address in 25ms steps. Valid range is 25-400ms, intermediate values are rounded down to the nearest multiple of 25. Default values is 100ms.|

Set the local SAR Transmitter configuration

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_server_get_sar_receiver

`sl_status_t sl_btmesh_sar_config_server_get_sar_receiver(uint8_t *segments_threshold, uint8_t *ack_delay_increment, uint32_t *discard_timeout, uint8_t *segment_interval_step, uint8_t *ack_retrans_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|segments_threshold|SAR Segments Threshold<br/><br/>The SAR Segments Threshold state represents the size of a segmented message in number of segments above which the Segment Acknowledgment messages are enabled. Valid range is 0 - 31, the default value is 3.|
|uint8_t *|[out]|ack_delay_increment|SAR Acknowledgment Delay Increment<br/><br/>The SAR Acknowledgment Delay Increment state control the interval between the reception of a new segment of a segmented message for a destination that is a unicast address and the transmission of the Segment Acknowledgment for that message. Valid range is 0 - 7, default is 2.|
|uint32_t *|[out]|discard_timeout|SAR Discard Timeout<br/><br/>The SAR Discard Timeout state controls the time that the lower transport layer waits after receiving unique segments of a segmented message before discarding that segmented message in 5s steps. Valid range is 5000 - 80000ms, intermediate values are rounded down to the nearest multiple of 5s. The default value is 10000ms.|
|uint8_t *|[out]|segment_interval_step|SAR Receiver Segment Interval Step<br/><br/>The SAR Receiver Segment Interval Step state indicates the interval between received segments of a segmented message in milliseconds. This is used to control rate of transmission of Segment Acknowledgment messages. Valid range is 10 - 160, intermediate values are rounded down to the nearest multiple of 10. The default value is 20ms.|
|uint8_t *|[out]|ack_retrans_count|SAR Acknowledgment Retransmissions Count<br/><br/>The SAR Acknowledgment Retransmissions Count state controls the maximum number of retransmissions of Segment Acknowledgment messages sent by the lower transport layer. Valid range is 0 - 3. The default value is 2, representing 2 retransmissions or 3 in total.|

Query the local SAR Receiver configuration

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_sar_config_server_set_sar_receiver

`sl_status_t sl_btmesh_sar_config_server_set_sar_receiver(uint8_t segments_threshold, uint8_t ack_delay_increment, uint32_t discard_timeout, uint8_t segment_interval_step, uint8_t ack_retrans_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|segments_threshold|SAR Segments Threshold<br/><br/>The SAR Segments Threshold state represents the size of a segmented message in number of segments above which the Segment Acknowledgment messages are enabled. Valid range is 0 - 31, the default value is 3.|
|uint8_t|[in]|ack_delay_increment|SAR Acknowledgment Delay Increment<br/><br/>The SAR Acknowledgment Delay Increment state control the interval between the reception of a new segment of a segmented message for a destination that is a unicast address and the transmission of the Segment Acknowledgment for that message. Valid range is 0 - 7, default is 2.|
|uint32_t|[in]|discard_timeout|SAR Discard Timeout<br/><br/>The SAR Discard Timeout state controls the time that the lower transport layer waits after receiving unique segments of a segmented message before discarding that segmented message in 5s steps. Valid range is 5000 - 80000ms, intermediate values are rounded down to the nearest multiple of 5s. The default value is 10000ms (10s).|
|uint8_t|[in]|segment_interval_step|SAR Receiver Segment Interval Step<br/><br/>The SAR Receiver Segment Interval Step state indicates the interval between received segments of a segmented message in milliseconds. This is used to control rate of transmission of Segment Acknowledgment messages. Valid range is 10 - 160, intermediate values are rounded down to the nearest multiple of 10. The default value is 20ms.|
|uint8_t|[in]|ack_retrans_count|SAR Acknowledgment Retransmissions Count<br/><br/>The SAR Acknowledgment Retransmissions Count state controls the maximum number of retransmissions of Segment Acknowledgment messages sent by the lower transport layer. Valid range is 0 - 3. The default value is 2, representing 2 retransmissions or 3 in total.|

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_sar_config_server_init_id 0x01630028`

`#define sl_btmesh_cmd_sar_config_server_deinit_id 0x02630028`

`#define sl_btmesh_cmd_sar_config_server_get_sar_transmitter_id 0x03630028`

`#define sl_btmesh_cmd_sar_config_server_set_sar_transmitter_id 0x04630028`

`#define sl_btmesh_cmd_sar_config_server_get_sar_receiver_id 0x05630028`

`#define sl_btmesh_cmd_sar_config_server_set_sar_receiver_id 0x06630028`

`#define sl_btmesh_rsp_sar_config_server_init_id 0x01630028`

`#define sl_btmesh_rsp_sar_config_server_deinit_id 0x02630028`

`#define sl_btmesh_rsp_sar_config_server_get_sar_transmitter_id 0x03630028`

`#define sl_btmesh_rsp_sar_config_server_set_sar_transmitter_id 0x04630028`

`#define sl_btmesh_rsp_sar_config_server_get_sar_receiver_id 0x05630028`

`#define sl_btmesh_rsp_sar_config_server_set_sar_receiver_id 0x06630028`

#### sl_btmesh_evt_sar_config_server_sar_transmitter_set

Diagnostic event to report SAR Transmitter state changes. 

##### Modules

[sl_btmesh_evt_sar_config_server_sar_transmitter_set_s](sl-btmesh-evt-sar-config-server-sar-transmitter-set-s)

##### Typedefs

###### sl_btmesh_evt_sar_config_server_sar_transmitter_set_t

`typedef struct sl_btmesh_evt_sar_config_server_sar_transmitter_set_s sl_btmesh_evt_sar_config_server_sar_transmitter_set_t`

##### Macros

`#define sl_btmesh_evt_sar_config_server_sar_transmitter_set_id 0x016300a8`

**Description**: Identifier of the sar_transmitter_set event.

Data structure of the sar_transmitter_set event. 

###### Public Attributes

###### segment_interval_step (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::segment_interval_step
```

**Details:** SAR Segment Interval Step

The Segment Interval Step controls the interval between transmissions of segments of a segmented message in milliseconds. The value is the range of 10ms to 160ms in 10ms steps, intermediate values are rounded down to the nearest multiple of 10. Default value is 20ms.

###### unicast_retrans_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::unicast_retrans_count
```

**Details:** SAR Unicast Retransmissions Count

The SAR Unicast Retransmission Count controls the maximum number of transmissions of segments of segmented messages to a unicast destination. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 7, resulting in 8 transmissions total.

###### unicast_retrans_wo_progress_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::unicast_retrans_wo_progress_count
```

**Details:** SAR Unicast Retransmissions Without Progress Count

The SAR Unicase Retransmissions Without Progress Count controls the maximum number of retransmissions of segments of segmented messages to a unicast destination without progress (without marking newly marking any segments acknowledged). Valid range is 0 - 15, where 0 represents a single transmission. The default value is 2, resulting in 3 transmissions. The value of this state should be set to a value greater by two or more than the value of the SAR Acknowledgement Retransmissions Count on a peer node. This helps prevent the SAR transmitter from abandoning the SAR prematurely.

###### unicast_retrans_interval_step (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::unicast_retrans_interval_step
```

**Details:** SAR Unicast Retransmissions Interval Step

The SAR Unicast Retransmissions Interval Step state controls the minimum interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 200ms.

###### unicast_retrans_interval_increment (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::unicast_retrans_interval_increment
```

**Details:** SAR Unicast Retransmissions Interval Increment

The SAR Unicast Retransmissions Interval Increment state controls the incremental component of the interval between retransmissions of segments of a segmented message for a destination that is a unicast address in 25ms steps. Valid range is 25 - 400ms, intermediate values are rounded down to the nearest multiple of 25. Default value is 50ms.

###### multicast_retrans_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::multicast_retrans_count
```

**Details:** SAR Multicast Retransmissions Count

The SAR Multicast Retransmissions Count state controls the maximum number of transmissions of segments of segmented messages to a group address or a virtual address. Valid range is 0 - 15, where 0 represents a single transmission. The default value is 1, resulting in 2 transmissions.

###### multicast_retrans_interval_step (heading level 7)

```
uint16_t sl_btmesh_evt_sar_config_server_sar_transmitter_set_s::multicast_retrans_interval_step
```

**Details:** SAR Multicast Retransmissions Interval

The SAR Multicast Retransmissions Interval Step state controls the interval between retransmissions of segments of a segmented message for a destination that is a group address or a virtual address in 25ms steps. Valid range is 25-400ms, intermediate values are rounded down to the nearest multiple of 25. Default values is 100ms.

#### sl_btmesh_evt_sar_config_server_sar_receiver_set

Diagnostic event to report SAR Receiver state changes. 

##### Modules

[sl_btmesh_evt_sar_config_server_sar_receiver_set_s](sl-btmesh-evt-sar-config-server-sar-receiver-set-s)

##### Typedefs

###### sl_btmesh_evt_sar_config_server_sar_receiver_set_t

`typedef struct sl_btmesh_evt_sar_config_server_sar_receiver_set_s sl_btmesh_evt_sar_config_server_sar_receiver_set_t`

##### Macros

`#define sl_btmesh_evt_sar_config_server_sar_receiver_set_id 0x026300a8`

**Description**: Identifier of the sar_receiver_set event.

Data structure of the sar_receiver_set event. 

###### Public Attributes

###### segments_threshold (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_receiver_set_s::segments_threshold
```

**Details:** SAR Segments Threshold

The SAR Segments Threshold state represents the size of a segmented message in number of segments above which the Segment Acknowledgment messages are enabled. Valid range is 0 - 31, the default value is 3.

###### ack_delay_increment (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_receiver_set_s::ack_delay_increment
```

**Details:** SAR Acknowledgment Delay Increment

The SAR Acknowledgment Delay Increment state control the interval between the reception of a new segment of a segmented message for a destination that is a unicast address and the transmission of the Segment Acknowledgment for that message. Valid range is 0 - 7, default is

1.

###### discard_timeout (heading level 7)

```
uint32_t sl_btmesh_evt_sar_config_server_sar_receiver_set_s::discard_timeout
```

**Details:** SAR Discard Timeout

The SAR Discard Timeout state controls the time that the lower transport layer waits after receiving unique segments of a segmented message before discarding that segmented message in 5s steps. Valid range is 5000 - 80000ms, intermediate values are rounded down to the nearest multiple of 5s. The default value is 10000ms.

###### segment_interval_step (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_receiver_set_s::segment_interval_step
```

**Details:** SAR Receiver Segment Interval Step

The SAR Receiver Segment Interval Step state indicates the interval between received segments of a segmented message in milliseconds. This is used to control rate of transmission of Segment Acknowledgment messages. Valid range is 10 - 160, intermediate values are rounded down to the nearest multiple of 10. The default value is 20ms.

###### ack_retrans_count (heading level 7)

```
uint8_t sl_btmesh_evt_sar_config_server_sar_receiver_set_s::ack_retrans_count
```

**Details:** SAR Acknowledgment Retransmissions Count

The SAR Acknowledgment Retransmissions Count state controls the maximum number of retransmissions of Segment Acknowledgment messages sent by the lower transport layer. Valid range is 0 - 3. The default value is 2, representing 2 retransmissions or 3 in total.

### Bluetooth Mesh Private Beacon Client Model

Bluetooth Mesh Private Beacon Client Model. 

This class provides the commands and messages to interface with the Private Beacon Client Model. 

#### Modules

[sl_btmesh_evt_private_beacon_client_beacon_status](sl-btmesh-evt-private-beacon-client-beacon-status)

[sl_btmesh_evt_private_beacon_client_gatt_proxy_status](sl-btmesh-evt-private-beacon-client-gatt-proxy-status)

[sl_btmesh_evt_private_beacon_client_identity_status](sl-btmesh-evt-private-beacon-client-identity-status)

#### Functions

##### sl_btmesh_private_beacon_client_init

`sl_status_t sl_btmesh_private_beacon_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the private beacon client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_private_beacon_client_deinit

`sl_status_t sl_btmesh_private_beacon_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the private beacon client.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_private_beacon_client_get_beacon

`sl_status_t sl_btmesh_private_beacon_client_get_beacon(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle.|

Get the node's private network beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_private_beacon_client_beacon_status](sl-btmesh-evt-private-beacon-client-beacon-status)

##### sl_btmesh_private_beacon_client_set_beacon

`sl_status_t sl_btmesh_private_beacon_client_set_beacon(uint16_t enc_netkey_index, uint16_t server_address, uint8_t state, uint16_t random_update_steps, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|state|Secure network beacon value to set. Valid values are:<br/><br/>- 0: Node is not broadcasting private network beacons<br/>- 1: Node is broadcasting private network beacons|
|uint16_t|[in]|random_update_steps|Number of beacons that are to be sent before changing the random of obfuscation. Valid step values are from 0x00 to 0xff. 0x00 means that the random is updated for every beacon send. and 0x01-0xff tells how often random is updated in multiples of 10 seconds. Update of random will also trigger update of random address used in sending. Value 0x100 is used to indicate that no change in this parameter is desired.|
|uint32_t *|[out]|handle|Request handle|

Set node private network beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_private_beacon_client_beacon_status](sl-btmesh-evt-private-beacon-client-beacon-status)

##### sl_btmesh_private_beacon_client_get_gatt_proxy

`sl_status_t sl_btmesh_private_beacon_client_get_gatt_proxy(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle.|

Get the node's private gatt proxy beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_private_beacon_client_gatt_proxy_status](sl-btmesh-evt-private-beacon-client-gatt-proxy-status)

##### sl_btmesh_private_beacon_client_set_gatt_proxy

`sl_status_t sl_btmesh_private_beacon_client_set_gatt_proxy(uint16_t enc_netkey_index, uint16_t server_address, uint8_t state, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|state|Secure network beacon value to set. Valid values are:<br/><br/>- 0: Node is not broadcasting private gatt proxy beacons<br/>- 1: Node is broadcasting private gatt proxy beacons|
|uint32_t *|[out]|handle|Request handle|

Set the node's private gatt proxy beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_private_beacon_client_gatt_proxy_status](sl-btmesh-evt-private-beacon-client-gatt-proxy-status)

##### sl_btmesh_private_beacon_client_get_identity

`sl_status_t sl_btmesh_private_beacon_client_get_identity(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Network key index for which the state is queried|
|uint32_t *|[out]|handle|Request handle.|

Get the node's private identity beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_private_beacon_client_identity_status](sl-btmesh-evt-private-beacon-client-identity-status)

##### sl_btmesh_private_beacon_client_set_identity

`sl_status_t sl_btmesh_private_beacon_client_set_identity(uint16_t enc_netkey_index, uint16_t server_address, uint16_t netkey_index, uint8_t state, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint16_t|[in]|netkey_index|Network key index for which the state is configured|
|uint8_t|[in]|state|Node private beacon value to set. Valid values are:<br/><br/>- 0: Node is not broadcasting private identity beacons<br/>- 1: Node is broadcasting private identity beacons|
|uint32_t *|[out]|handle|Request handle|

Set the node's private node identity beacon state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_private_beacon_client_identity_status](sl-btmesh-evt-private-beacon-client-identity-status)

#### Macros

`#define sl_btmesh_cmd_private_beacon_client_init_id 0x01640028`

`#define sl_btmesh_cmd_private_beacon_client_deinit_id 0x02640028`

`#define sl_btmesh_cmd_private_beacon_client_get_beacon_id 0x03640028`

`#define sl_btmesh_cmd_private_beacon_client_set_beacon_id 0x04640028`

`#define sl_btmesh_cmd_private_beacon_client_get_gatt_proxy_id 0x05640028`

`#define sl_btmesh_cmd_private_beacon_client_set_gatt_proxy_id 0x06640028`

`#define sl_btmesh_cmd_private_beacon_client_get_identity_id 0x07640028`

`#define sl_btmesh_cmd_private_beacon_client_set_identity_id 0x08640028`

`#define sl_btmesh_rsp_private_beacon_client_init_id 0x01640028`

`#define sl_btmesh_rsp_private_beacon_client_deinit_id 0x02640028`

`#define sl_btmesh_rsp_private_beacon_client_get_beacon_id 0x03640028`

`#define sl_btmesh_rsp_private_beacon_client_set_beacon_id 0x04640028`

`#define sl_btmesh_rsp_private_beacon_client_get_gatt_proxy_id 0x05640028`

`#define sl_btmesh_rsp_private_beacon_client_set_gatt_proxy_id 0x06640028`

`#define sl_btmesh_rsp_private_beacon_client_get_identity_id 0x07640028`

`#define sl_btmesh_rsp_private_beacon_client_set_identity_id 0x08640028`

#### sl_btmesh_evt_private_beacon_client_beacon_status

Status event for [sl_btmesh_private_beacon_client_get_beacon](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-get-beacon) and [sl_btmesh_private_beacon_client_set_beacon](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-beacon) commands. 

##### Modules

[sl_btmesh_evt_private_beacon_client_beacon_status_s](sl-btmesh-evt-private-beacon-client-beacon-status-s)

##### Typedefs

###### sl_btmesh_evt_private_beacon_client_beacon_status_t

`typedef struct sl_btmesh_evt_private_beacon_client_beacon_status_s sl_btmesh_evt_private_beacon_client_beacon_status_t`

##### Macros

`#define sl_btmesh_evt_private_beacon_client_beacon_status_id 0x016400a8`

**Description**: Identifier of the beacon_status event.

Data structure of the beacon_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_private_beacon_client_beacon_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_private_beacon_client_beacon_status_s::handle
```

**Details:** Request handle

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_private_beacon_client_beacon_status_s::state
```

**Details:** Private network beacon state of the node. Valid values are:

- 0: Node is not broadcasting secure network beacons
- 1: Node is broadcasting secure network beacons

###### random_update_steps (heading level 7)

```
uint8_t sl_btmesh_evt_private_beacon_client_beacon_status_s::random_update_steps
```

**Details:** Number of beacons that are to be sent before changing the random of obfuscation. Valid step values are from 0x00 to 0xff. 0x00 means that random is updated for every beacon send and 0x01-0xff tells in multiples of 10 seconds how often random is updated.

#### sl_btmesh_evt_private_beacon_client_gatt_proxy_status

Status event for [sl_btmesh_private_beacon_client_get_gatt_proxy](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-get-gatt-proxy) and [sl_btmesh_private_beacon_client_set_gatt_proxy](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-gatt-proxy) commands. 

##### Modules

[sl_btmesh_evt_private_beacon_client_gatt_proxy_status_s](sl-btmesh-evt-private-beacon-client-gatt-proxy-status-s)

##### Typedefs

###### sl_btmesh_evt_private_beacon_client_gatt_proxy_status_t

`typedef struct sl_btmesh_evt_private_beacon_client_gatt_proxy_status_s sl_btmesh_evt_private_beacon_client_gatt_proxy_status_t`

##### Macros

`#define sl_btmesh_evt_private_beacon_client_gatt_proxy_status_id 0x026400a8`

**Description**: Identifier of the gatt_proxy_status event.

Data structure of the gatt_proxy_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_private_beacon_client_gatt_proxy_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_private_beacon_client_gatt_proxy_status_s::handle
```

**Details:** Request handle

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_private_beacon_client_gatt_proxy_status_s::state
```

**Details:** Private gatt proxy beacon state of the node. Valid values are:

- 0: Node is not broadcasting private gatt proxy beacons
- 1: Node is broadcasting private gatt proxy beacons

#### sl_btmesh_evt_private_beacon_client_identity_status

Status event for [sl_btmesh_private_beacon_client_get_identity](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-get-identity) and [sl_btmesh_private_beacon_client_set_identity](sl-btmesh-private-beacon-client#sl-btmesh-private-beacon-client-set-identity) commands. 

##### Modules

[sl_btmesh_evt_private_beacon_client_identity_status_s](sl-btmesh-evt-private-beacon-client-identity-status-s)

##### Typedefs

###### sl_btmesh_evt_private_beacon_client_identity_status_t

`typedef struct sl_btmesh_evt_private_beacon_client_identity_status_s sl_btmesh_evt_private_beacon_client_identity_status_t`

##### Macros

`#define sl_btmesh_evt_private_beacon_client_identity_status_id 0x036400a8`

**Description**: Identifier of the identity_status event.

Data structure of the identity_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_private_beacon_client_identity_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_private_beacon_client_identity_status_s::handle
```

**Details:** Request handle

###### status (heading level 7)

```
uint8_t sl_btmesh_evt_private_beacon_client_identity_status_s::status
```

**Details:** Foundation status of last request

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_private_beacon_client_identity_status_s::netkey_index
```

**Details:** Network key index for which the state is configured

###### state (heading level 7)

```
uint8_t sl_btmesh_evt_private_beacon_client_identity_status_s::state
```

**Details:** Private identity beacon state of the node. Valid values are:

- 0: Node is not broadcasting private identity beacons
- 1: Node is broadcasting private identity beacons

### Bluetooth Mesh Large Composition Data Client Model

Bluetooth Mesh Large Composition Data Client Model. 

This class provides the commands and messages to interface with the Large Composition Data Client model. 

#### Modules

[sl_btmesh_evt_lcd_client_data_header](sl-btmesh-evt-lcd-client-data-header)

[sl_btmesh_evt_lcd_client_data](sl-btmesh-evt-lcd-client-data)

[sl_btmesh_evt_lcd_client_data_end](sl-btmesh-evt-lcd-client-data-end)

#### Functions

##### sl_btmesh_lcd_client_init

`sl_status_t sl_btmesh_lcd_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the Large Composition Data Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lcd_client_deinit

`sl_status_t sl_btmesh_lcd_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the Large Composition Data Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_lcd_client_get_composition_data

`sl_status_t sl_btmesh_lcd_client_get_composition_data(uint16_t enc_netkey_index, uint16_t server_address, uint8_t page_number, uint16_t offset, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key index used to encrypt the request|
|uint16_t|[in]|server_address|Destination server model address|
|uint8_t|[in]|page_number|Page number of the Composition Data|
|uint16_t|[in]|offset|Offset within the page|
|uint32_t *|[out]|handle|Request handle|

Send a Large Composition Data Get to a LCD Server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lcd_client_data_header](sl-btmesh-evt-lcd-client-data-header)
- [sl_btmesh_evt_lcd_client_data](sl-btmesh-evt-lcd-client-data)
- [sl_btmesh_evt_lcd_client_data_end](sl-btmesh-evt-lcd-client-data-end)

##### sl_btmesh_lcd_client_get_metadata

`sl_status_t sl_btmesh_lcd_client_get_metadata(uint16_t enc_netkey_index, uint16_t server_address, uint8_t page_number, uint16_t offset, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key index used to encrypt the request|
|uint16_t|[in]|server_address|Destination server model address|
|uint8_t|[in]|page_number|Page number of the Composition Data|
|uint16_t|[in]|offset|Offset within the page|
|uint32_t *|[out]|handle|Request handle|

Send a Metadata request to a LCD Server.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_lcd_client_data_header](sl-btmesh-evt-lcd-client-data-header)
- [sl_btmesh_evt_lcd_client_data](sl-btmesh-evt-lcd-client-data)
- [sl_btmesh_evt_lcd_client_data_end](sl-btmesh-evt-lcd-client-data-end)

#### Macros

`#define sl_btmesh_cmd_lcd_client_init_id 0x01660028`

`#define sl_btmesh_cmd_lcd_client_deinit_id 0x02660028`

`#define sl_btmesh_cmd_lcd_client_get_composition_data_id 0x03660028`

`#define sl_btmesh_cmd_lcd_client_get_metadata_id 0x04660028`

`#define sl_btmesh_rsp_lcd_client_init_id 0x01660028`

`#define sl_btmesh_rsp_lcd_client_deinit_id 0x02660028`

`#define sl_btmesh_rsp_lcd_client_get_composition_data_id 0x03660028`

`#define sl_btmesh_rsp_lcd_client_get_metadata_id 0x04660028`

#### sl_btmesh_evt_lcd_client_data_header

Large Composition Data response message to the [sl_btmesh_lcd_client_get_composition_data](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-composition-data) or [sl_btmesh_lcd_client_get_metadata](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-metadata) command. 

This is a first event in a series, consists of page number, offset and total size of the requested page. 

##### Modules

[sl_btmesh_evt_lcd_client_data_header_s](sl-btmesh-evt-lcd-client-data-header-s)

##### Typedefs

###### sl_btmesh_evt_lcd_client_data_header_t

`typedef struct sl_btmesh_evt_lcd_client_data_header_s sl_btmesh_evt_lcd_client_data_header_t`

##### Macros

`#define sl_btmesh_evt_lcd_client_data_header_id 0x016600a8`

**Description**: Identifier of the data_header event.

Data structure of the data_header event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_lcd_client_data_header_s::handle
```

**Details:** Request handle

###### page_number (heading level 7)

```
uint8_t sl_btmesh_evt_lcd_client_data_header_s::page_number
```

**Details:** Page number of the Composition Data

###### offset (heading level 7)

```
uint16_t sl_btmesh_evt_lcd_client_data_header_s::offset
```

**Details:** Offset within the page

###### total_size (heading level 7)

```
uint16_t sl_btmesh_evt_lcd_client_data_header_s::total_size
```

**Details:** Total size of the page

#### sl_btmesh_evt_lcd_client_data

Event reporting queried composition data page contents. 

The content of the event is requested using the [sl_btmesh_lcd_client_get_composition_data](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-composition-data) or [sl_btmesh_lcd_client_get_metadata](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-metadata) command. More than one event may be generated. This event preceedes by a [sl_btmesh_evt_lcd_client_data_header](sl-btmesh-evt-lcd-client-data-header) event. Page content is terminated by a [sl_btmesh_evt_lcd_client_data_end](sl-btmesh-evt-lcd-client-data-end) event. Note that the interpretation of the received data is page-specific. 

##### Modules

[sl_btmesh_evt_lcd_client_data_s](sl-btmesh-evt-lcd-client-data-s)

##### Typedefs

###### sl_btmesh_evt_lcd_client_data_t

`typedef struct sl_btmesh_evt_lcd_client_data_s sl_btmesh_evt_lcd_client_data_t`

##### Macros

`#define sl_btmesh_evt_lcd_client_data_id 0x026600a8`

**Description**: Identifier of the data event.

Data structure of the data event. 

###### Public Attributes

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_lcd_client_data_s::handle
```

**Details:** Request handle

###### data (heading level 7)

```
uint8array sl_btmesh_evt_lcd_client_data_s::data
```

**Details:** Composition data page contents

#### sl_btmesh_evt_lcd_client_data_end

Terminating event for the Composition Data, response to the [sl_btmesh_lcd_client_get_composition_data](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-composition-data) or [sl_btmesh_lcd_client_get_metadata](sl-btmesh-lcd-client#sl-btmesh-lcd-client-get-metadata) command. 

##### Modules

[sl_btmesh_evt_lcd_client_data_end_s](sl-btmesh-evt-lcd-client-data-end-s)

##### Typedefs

###### sl_btmesh_evt_lcd_client_data_end_t

`typedef struct sl_btmesh_evt_lcd_client_data_end_s sl_btmesh_evt_lcd_client_data_end_t`

##### Macros

`#define sl_btmesh_evt_lcd_client_data_end_id 0x036600a8`

**Description**: Identifier of the data_end event.

Data structure of the data_end event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_lcd_client_data_end_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_lcd_client_data_end_s::handle
```

**Details:** Request handle

### Bluetooth Mesh On-demand Private Proxy Client Model

Bluetooth Mesh On-demand Private Proxy Client Model. 

The On-Demand Private Proxy Client model is used to configure a node to advertise with Private Network Identity 

#### Modules

[sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status](sl-btmesh-evt-on-demand-private-proxy-client-private-gatt-proxy-status)

#### Functions

##### sl_btmesh_on_demand_private_proxy_client_init

`sl_status_t sl_btmesh_on_demand_private_proxy_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the On-Demand Private Proxy Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_on_demand_private_proxy_client_deinit

`sl_status_t sl_btmesh_on_demand_private_proxy_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the On-Demand Private Proxy Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_on_demand_private_proxy_client_get_on_demand_private_gatt_proxy

`sl_status_t sl_btmesh_on_demand_private_proxy_client_get_on_demand_private_gatt_proxy(uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint32_t *|[out]|handle|Request handle|

Get node On-Demand Private GATT proxy state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status](sl-btmesh-evt-on-demand-private-proxy-client-private-gatt-proxy-status)

##### sl_btmesh_on_demand_private_proxy_client_set_on_demand_private_gatt_proxy

`sl_status_t sl_btmesh_on_demand_private_proxy_client_set_on_demand_private_gatt_proxy(uint16_t enc_netkey_index, uint16_t server_address, uint8_t value, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the request on the network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|value|On-Demand Private GATT proxy value to set. Valid values are:<br/><br/>- 0: Advertising with Private Network Identity type cannot be enabled on demand<br/>- 1: Advertising interval for Private Network Identity in seconds|
|uint32_t *|[out]|handle|Request handle|

Set node On-Demand Private GATT proxy state.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status](sl-btmesh-evt-on-demand-private-proxy-client-private-gatt-proxy-status)

#### Macros

`#define sl_btmesh_cmd_on_demand_private_proxy_client_init_id 0x01680028`

`#define sl_btmesh_cmd_on_demand_private_proxy_client_deinit_id 0x02680028`

`#define sl_btmesh_cmd_on_demand_private_proxy_client_get_on_demand_private_gatt_proxy_id 0x03680028`

`#define sl_btmesh_cmd_on_demand_private_proxy_client_set_on_demand_private_gatt_proxy_id 0x04680028`

`#define sl_btmesh_rsp_on_demand_private_proxy_client_init_id 0x01680028`

`#define sl_btmesh_rsp_on_demand_private_proxy_client_deinit_id 0x02680028`

`#define sl_btmesh_rsp_on_demand_private_proxy_client_get_on_demand_private_gatt_proxy_id 0x03680028`

`#define sl_btmesh_rsp_on_demand_private_proxy_client_set_on_demand_private_gatt_proxy_id 0x04680028`

#### sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status

Status event for [sl_btmesh_on_demand_private_proxy_client_get_on_demand_private_gatt_proxy](sl-btmesh-on-demand-private-proxy-client#sl-btmesh-on-demand-private-proxy-client-get-on-demand-private-gatt-proxy) and [sl_btmesh_on_demand_private_proxy_client_set_on_demand_private_gatt_proxy](sl-btmesh-on-demand-private-proxy-client#sl-btmesh-on-demand-private-proxy-client-set-on-demand-private-gatt-proxy) commands. 

##### Modules

[sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_s](sl-btmesh-evt-on-demand-private-proxy-client-private-gatt-proxy-status-s)

##### Typedefs

###### sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_t

`typedef struct sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_s sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_t`

##### Macros

`#define sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_id 0x016800a8`

**Description**: Identifier of the private_gatt_proxy_status event.

Data structure of the private_gatt_proxy_status event. 

###### Public Attributes

###### result (heading level 7)

```
uint16_t sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_s::result
```

**Details:** SL_STATUS_OK if successful. Error code otherwise.

###### handle (heading level 7)

```
uint32_t sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_s::handle
```

**Details:** Request handle

###### value (heading level 7)

```
uint8_t sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_s::value
```

**Details:** On-Demand Private GATT proxy value of the node. Valid values are:

- 0: Advertising with Private Network Identity type cannot be enabled on demand
- 1-255: Advertising interval for Private Network Identity in seconds

### Bluetooth Mesh Solicitation PDU RPL Config Client Model

Bluetooth Mesh Solicitation PDU RPL Config Client Model. 

The Solicitation PDU RPL Configuration Client model is used to support the functionality of removing addresses from the solicitation replay protection list of a node that supports the Solicitation PDU RPL Configuration Server model. A Configuration Manager can use the Solicitation PDU RPL Configuration Client model to remove from the solicitation replay protection list the addresses that have been reassigned to a new node after a node was removed from the network. 

#### Modules

[sl_btmesh_evt_solicitation_config_client_items_status](sl-btmesh-evt-solicitation-config-client-items-status)

#### Functions

##### sl_btmesh_solicitation_config_client_init

`sl_status_t sl_btmesh_solicitation_config_client_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the Solicitation PDU RPL Configuration Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_solicitation_config_client_deinit

`sl_status_t sl_btmesh_solicitation_config_client_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the Solicitation PDU RPL Configuration Client model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_solicitation_config_client_clear_items

`sl_status_t sl_btmesh_solicitation_config_client_clear_items(uint16_t dst, uint16_t appkey_index, uint16_t range_start, uint8_t length_present, uint8_t range_length, uint8_t response_required)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|dst|Destination address|
|uint16_t|[in]|appkey_index|The application key index to use|
|uint16_t|[in]|range_start|15 least significant bits of the starting unicast address|
|uint8_t|[in]|length_present|Indicates the presence or absence of the RangeLength field|
|uint8_t|[in]|range_length|If present, containsNumber of addresses in the range (0x02 – 0xFF), otherwise 0|
|uint8_t|[in]|response_required|Defines whether acknowledged or unacknowledged message shall be used|

Sends a SOLICITATION_PDU_RPL_ITEMS_CLEAR message to remove one or more items from the solicitation replay protection list of a node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_solicitation_config_client_items_status](sl-btmesh-evt-solicitation-config-client-items-status)

#### Macros

`#define sl_btmesh_cmd_solicitation_config_client_init_id 0x01690028`

`#define sl_btmesh_cmd_solicitation_config_client_deinit_id 0x02690028`

`#define sl_btmesh_cmd_solicitation_config_client_clear_items_id 0x03690028`

`#define sl_btmesh_rsp_solicitation_config_client_init_id 0x01690028`

`#define sl_btmesh_rsp_solicitation_config_client_deinit_id 0x02690028`

`#define sl_btmesh_rsp_solicitation_config_client_clear_items_id 0x03690028`

#### sl_btmesh_evt_solicitation_config_client_items_status

Indicate an incoming Solicitation PDU RPL Items Status message, received as a response to the [sl_btmesh_solicitation_config_client_clear_items](sl-btmesh-solicitation-config-client#sl-btmesh-solicitation-config-client-clear-items) command if acknowledged mode used. 

##### Modules

[sl_btmesh_evt_solicitation_config_client_items_status_s](sl-btmesh-evt-solicitation-config-client-items-status-s)

##### Typedefs

###### sl_btmesh_evt_solicitation_config_client_items_status_t

`typedef struct sl_btmesh_evt_solicitation_config_client_items_status_s sl_btmesh_evt_solicitation_config_client_items_status_t`

##### Macros

`#define sl_btmesh_evt_solicitation_config_client_items_status_id 0x016900a8`

**Description**: Identifier of the items_status event.

Data structure of the items_status event. 

###### Public Attributes

###### src (heading level 7)

```
uint16_t sl_btmesh_evt_solicitation_config_client_items_status_s::src
```

**Details:** Server address

###### dst (heading level 7)

```
uint16_t sl_btmesh_evt_solicitation_config_client_items_status_s::dst
```

**Details:** Client address

###### appkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_solicitation_config_client_items_status_s::appkey_index
```

**Details:** App key index

###### range_start (heading level 7)

```
uint16_t sl_btmesh_evt_solicitation_config_client_items_status_s::range_start
```

**Details:** 15 least significant bits of the starting unicast address

###### length_present (heading level 7)

```
uint8_t sl_btmesh_evt_solicitation_config_client_items_status_s::length_present
```

**Details:** Indicates the presence or absence of the RangeLength field

###### range_length (heading level 7)

```
uint8_t sl_btmesh_evt_solicitation_config_client_items_status_s::range_length
```

**Details:** If present, containsNumber of addresses in the range (0x02 – 0xFF), otherwise 0

### Bluetooth Mesh Silabs Configuration Server Vendor Model

Bluetooth Mesh Silabs Configuration Server Vendor Model. 

Silicon Labs Configuration Server vendor model. It provides the functionality of configuration of global and per-model specific settings of a node. 

#### Modules

[sl_btmesh_evt_silabs_config_server_tx_changed](sl-btmesh-evt-silabs-config-server-tx-changed)

[sl_btmesh_evt_silabs_config_server_model_option_changed](sl-btmesh-evt-silabs-config-server-model-option-changed)

[sl_btmesh_evt_silabs_config_server_network_pdu_changed](sl-btmesh-evt-silabs-config-server-network-pdu-changed)

#### Functions

##### sl_btmesh_silabs_config_server_init

`sl_status_t sl_btmesh_silabs_config_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize Silabs Configuration Server model

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_deinit

`sl_status_t sl_btmesh_silabs_config_server_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize Silabs Configuration Server model. After this call, the model cannot be used until it is initialized again. See [sl_btmesh_silabs_config_server_init](sl-btmesh-silabs-config-server#sl-btmesh-silabs-config-server-init).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_set_tx

`sl_status_t sl_btmesh_silabs_config_server_set_tx(uint8_t phy, uint32_t options)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|phy|TX PHY for long packets (packets that would be segmented).<br/><br/>- 1: LE 1M PHY<br/>- 2: LE 2M PHY|
|uint32_t|[in]|options|TX options. NOTE: Currently not used: reserved for future use.|

Set TX PHY for the node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_get_tx

`sl_status_t sl_btmesh_silabs_config_server_get_tx(uint8_t *phy, uint32_t *options)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|phy|TX PHY for long packets (packets that would be segmented).<br/><br/>- 1: LE 1M PHY<br/>- 2: LE 2M PHY|
|uint32_t *|[out]|options|TX options. NOTE: Currently not used: reserved for future use.|

Get current TX PHY.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_set_model_enable

`sl_status_t sl_btmesh_silabs_config_server_set_model_enable(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Element index of model to configure.|
|uint16_t|[in]|vendor_id|Vendor ID of model to configure.|
|uint16_t|[in]|model_id|Model ID of model to configure.|
|uint16_t|[in]|value|Extended packet size to set, currently 1 to use extended 0 to not|

Enable/Disable usage of extended packets for a model.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_get_model_enable

`sl_status_t sl_btmesh_silabs_config_server_get_model_enable(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t *value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Element index of model to get.|
|uint16_t|[in]|vendor_id|Vendor ID of model to get.|
|uint16_t|[in]|model_id|Model ID of model to get.|
|uint16_t *|[out]|value|Extended packet size is used, currently 1 is in use, 0 is not|

Get model settings.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_set_network_pdu

`sl_status_t sl_btmesh_silabs_config_server_set_network_pdu(uint16_t max_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|max_size|Max size of packet to be used, in range 29 - 227 bytes.|

Set max network pdu for the node.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_silabs_config_server_get_network_pdu

`sl_status_t sl_btmesh_silabs_config_server_get_network_pdu(uint16_t *max_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|max_size|Max size of packet, in range 29 - 227 bytes.|

Get max network pdu in use.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_silabs_config_server_init_id 0x006b0028`

`#define sl_btmesh_cmd_silabs_config_server_deinit_id 0x016b0028`

`#define sl_btmesh_cmd_silabs_config_server_set_tx_id 0x026b0028`

`#define sl_btmesh_cmd_silabs_config_server_get_tx_id 0x036b0028`

`#define sl_btmesh_cmd_silabs_config_server_set_model_enable_id 0x046b0028`

`#define sl_btmesh_cmd_silabs_config_server_get_model_enable_id 0x056b0028`

`#define sl_btmesh_cmd_silabs_config_server_set_network_pdu_id 0x066b0028`

`#define sl_btmesh_cmd_silabs_config_server_get_network_pdu_id 0x076b0028`

`#define sl_btmesh_rsp_silabs_config_server_init_id 0x006b0028`

`#define sl_btmesh_rsp_silabs_config_server_deinit_id 0x016b0028`

`#define sl_btmesh_rsp_silabs_config_server_set_tx_id 0x026b0028`

`#define sl_btmesh_rsp_silabs_config_server_get_tx_id 0x036b0028`

`#define sl_btmesh_rsp_silabs_config_server_set_model_enable_id 0x046b0028`

`#define sl_btmesh_rsp_silabs_config_server_get_model_enable_id 0x056b0028`

`#define sl_btmesh_rsp_silabs_config_server_set_network_pdu_id 0x066b0028`

`#define sl_btmesh_rsp_silabs_config_server_get_network_pdu_id 0x076b0028`

#### sl_btmesh_evt_silabs_config_server_tx_changed

TX PHY configuration value has changed. 

New values included in the parameters. 

##### Modules

[sl_btmesh_evt_silabs_config_server_tx_changed_s](sl-btmesh-evt-silabs-config-server-tx-changed-s)

##### Typedefs

###### sl_btmesh_evt_silabs_config_server_tx_changed_t

`typedef struct sl_btmesh_evt_silabs_config_server_tx_changed_s sl_btmesh_evt_silabs_config_server_tx_changed_t`

##### Macros

`#define sl_btmesh_evt_silabs_config_server_tx_changed_id 0x006b00a8`

**Description**: Identifier of the tx_changed event.

Data structure of the tx_changed event. 

###### Public Attributes

###### phy (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_server_tx_changed_s::phy
```

**Details:** TX PHY for long packets (packets that would be segmented).

- 1: LE 1M PHY
- 2: LE 2M PHY

###### options (heading level 7)

```
uint32_t sl_btmesh_evt_silabs_config_server_tx_changed_s::options
```

**Details:** TX options. NOTE: Currently not used: reserved for future use.

#### sl_btmesh_evt_silabs_config_server_model_option_changed

TX over AE on per-model basis enable/disable configuration value has changed. 

##### Modules

[sl_btmesh_evt_silabs_config_server_model_option_changed_s](sl-btmesh-evt-silabs-config-server-model-option-changed-s)

##### Typedefs

###### sl_btmesh_evt_silabs_config_server_model_option_changed_t

`typedef struct sl_btmesh_evt_silabs_config_server_model_option_changed_s sl_btmesh_evt_silabs_config_server_model_option_changed_t`

##### Macros

`#define sl_btmesh_evt_silabs_config_server_model_option_changed_id 0x016b00a8`

**Description**: Identifier of the model_option_changed event.

Data structure of the model_option_changed event. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t sl_btmesh_evt_silabs_config_server_model_option_changed_s::elem_index
```

**Details:** Element index of model to configure.

###### vendor_id (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_server_model_option_changed_s::vendor_id
```

**Details:** Vendor ID of model to configure.

###### model_id (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_server_model_option_changed_s::model_id
```

**Details:** Model ID of model to configure.

###### value (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_server_model_option_changed_s::value
```

**Details:** Extended packet size to set, currently 1 to use extended 0 to not

#### sl_btmesh_evt_silabs_config_server_network_pdu_changed

Network PDU configuration value has changed. 

##### Modules

[sl_btmesh_evt_silabs_config_server_network_pdu_changed_s](sl-btmesh-evt-silabs-config-server-network-pdu-changed-s)

##### Typedefs

###### sl_btmesh_evt_silabs_config_server_network_pdu_changed_t

`typedef struct sl_btmesh_evt_silabs_config_server_network_pdu_changed_s sl_btmesh_evt_silabs_config_server_network_pdu_changed_t`

##### Macros

`#define sl_btmesh_evt_silabs_config_server_network_pdu_changed_id 0x026b00a8`

**Description**: Identifier of the network_pdu_changed event.

Data structure of the network_pdu_changed event. 

###### Public Attributes

###### max_size (heading level 7)

```
uint16_t sl_btmesh_evt_silabs_config_server_network_pdu_changed_s::max_size
```

**Details:** Max size of packet to be used, in range 29 - 227 bytes.

### Bluetooth Mesh Diagnostic Utilities

Bluetooth Mesh Diagnostic Utilities. 

Diagnostic Utilities. It provides the functionality that assist with diagnosing problems. 

#### Modules

[sl_btmesh_evt_diagnostic_relay](sl-btmesh-evt-diagnostic-relay)

[sl_btmesh_evt_diagnostic_friend_queue](sl-btmesh-evt-diagnostic-friend-queue)

[sl_btmesh_evt_diagnostic_friend_relay](sl-btmesh-evt-diagnostic-friend-relay)

[sl_btmesh_evt_diagnostic_friend_remove](sl-btmesh-evt-diagnostic-friend-remove)

#### Functions

##### sl_btmesh_diagnostic_init

`sl_status_t sl_btmesh_diagnostic_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize Diagnostic Utilities.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_deinit

`sl_status_t sl_btmesh_diagnostic_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize Diagnostic Utilities. After this call it cannot be used until it is initialized again. See [sl_btmesh_diagnostic_init](sl-btmesh-diagnostic#sl-btmesh-diagnostic-init).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_enable_relay

`sl_status_t sl_btmesh_diagnostic_enable_relay(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Enable event sending for each relayed or proxied message. NOTE: On NCP target this can saturate the NCP PHY interface. An alternative for this is [sl_btmesh_diagnostic_get_relay](sl-btmesh-diagnostic#sl-btmesh-diagnostic-get-relay)

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_diagnostic_relay](sl-btmesh-evt-diagnostic-relay)

##### sl_btmesh_diagnostic_disable_relay

`sl_status_t sl_btmesh_diagnostic_disable_relay(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Disable event sending for each relayed or proxied message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_get_relay

`sl_status_t sl_btmesh_diagnostic_get_relay(uint32_t *relay_counter)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *|[out]|relay_counter|Relayed or proxied message counter.|

Get relayed or proxied message counter, which is a counter incremented for each relayed or proxied message.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_get_statistics

`sl_status_t sl_btmesh_diagnostic_get_statistics(uint32_t requested_chunk, uint32_t requested_offset, uint32_t *total_length, uint32_t *chunk_offset, size_t max_statistics_size, size_t *statistics_len, uint8_t *statistics)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|requested_chunk|Size of the statistics data chunk requested|
|uint32_t|[in]|requested_offset|Byte offset to the statistics data chunk requested|
|uint32_t *|[out]|total_length|Total length of the statistics data in the system|
|uint32_t *|[out]|chunk_offset|Byte offset to the statistics data chunk delivered|
|size_t|[in]|max_statistics_size|Size of output buffer passed in `statistics`|
|size_t *|[out]|statistics_len|On return, set to the length of output data written to `statistics`|
|uint8_t *|[out]|statistics|Raw statistics data counter array.|

Get a chunk of Bluetooth mesh stack statistics data counters. As there can be a large amount of statistics, it has to be retrieved as chunks. The application is free to specify the size of the chunk it wants to use, but keep in mind that there is an inherent BGAPI limitation that caps the maximum size for the variable-length data array to 255 bytes; and furthermore, for the NCP use case there may be limited size buffers in the underlying serial channel.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_clear_statistics

`sl_status_t sl_btmesh_diagnostic_clear_statistics(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Clear Bluetooth mesh stack statistics data counters.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_enable_friend

`sl_status_t sl_btmesh_diagnostic_enable_friend(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Enable event sending for friendship diagnostics on the friend node side. NOTE: On NCP target this can saturate the NCP PHY interface. An alternative for this is [sl_btmesh_diagnostic_get_friend](sl-btmesh-diagnostic#sl-btmesh-diagnostic-get-friend)

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

**Events**

- [sl_btmesh_evt_diagnostic_friend_queue](sl-btmesh-evt-diagnostic-friend-queue)
- [sl_btmesh_evt_diagnostic_friend_relay](sl-btmesh-evt-diagnostic-friend-relay)
- [sl_btmesh_evt_diagnostic_friend_remove](sl-btmesh-evt-diagnostic-friend-remove)

##### sl_btmesh_diagnostic_disable_friend

`sl_status_t sl_btmesh_diagnostic_disable_friend(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Disable event sending for friendship diagnostics on the friend node side.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

##### sl_btmesh_diagnostic_get_friend

`sl_status_t sl_btmesh_diagnostic_get_friend(uint32_t *queue_counter, uint32_t *relay_counter, uint32_t *remove_counter_sent, uint32_t *remove_counter_old_pdu, uint32_t *remove_counter_old_segack, uint32_t *remove_counter_old_segment)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *|[out]|queue_counter|Number of messages queued for LPNs.|
|uint32_t *|[out]|relay_counter|Number of messages relayed to LPNs as a response to polls.|
|uint32_t *|[out]|remove_counter_sent|Number of messages discarded from LPN friendship queues due to message having been to sent to LPN and acknowledged by LPN by it sending the next poll.|
|uint32_t *|[out]|remove_counter_old_pdu|Number of messages discarded from LPN friendship queues due to message queue overflow, resulting in the need to flush the oldest PDU un the queue|
|uint32_t *|[out]|remove_counter_old_segack|Number of messages discarded from LPN friendship queues due to a new segment acknowledgement message replacing an old one in the queue.|
|uint32_t *|[out]|remove_counter_old_segment|Number of messages discarded from LPN friendship queues due to invalidated segments being removed from the queue.|

Get friend event counters.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

#### Macros

`#define sl_btmesh_cmd_diagnostic_init_id 0x006c0028`

`#define sl_btmesh_cmd_diagnostic_deinit_id 0x016c0028`

`#define sl_btmesh_cmd_diagnostic_enable_relay_id 0x026c0028`

`#define sl_btmesh_cmd_diagnostic_disable_relay_id 0x036c0028`

`#define sl_btmesh_cmd_diagnostic_get_relay_id 0x046c0028`

`#define sl_btmesh_cmd_diagnostic_get_statistics_id 0x056c0028`

`#define sl_btmesh_cmd_diagnostic_clear_statistics_id 0x066c0028`

`#define sl_btmesh_cmd_diagnostic_enable_friend_id 0x076c0028`

`#define sl_btmesh_cmd_diagnostic_disable_friend_id 0x086c0028`

`#define sl_btmesh_cmd_diagnostic_get_friend_id 0x096c0028`

`#define sl_btmesh_rsp_diagnostic_init_id 0x006c0028`

`#define sl_btmesh_rsp_diagnostic_deinit_id 0x016c0028`

`#define sl_btmesh_rsp_diagnostic_enable_relay_id 0x026c0028`

`#define sl_btmesh_rsp_diagnostic_disable_relay_id 0x036c0028`

`#define sl_btmesh_rsp_diagnostic_get_relay_id 0x046c0028`

`#define sl_btmesh_rsp_diagnostic_get_statistics_id 0x056c0028`

`#define sl_btmesh_rsp_diagnostic_clear_statistics_id 0x066c0028`

`#define sl_btmesh_rsp_diagnostic_enable_friend_id 0x076c0028`

`#define sl_btmesh_rsp_diagnostic_disable_friend_id 0x086c0028`

`#define sl_btmesh_rsp_diagnostic_get_friend_id 0x096c0028`

#### sl_btmesh_evt_diagnostic_relay

Event for each relayed or proxied message. 

##### Modules

[sl_btmesh_evt_diagnostic_relay_s](sl-btmesh-evt-diagnostic-relay-s)

##### Typedefs

###### sl_btmesh_evt_diagnostic_relay_t

`typedef struct sl_btmesh_evt_diagnostic_relay_s sl_btmesh_evt_diagnostic_relay_t`

##### Macros

`#define sl_btmesh_evt_diagnostic_relay_id 0x006c00a8`

**Description**: Identifier of the relay event.

Data structure of the relay event. 

###### Public Attributes

###### destination_address (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_relay_s::destination_address
```

**Details:** Message destination address

###### source_address (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_relay_s::source_address
```

**Details:** Message source address

###### rssi (heading level 7)

```
int8_t sl_btmesh_evt_diagnostic_relay_s::rssi
```

**Details:** RSSI value of the relayed message. Units: dBm.

###### ttl (heading level 7)

```
uint8_t sl_btmesh_evt_diagnostic_relay_s::ttl
```

**Details:** Time-to-Live value of the relayed or proxied message

#### sl_btmesh_evt_diagnostic_friend_queue

Event for LPN message queuing. 

##### Modules

[sl_btmesh_evt_diagnostic_friend_queue_s](sl-btmesh-evt-diagnostic-friend-queue-s)

##### Typedefs

###### sl_btmesh_evt_diagnostic_friend_queue_t

`typedef struct sl_btmesh_evt_diagnostic_friend_queue_s sl_btmesh_evt_diagnostic_friend_queue_t`

##### Macros

`#define sl_btmesh_evt_diagnostic_friend_queue_id 0x016c00a8`

**Description**: Identifier of the friend_queue event.

Data structure of the friend_queue event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_queue_s::netkey_index
```

**Details:** Index of the network key used in friendship

###### lpn (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_queue_s::lpn
```

**Details:** LPN address

###### src (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_queue_s::src
```

**Details:** Source address of the message

###### dst (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_queue_s::dst
```

**Details:** Destination address of the message

###### ivi (heading level 7)

```
uint32_t sl_btmesh_evt_diagnostic_friend_queue_s::ivi
```

**Details:** IV index used to secure the message

###### seq (heading level 7)

```
uint32_t sl_btmesh_evt_diagnostic_friend_queue_s::seq
```

**Details:** Sequence number of the message

#### sl_btmesh_evt_diagnostic_friend_relay

Event for LPN message relaying as a response to a poll request from the LPN. 

##### Modules

[sl_btmesh_evt_diagnostic_friend_relay_s](sl-btmesh-evt-diagnostic-friend-relay-s)

##### Typedefs

###### sl_btmesh_evt_diagnostic_friend_relay_t

`typedef struct sl_btmesh_evt_diagnostic_friend_relay_s sl_btmesh_evt_diagnostic_friend_relay_t`

##### Macros

`#define sl_btmesh_evt_diagnostic_friend_relay_id 0x026c00a8`

**Description**: Identifier of the friend_relay event.

Data structure of the friend_relay event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_relay_s::netkey_index
```

**Details:** Index of the network key used in friendship

###### lpn (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_relay_s::lpn
```

**Details:** LPN address

###### src (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_relay_s::src
```

**Details:** Source address of the message

###### dst (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_relay_s::dst
```

**Details:** Destination address of the message

###### ivi (heading level 7)

```
uint32_t sl_btmesh_evt_diagnostic_friend_relay_s::ivi
```

**Details:** IV index used to secure the message

###### seq (heading level 7)

```
uint32_t sl_btmesh_evt_diagnostic_friend_relay_s::seq
```

**Details:** Sequence number of the message

#### sl_btmesh_evt_diagnostic_friend_remove

Event for removing a message from friendship queue. 

##### Modules

[sl_btmesh_evt_diagnostic_friend_remove_s](sl-btmesh-evt-diagnostic-friend-remove-s)

##### Typedefs

###### sl_btmesh_evt_diagnostic_friend_remove_t

`typedef struct sl_btmesh_evt_diagnostic_friend_remove_s sl_btmesh_evt_diagnostic_friend_remove_t`

##### Macros

`#define sl_btmesh_evt_diagnostic_friend_remove_id 0x036c00a8`

**Description**: Identifier of the friend_remove event.

Data structure of the friend_remove event. 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_remove_s::netkey_index
```

**Details:** Index of the network key used in friendship

###### lpn (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_remove_s::lpn
```

**Details:** LPN address

###### src (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_remove_s::src
```

**Details:** Source address of the message

###### dst (heading level 7)

```
uint16_t sl_btmesh_evt_diagnostic_friend_remove_s::dst
```

**Details:** Destination address of the message

###### ivi (heading level 7)

```
uint32_t sl_btmesh_evt_diagnostic_friend_remove_s::ivi
```

**Details:** IV index used to secure the message

###### seq (heading level 7)

```
uint32_t sl_btmesh_evt_diagnostic_friend_remove_s::seq
```

**Details:** Sequence number of the message

###### reason (heading level 7)

```
uint8_t sl_btmesh_evt_diagnostic_friend_remove_s::reason
```

**Details:** Reason for removing the message. The following reasons are defined:

- 0: The message has been acknowledged as delivered by the LPN
- 1: The message queue has overflowed and the oldest message was dropped
- 2: A newer segment acknowledgement has been inserted to the message queue
- 3: Invalidated message segments have been cleaned up

### BTMESH Common Types

Common types of `btmesh` API. 

#### Modules

[sl_btmesh_msg](sl-btmesh-msg)

[sl_btmesh_msg.data](sl-btmesh-msg-data)

#### Typedefs

##### sl_btmesh_msg_t

`typedef struct sl_btmesh_msg sl_btmesh_msg_t`

**Description:**

Type definition for the data structure of `btmesh` API messages.

Data structure of `btmesh` API messages. 

##### Public Attributes

###### header

```
uint32_t sl_btmesh_msg::header
```

**Details:** API protocol header consisting of event identifier and data length

###### data

```
union sl_btmesh_msg::@0 sl_btmesh_msg::data
```

**Details:** Union of API event types

Union of API event types 

##### Public Attributes

###### handle

```
undefined
```

###### evt_node_initialized

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_initialized_id

###### evt_node_provisioned

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_provisioned_id

###### evt_node_config_get

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_config_get_id

###### evt_node_config_set

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_config_set_id

###### evt_node_display_output_oob

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_display_output_oob_id

###### evt_node_input_oob_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_input_oob_request_id

###### evt_node_provisioning_started

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_provisioning_started_id

###### evt_node_provisioning_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_provisioning_failed_id

###### evt_node_key_added

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_key_added_id

###### evt_node_model_config_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_model_config_changed_id

###### evt_node_ivrecovery_needed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_ivrecovery_needed_id

###### evt_node_changed_ivupdate_state

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_changed_ivupdate_state_id

###### evt_node_key_removed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_key_removed_id

###### evt_node_key_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_key_updated_id

###### evt_node_heartbeat

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_heartbeat_id

###### evt_node_heartbeat_start

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_heartbeat_start_id

###### evt_node_heartbeat_stop

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_heartbeat_stop_id

###### evt_node_beacon_received

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_beacon_received_id

###### evt_node_local_dcd_data

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_local_dcd_data_id

###### evt_node_local_dcd_data_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_local_dcd_data_end_id

###### evt_node_local_model_metadata_page

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_local_model_metadata_page_id

###### evt_node_local_model_metadata_page_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_local_model_metadata_page_end_id

###### evt_node_start_received

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_start_received_id

###### evt_node_address_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_node_address_updated_id

###### evt_prov_initialized

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_initialized_id

###### evt_prov_provisioning_suspended

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_provisioning_suspended_id

###### evt_prov_capabilities

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_capabilities_id

###### evt_prov_provisioning_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_provisioning_failed_id

###### evt_prov_device_provisioned

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_device_provisioned_id

###### evt_prov_unprov_beacon

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_unprov_beacon_id

###### evt_prov_oob_pkey_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_oob_pkey_request_id

###### evt_prov_oob_auth_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_oob_auth_request_id

###### evt_prov_oob_display_input

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_oob_display_input_id

###### evt_prov_ddb_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_ddb_list_id

###### evt_prov_uri

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_uri_id

###### evt_prov_key_refresh_phase_update

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_key_refresh_phase_update_id

###### evt_prov_key_refresh_node_update

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_key_refresh_node_update_id

###### evt_prov_key_refresh_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_key_refresh_complete_id

###### evt_prov_add_ddb_entry_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_add_ddb_entry_complete_id

###### evt_prov_delete_ddb_entry_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_delete_ddb_entry_complete_id

###### evt_prov_initialization_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_initialization_failed_id

###### evt_prov_provisioning_records_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_provisioning_records_list_id

###### evt_prov_provisioning_record_data

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_provisioning_record_data_id

###### evt_prov_start_sent

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_prov_start_sent_id

###### evt_proxy_connected

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_proxy_connected_id

###### evt_proxy_disconnected

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_proxy_disconnected_id

###### evt_proxy_filter_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_proxy_filter_status_id

###### evt_silabs_config_client_tx_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_silabs_config_client_tx_status_id

###### evt_silabs_config_client_model_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_silabs_config_client_model_status_id

###### evt_silabs_config_client_network_pdu_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_silabs_config_client_network_pdu_status_id

###### evt_vendor_model_receive

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_vendor_model_receive_id

###### evt_vendor_model_send_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_vendor_model_send_complete_id

###### evt_health_client_server_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_health_client_server_status_id

###### evt_health_client_server_status_period

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_health_client_server_status_period_id

###### evt_health_client_server_status_attention

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_health_client_server_status_attention_id

###### evt_health_server_attention

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_health_server_attention_id

###### evt_health_server_test_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_health_server_test_request_id

###### evt_generic_client_server_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_generic_client_server_status_id

###### evt_generic_server_client_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_generic_server_client_request_id

###### evt_generic_server_state_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_generic_server_state_changed_id

###### evt_generic_server_state_recall

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_generic_server_state_recall_id

###### evt_test_local_heartbeat_subscription_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_test_local_heartbeat_subscription_complete_id

###### evt_test_replay_protection_list_entry_set

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_test_replay_protection_list_entry_set_id

###### evt_test_replay_protection_list_entry_cleared

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_test_replay_protection_list_entry_cleared_id

###### evt_test_replay_protection_list_saved

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_test_replay_protection_list_saved_id

###### evt_lpn_friendship_established

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lpn_friendship_established_id

###### evt_lpn_friendship_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lpn_friendship_failed_id

###### evt_lpn_friendship_terminated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lpn_friendship_terminated_id

###### evt_friend_friendship_established

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_friend_friendship_established_id

###### evt_friend_friendship_terminated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_friend_friendship_terminated_id

###### evt_config_client_request_modified

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_request_modified_id

###### evt_config_client_netkey_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_netkey_status_id

###### evt_config_client_netkey_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_netkey_list_id

###### evt_config_client_netkey_list_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_netkey_list_end_id

###### evt_config_client_appkey_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_appkey_status_id

###### evt_config_client_appkey_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_appkey_list_id

###### evt_config_client_appkey_list_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_appkey_list_end_id

###### evt_config_client_binding_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_binding_status_id

###### evt_config_client_bindings_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_bindings_list_id

###### evt_config_client_bindings_list_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_bindings_list_end_id

###### evt_config_client_model_pub_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_model_pub_status_id

###### evt_config_client_model_sub_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_model_sub_status_id

###### evt_config_client_subs_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_subs_list_id

###### evt_config_client_subs_list_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_subs_list_end_id

###### evt_config_client_heartbeat_pub_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_heartbeat_pub_status_id

###### evt_config_client_heartbeat_sub_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_heartbeat_sub_status_id

###### evt_config_client_beacon_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_beacon_status_id

###### evt_config_client_default_ttl_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_default_ttl_status_id

###### evt_config_client_gatt_proxy_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_gatt_proxy_status_id

###### evt_config_client_relay_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_relay_status_id

###### evt_config_client_network_transmit_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_network_transmit_status_id

###### evt_config_client_identity_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_identity_status_id

###### evt_config_client_friend_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_friend_status_id

###### evt_config_client_key_refresh_phase_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_key_refresh_phase_status_id

###### evt_config_client_lpn_polltimeout_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_lpn_polltimeout_status_id

###### evt_config_client_dcd_data

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_dcd_data_id

###### evt_config_client_dcd_data_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_dcd_data_end_id

###### evt_config_client_reset_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_reset_status_id

###### evt_config_client_obo_ack_received

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_config_client_obo_ack_received_id

###### evt_mbt_client_server_information_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_server_information_status_id

###### evt_mbt_client_query_information_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_query_information_complete_id

###### evt_mbt_client_server_transfer_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_server_transfer_status_id

###### evt_mbt_client_start_transfer_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_start_transfer_complete_id

###### evt_mbt_client_server_block_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_server_block_status_id

###### evt_mbt_client_start_block_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_start_block_complete_id

###### evt_mbt_client_send_chunk_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_send_chunk_request_id

###### evt_mbt_client_server_partial_block_report

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_server_partial_block_report_id

###### evt_mbt_client_send_chunks_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_send_chunks_complete_id

###### evt_mbt_client_query_block_status_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_query_block_status_complete_id

###### evt_mbt_client_tx_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_tx_complete_id

###### evt_mbt_client_server_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_server_failed_id

###### evt_mbt_client_transfer_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_client_transfer_complete_id

###### evt_mbt_server_state_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_state_changed_id

###### evt_mbt_server_transfer_start_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_transfer_start_req_id

###### evt_mbt_server_block_start

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_block_start_id

###### evt_mbt_server_chunk

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_chunk_id

###### evt_mbt_server_block_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_block_complete_id

###### evt_mbt_server_transfer_cancel

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_transfer_cancel_id

###### evt_mbt_server_partial_block_report_tx_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_mbt_server_partial_block_report_tx_complete_id

###### evt_sensor_server_get_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_server_get_request_id

###### evt_sensor_server_get_column_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_server_get_column_request_id

###### evt_sensor_server_get_series_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_server_get_series_request_id

###### evt_sensor_server_publish

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_server_publish_id

###### evt_sensor_setup_server_get_cadence_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_setup_server_get_cadence_request_id

###### evt_sensor_setup_server_set_cadence_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_setup_server_set_cadence_request_id

###### evt_sensor_setup_server_get_settings_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_setup_server_get_settings_request_id

###### evt_sensor_setup_server_get_setting_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_setup_server_get_setting_request_id

###### evt_sensor_setup_server_set_setting_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_setup_server_set_setting_request_id

###### evt_sensor_setup_server_publish

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_setup_server_publish_id

###### evt_sensor_client_descriptor_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_descriptor_status_id

###### evt_sensor_client_cadence_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_cadence_status_id

###### evt_sensor_client_settings_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_settings_status_id

###### evt_sensor_client_setting_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_setting_status_id

###### evt_sensor_client_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_status_id

###### evt_sensor_client_column_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_column_status_id

###### evt_sensor_client_series_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_series_status_id

###### evt_sensor_client_publish

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sensor_client_publish_id

###### evt_fw_update_client_info_status_current_fwid

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_client_info_status_current_fwid_id

###### evt_fw_update_client_info_status_update_uri

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_client_info_status_update_uri_id

###### evt_fw_update_client_update_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_client_update_status_id

###### evt_fw_update_client_metadata_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_client_metadata_status_id

###### evt_lc_client_mode_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_client_mode_status_id

###### evt_lc_client_om_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_client_om_status_id

###### evt_lc_client_light_onoff_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_client_light_onoff_status_id

###### evt_lc_client_property_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_client_property_status_id

###### evt_lc_server_mode_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_mode_updated_id

###### evt_lc_server_om_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_om_updated_id

###### evt_lc_server_light_onoff_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_light_onoff_updated_id

###### evt_lc_server_occupancy_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_occupancy_updated_id

###### evt_lc_server_ambient_lux_level_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_ambient_lux_level_updated_id

###### evt_lc_server_linear_output_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_linear_output_updated_id

###### evt_lc_server_state_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_state_updated_id

###### evt_lc_server_regulator_debug_info

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_server_regulator_debug_info_id

###### evt_lc_setup_server_set_property

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lc_setup_server_set_property_id

###### evt_scene_client_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_client_status_id

###### evt_scene_client_register_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_client_register_status_id

###### evt_scene_server_get

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_server_get_id

###### evt_scene_server_register_get

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_server_register_get_id

###### evt_scene_server_recall

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_server_recall_id

###### evt_scene_server_publish

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_server_publish_id

###### evt_scene_server_compact_recall

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_server_compact_recall_id

###### evt_scene_setup_server_store

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_setup_server_store_id

###### evt_scene_setup_server_delete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_setup_server_delete_id

###### evt_scene_setup_server_publish

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scene_setup_server_publish_id

###### evt_scheduler_client_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scheduler_client_status_id

###### evt_scheduler_client_action_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scheduler_client_action_status_id

###### evt_scheduler_server_action_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scheduler_server_action_changed_id

###### evt_scheduler_server_scene_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scheduler_server_scene_changed_id

###### evt_scheduler_server_action_triggered

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_scheduler_server_action_triggered_id

###### evt_fw_update_server_check_fw_metadata_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_server_check_fw_metadata_req_id

###### evt_fw_update_server_update_start_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_server_update_start_req_id

###### evt_fw_update_server_verify_fw_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_server_verify_fw_req_id

###### evt_fw_update_server_apply

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_server_apply_id

###### evt_fw_update_server_update_cancelled

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_server_update_cancelled_id

###### evt_fw_update_server_distributor_self_update_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_update_server_distributor_self_update_req_id

###### evt_time_server_time_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_server_time_updated_id

###### evt_time_server_time_zone_offset_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_server_time_zone_offset_updated_id

###### evt_time_server_tai_utc_delta_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_server_tai_utc_delta_updated_id

###### evt_time_server_time_role_updated

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_server_time_role_updated_id

###### evt_time_client_time_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_client_time_status_id

###### evt_time_client_time_zone_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_client_time_zone_status_id

###### evt_time_client_tai_utc_delta_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_client_tai_utc_delta_status_id

###### evt_time_client_time_role_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_time_client_time_role_status_id

###### evt_fw_dist_server_nodes_added

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_nodes_added_id

###### evt_fw_dist_server_nodes_deleted

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_nodes_deleted_id

###### evt_fw_dist_server_dist_start_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_dist_start_req_id

###### evt_fw_dist_server_dist_cancel

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_dist_cancel_id

###### evt_fw_dist_server_dist_cancel_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_dist_cancel_complete_id

###### evt_fw_dist_server_upload_start_metadata

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_start_metadata_id

###### evt_fw_dist_server_upload_start_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_start_req_id

###### evt_fw_dist_server_upload_cancel

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_cancel_id

###### evt_fw_dist_server_dist_state_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_dist_state_changed_id

###### evt_fw_dist_server_node_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_node_failed_id

###### evt_fw_dist_server_upload_complete_metadata

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_complete_metadata_id

###### evt_fw_dist_server_upload_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_complete_id

###### evt_fw_dist_server_upload_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_failed_id

###### evt_fw_dist_server_upload_oob_start_uri

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_oob_start_uri_id

###### evt_fw_dist_server_upload_oob_start_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_upload_oob_start_req_id

###### evt_fw_dist_server_fw_delete_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_fw_delete_req_id

###### evt_fw_dist_server_fw_delete_all_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_fw_delete_all_req_id

###### evt_fw_dist_server_dist_suspend

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_dist_suspend_id

###### evt_fw_dist_server_resume_req

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_server_resume_req_id

###### evt_fw_dist_client_receivers_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_receivers_status_id

###### evt_fw_dist_client_receivers_list

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_receivers_list_id

###### evt_fw_dist_client_receivers_list_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_receivers_list_end_id

###### evt_fw_dist_client_capabilities_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_capabilities_status_id

###### evt_fw_dist_client_distribution_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_distribution_status_id

###### evt_fw_dist_client_upload_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_upload_status_id

###### evt_fw_dist_client_fw_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_fw_status_id

###### evt_fw_dist_client_upload_complete

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_upload_complete_id

###### evt_fw_dist_client_upload_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_dist_client_upload_failed_id

###### evt_remote_provisioning_client_scan_capabilities

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_client_scan_capabilities_id

###### evt_remote_provisioning_client_scan_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_client_scan_status_id

###### evt_remote_provisioning_client_scan_report

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_client_scan_report_id

###### evt_remote_provisioning_client_extended_scan_report

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_client_extended_scan_report_id

###### evt_remote_provisioning_client_link_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_client_link_status_id

###### evt_remote_provisioning_client_link_report

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_client_link_report_id

###### evt_remote_provisioning_server_link_open_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_server_link_open_request_id

###### evt_remote_provisioning_server_link_close_request

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_remote_provisioning_server_link_close_request_id

###### evt_fw_standalone_updater_dist_state_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_standalone_updater_dist_state_changed_id

###### evt_fw_standalone_updater_node_failed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_fw_standalone_updater_node_failed_id

###### evt_ncp_fw_list_fw_deleted

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_ncp_fw_list_fw_deleted_id

###### evt_ncp_fw_list_fw_all_deleted

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_ncp_fw_list_fw_all_deleted_id

###### evt_ncp_fw_list_fw_added

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_ncp_fw_list_fw_added_id

###### evt_sar_config_client_sar_transmitter_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sar_config_client_sar_transmitter_status_id

###### evt_sar_config_client_sar_receiver_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sar_config_client_sar_receiver_status_id

###### evt_sar_config_server_sar_transmitter_set

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sar_config_server_sar_transmitter_set_id

###### evt_sar_config_server_sar_receiver_set

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_sar_config_server_sar_receiver_set_id

###### evt_private_beacon_client_beacon_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_private_beacon_client_beacon_status_id

###### evt_private_beacon_client_gatt_proxy_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_private_beacon_client_gatt_proxy_status_id

###### evt_private_beacon_client_identity_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_private_beacon_client_identity_status_id

###### evt_lcd_client_data_header

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lcd_client_data_header_id

###### evt_lcd_client_data

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lcd_client_data_id

###### evt_lcd_client_data_end

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_lcd_client_data_end_id

###### evt_on_demand_private_proxy_client_private_gatt_proxy_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_on_demand_private_proxy_client_private_gatt_proxy_status_id

###### evt_solicitation_config_client_items_status

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_solicitation_config_client_items_status_id

###### evt_silabs_config_server_tx_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_silabs_config_server_tx_changed_id

###### evt_silabs_config_server_model_option_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_silabs_config_server_model_option_changed_id

###### evt_silabs_config_server_network_pdu_changed

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_silabs_config_server_network_pdu_changed_id

###### evt_diagnostic_relay

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_diagnostic_relay_id

###### evt_diagnostic_friend_queue

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_diagnostic_friend_queue_id

###### evt_diagnostic_friend_relay

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_diagnostic_friend_relay_id

###### evt_diagnostic_friend_remove

```
undefined
```

**Details:** Data field for event sl_btmesh_evt_diagnostic_friend_remove_id

###### payload

```
undefined
```

## Bluetooth Mesh Service API Reference

### Bluetooth Mesh Message Decoder Library

#### Introduction

This library provides utilities for decrypting, authenticating, and decoding Bluetooth Mesh messages. It relies on the PSA Crypto API for cryptographic functionality.

The library supports the following Mesh stack features:

- Decrypting and authenticating Mesh Network PDUs with  
  - Flooding credentials  
  - Directed forwarding credentials  
  - Friendship credentials (provided that friendship establishment is observed)
- Decoding decrypted Mesh Network PDU contents
- Decoding Lower Transport PDU contents
- Reassembling segmented Upper Transport messages  
  - Provided that all segments are observed
- Decoding Transport Control messages
- Decrypting and authenticating Access messages
- Authenticating Mesh beacons
- Decoding Mesh beacons

The library does **not** support the following Mesh stack features:

- Network cache  
  - It is up to the application to process or not process data that is decoded from receives messages when it can be retransmitted
- Replay protection  
  - It is up to the application to process or not process data that is decoded from receives messages when it can be replayed
- Scanning for Mesh traffic  
  - It is the application's responsibility to supply scanned data to the library
- Decoding model messages  
  - This is up to the application or a higher layer library
- GATT traffic  
  - Potentially to be added later
- The provisioning protocol  
  - Potentially to be added later

#### Quickstart

When building an application the library needs to be configured accordingly by

- Setting the optional feature support;
- Setting the number of encryption keys to support;
- Setting the number of label UUIDs to support;
- Setting the number of SAR reassemblies to support;
- Setting the number of friendships to track;

These can be done by editing sl_mesh_decoder_config.h

Furthermore, it needs to be ensured that PSA Crypto is compiled with enough resources to manage all necessary encryption keys including all derivations for the network key (seven if directed forwarding credentials are supported) and friendship derivations (two per friendship).

An application using the library should do the following:

- Initialize a decoder context: sl_mesh_decoder_create()
- Install an initial set of encryption keys:  
  - sl_mesh_decoder_add_network_key() – note that this will generate multiple derived keys internally  
  - sl_mesh_decoder_add_application_key()  
  - sl_mesh_decoder_add_device_key()
- Install a set of label UUIDs (if any) by sl_mesh_decoder_add_virtual_label_uuid()
- Know the current IV index for the network
- Feed incoming network PDU data to sl_mesh_decoder_decrypt_net_pdu()
- If decryption succeeds:  
  - Examine the network PDU contents, starting with sl_mesh_net_pdu_is_valid()  
  - Examine the lower transport PDU within network PDU payload, starting with sl_mesh_net_pdu_contains_valid_trans_pdu()  
  - Make use of the SAR reassembler for segmented messages (sl_mesh_reassembler_add_segment())  
  - Examine transport control message contents, starting with sl_mesh_pointer_contains_valid_control_message()    
    - Make use of friendship tracking (sl_mesh_friendship_add_friend_request(), sl_mesh_friendship_add_friend_offer())  
  - Feed access message data to sl_mesh_decoder_decrypt_access_pdu()  
  - If decryption succeeds:    
    - Examine access message contents, starting with sl_mesh_access_pdu_contains_valid_access_message()

### Profile Metadata

This group includes components that provide metadata for various Network Lighting Control (NLC) profiles in Bluetooth Mesh networks. These components ensure that the relevant profile metadata is included in the Device Composition Data (DCD) Page 2. They are designed for seamless integration into SOC applications and are primarily No-Code components. 

#### Modules

[Basic Scene Selector Profile Metadata](btmesh-nlc-basic-scene-selector-profile-metadata)

[Dimming Control Profile Metadata](btmesh-nlc-dimming-control-profile-metadata)

[Energy monitor Profile Metadata](btmesh-nlc-energy-monitor-profile-metadata)

[Ambient Light Sensor Profile Metadata](btmesh-nlc-ambient-light-sensor-profile-metadata)

[Occupancy Sensor Profile Metadata](btmesh-nlc-occupancy-sensor-profile-metadata)

[Basic Lightness Controller Profile Metadata](btmesh-nlc-basic-lightness-controller-profile-metadata)

#### Basic Scene Selector Profile Metadata

This component provides the relevant metadata so the Basic Scene Selector NLC profile is included in DCD Page 2.

#### Dimming Control Profile Metadata

This component provides the relevant metadata so the Dimming Control NLC profile is included in DCD Page 2.

#### Energy monitor Profile Metadata

This component provides the relevant metadata so the Energy Monitor NLC profile is included in DCD Page 2.

#### Ambient Light Sensor Profile Metadata

This component provides the relevant metadata so the Ambient Light Sensor NLC profile is included in DCD Page 2.

#### Occupancy Sensor Profile Metadata

This component provides the relevant metadata so the Occupancy Sensor NLC profile is included in DCD Page 2.

#### Basic Lightness Controller Profile Metadata

This component provides the relevant metadata so the Basic Lightness Controller NLC profile is included in DCD Page 2.

### Host

This group includes components that provide host-side functionality for Bluetooth Mesh networking. These components are designed to run on a host PC running a desktop OS. 

#### Modules

[BT Mesh Remote Provisioner Application Component](btmesh-host-app-remote-prov)

[BT Mesh Provisioner CBP Application Component](btmesh-host-app-prov-cbp)

[NCP Host BT Mesh Component](ncp-host-btmesh)

[BT Mesh Provisioner Application Component](btmesh-host-app-prov)

[BT Mesh Remote Provisioner Component](btmesh-host-remote-prov)

[BT Mesh Provisioner UI Application Component](btmesh-host-app-prov-ui)

[BT Mesh Remote Provisioner UI Application Component](btmesh-host-app-remote-prov-ui)

[BT Mesh Provisioner Component](btmesh-host-prov)

[BT Mesh Database Component](btmesh-host-db)

[BT Mesh Configurator Component](btmesh-host-conf)

[BT Mesh Key Export Component](btmesh-host-key-export)

#### BT Mesh Remote Provisioner Application Component

BT Mesh Remote Provisioner Application component provides application-level functionality for remote provisioning of devices in Bluetooth Mesh networks. 

##### Functions

###### btmesh_app_remote_prov_init

`sl_status_t btmesh_app_remote_prov_init(int cmd_opt, char *cmd_optarg)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|cmd_opt|Command option|
|char *|[in]|cmd_optarg|Command argument|

Remote Provisioner Command Line Application Init

###### btmesh_app_remote_prov_process_action

`void btmesh_app_remote_prov_process_action(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Remote Provisioner Application Process Action 

###### btmesh_app_remote_prov_on_event

`void btmesh_app_remote_prov_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Event coming from the Bluetooth Mesh stack|

Bluetooth Mesh stack event handler

###### btmesh_app_remote_prov_get_command

`void btmesh_app_remote_prov_get_command(command_t *remote_prov_command, command_state_t *remote_prov_command_state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|command_t *|[out]|remote_prov_command|Current command|
|command_state_t *|[out]|remote_prov_command_state|Current command status|

Get the remote provisioner command and command status

###### btmesh_app_remote_prov_set_command

`void btmesh_app_remote_prov_set_command(command_t remote_prov_command)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|command_t|[in]|remote_prov_command|New command|

Set the remote provisioner command

###### btmesh_app_remote_prov_set_command_state

`void btmesh_app_remote_prov_set_command_state(command_state_t remote_prov_command_state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|command_state_t|[out]|remote_prov_command_state|New command status|

Set the remote provisioner command status

###### btmesh_app_remote_prov_end_of_cmd

`void btmesh_app_remote_prov_end_of_cmd(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Callback to inform when the command ends 

###### btmesh_app_remote_prov_get_server_address

`bool btmesh_app_remote_prov_get_server_address(uint16_t *ui_server_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|ui_server_address|The variable to fill with server address|

Get remote provisioning server address from UI

###### btmesh_app_remote_prov_get_prov_data

`bool btmesh_app_remote_prov_get_prov_data(uint16_t *remote_prov_server_addr, uuid_128 *remote_prov_uuid, uint16_t *remote_prov_oob_capabilities)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|remote_prov_server_addr|The variable to fill with server address|
|uuid_128 *|[out]|remote_prov_uuid|The variable to fill with unprovisioned node uuid|
|uint16_t *|[out]|remote_prov_oob_capabilities|The variable to fill with unprovisioned node OOB capability bitmask|

Get remote provisioning server address and unprovisioned node uuid from UI

##### Macros

`#define REMOTE_PROV_OPTLENGTH 4`

**Description**: Optstring argument for getopt.

`#define REMOTE_PROV_OPTSTRING "a:mo:v:"`

**Description**: Optstring argument for getopt.

`#define REMOTE_PROV_USAGE `

**Description**: Usage info.

`#define REMOTE_PROV_OPTIONS `

`#define CBP_OPTLENGTH 0`

`#define CBP_OPTSTRING `

`#define CBP_USAGE `

`#define CBP_OPTIONS `

`#define LONG_OPT_SIZE PROV_OPTLENGTH + REMOTE_PROV_OPTLENGTH + CBP_OPTLENGTH + LAST_OPTION_ELEMENT`

`#define OPTSTRING NCP_HOST_OPTSTRING PROV_OPTSTRINGREMOTE_PROV_OPTSTRING CBP_OPTSTRING "h"`

`#define USAGE "\n%s " NCP_HOST_USAGE PROV_USAGEREMOTE_PROV_USAGECBP_USAGE " [-h]\n"`

`#define OPTIONS `

#### BT Mesh Provisioner CBP Application Component

BT Mesh Provisioner CBP (Certificate-Based Provisioning) Application component provides certificate-based provisioning functionality for Bluetooth Mesh networks. 

##### Macros

`#define CBP_OPTLENGTH 1`

`#define CBP_OPTSTRING "c"`

`#define CBP_USAGE   " [--cbp]"`

**Description**: Usage info.

`#define CBP_OPTIONS `

#### NCP Host BT Mesh Component

NCP Host component with threading support for Bluetooth Mesh applications. This component provides host-side NCP (Network Co-Processor) functionality for Bluetooth Mesh.

#### BT Mesh Provisioner Application Component

BT Mesh Provisioner Application component provides application-level functionality for provisioning devices into a Bluetooth Mesh network. 

##### Enumerations

###### prov_mode_t

```
enum prov_mode_t {
    PROV_CMD_LINE_MODE
    PROV_UI_MODE
}
```

**Description:**

Current provisioner mode, either single run command line mode or ui, menu mode.

**Enumerator:**

|   |   |
|---|---|
|PROV_CMD_LINE_MODE||
|PROV_UI_MODE||

##### Functions

###### btmesh_app_prov_init

`sl_status_t btmesh_app_prov_init(int opt, char *optarg)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|opt|Command option|
|char *|[in]|optarg|Command argument|

Provisioner Command Line Application Init

###### btmesh_app_prov_process_action

`void btmesh_app_prov_process_action(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Provisioner Application Process Action 

###### btmesh_app_prov_on_event

`void btmesh_app_prov_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Event coming from the Bluetooth Mesh stack|

Bluetooth Mesh stack event handler

###### btmesh_app_prov_get_command

`void btmesh_app_prov_get_command(command_t *prov_command, command_state_t *prov_command_state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|command_t *|[out]|prov_command|Current command|
|command_state_t *|[out]|prov_command_state|Current command status|

Get the provisioner command and command status

###### btmesh_app_prov_set_command

`void btmesh_app_prov_set_command(command_t prov_command)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|command_t|[in]|prov_command|New command|

Set the provisioner command

###### btmesh_app_prov_set_command_state

`void btmesh_app_prov_set_command_state(command_state_t prov_command_state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|command_state_t|[out]|prov_command_state|New command status|

Set the provisioner command status

###### btmesh_app_prov_get_cmd_options

`void btmesh_app_prov_get_cmd_options(struct option **prov_options)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|struct option **|[out]|prov_options|Options struct array address|

Get the command options struct array address

###### btmesh_cbp_prov_get_cmd_options

`void btmesh_cbp_prov_get_cmd_options(struct option **prov_options)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|struct option **|[out]|prov_options|Options struct array address|

Get the command options struct array address for CBP

###### btmesh_app_prov_handle_ui

`void btmesh_app_prov_handle_ui(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Handle the main menu in UI mode 

###### btmesh_app_prov_get_uuid_from_unprov_list

`bool btmesh_app_prov_get_uuid_from_unprov_list(uuid_128 *command_uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128 *|[out]|command_uuid|The variable to fill with the parsed data|

Get UUID from UI for provisioning

###### btmesh_app_prov_get_uuid_from_prov_list

`bool btmesh_app_prov_get_uuid_from_prov_list(uuid_128 *command_uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128 *|[out]|command_uuid|The variable to fill with UUID|

Get UUID from UI from rovisioned node list

###### btmesh_app_prov_get_ddb_status

`bool btmesh_app_prov_get_ddb_status(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get ddb status after startup

###### btmesh_app_prov_set_mode

`void btmesh_app_prov_set_mode(prov_mode_t prov_mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[prov_mode_t](btmesh-host-app-prov#prov-mode-t)|[in]|prov_mode|New provisioner mode|

Set provisioner mode, command line or ui mode

###### btmesh_app_prov_get_mode

`prov_mode_t btmesh_app_prov_get_mode(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get provisioner mode command line or menu UI mode

###### btmesh_app_prov_on_nodeinfo_end

`void btmesh_app_prov_on_nodeinfo_end(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Callback to inform when the nodeinfo query ends 

###### btmesh_app_prov_end_of_cmd

`void btmesh_app_prov_end_of_cmd(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Callback to inform when the command ends 

###### btmesh_app_prov_append_uuid

`void btmesh_app_prov_append_uuid(uuid_128 *uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128 *|[in]|uuid|Pointer to the UUID|

Helper script to print a given UUID

###### btmesh_app_prov_get_networks_number

`uint16_t btmesh_app_prov_get_networks_number(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get ddb status after startup

###### btmesh_app_prov_handle_cbp

`void btmesh_app_prov_handle_cbp(uint16_t netkey_index, uuid_128 uuid, bd_addr mac_address, uint8_t bearer_type)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|uuid_128|[in]|uuid|UUID of the device to be provisioned|
|bd_addr|[in]|mac_address|MAC address of the device to be provisioned|
|uint8_t|[in]|bearer_type|Type of the provisioning bearer layer. Can be PB-ADV (0) or PB-GATT (1).|

Handle certificate-based provisioning

###### btmesh_app_prov_set_cbp_capability

`void btmesh_app_prov_set_cbp_capability(bool capability)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|capability|true if the node is CBP-capable, false otherwise|

Inform the CBP handler if the provisioned node is capable of CBP or not

###### btmesh_app_prov_get_cbp_status

`bool btmesh_app_prov_get_cbp_status(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get current CBP status from the CBP handler

###### btmesh_app_prov_set_oob_capability

`void btmesh_app_prov_set_oob_capability(bool capability)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|capability|true if the node is OOB-capable, false otherwise|

Inform the OOB handler if the provisioned node is capable of OOB or not

###### btmesh_app_prov_get_oob_status

`bool btmesh_app_prov_get_oob_status(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get current OOB status from the OOB handler

##### Macros

`#define PROV_OPTLENGTH 8`

**Description**: Optstring argument for getopt.

`#define BTMESH_APP_PROV_NCP_ADDRESS 0x2001`

**Description**: NCP node address.

`#define LAST_OPTION_ELEMENT 1`

**Description**: Array terminate element length.

`#define PROV_OPTSTRING "ei:lp:k:x:r:s"`

**Description**: Optstring argument for getopt.

`#define PROV_USAGE `

**Description**: Usage info.

`#define PROV_OPTIONS `

#### BT Mesh Remote Provisioner Component

BT Mesh Remote Provisioner component provides functionality for remote provisioning of devices into a Bluetooth Mesh network.

#### BT Mesh Provisioner UI Application Component

BT Mesh Provisioner UI Application component provides user interface functionality for provisioning applications in Bluetooth Mesh networks. 

##### Enumerations

###### ui_state_e

```
enum ui_state_e {
    UI_MENU
    UI_WAITING_FOR_CMD
    UI_CMD_PROCESSING
    UI_WAITING_FOR_INPUT
    UI_EXIT
}
```

**Description:**

UI state.

**Enumerator:**

|   |   |
|---|---|
|UI_MENU||
|UI_WAITING_FOR_CMD||
|UI_CMD_PROCESSING||
|UI_WAITING_FOR_INPUT||
|UI_EXIT||

##### Typedefs

###### sl_ui_state

`typedef enum ui_state_e sl_ui_state`

**Description:**

UI state.

##### Functions

###### btmesh_app_prov_ui_handle_remote_prov_cmd

`sl_status_t btmesh_app_prov_ui_handle_remote_prov_cmd(char cmd_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char|[in]|cmd_id|Command id|

Remote provisioning related command handler

###### btmesh_app_prov_ui_get_ui_state

`sl_ui_state btmesh_app_prov_ui_get_ui_state(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get UI state

###### btmesh_app_prov_ui_get_input_buffer

`bool btmesh_app_prov_ui_get_input_buffer(char **ui_input_buffer)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char **|[out]|ui_input_buffer|data read from input console|

Get buffer with input console content

##### Macros

`#define EXIT_COMMAND 'q'`

`#define SCAN_COMMAND 's'`

`#define PROVISION_COMMAND 'p'`

`#define NODELIST_COMMAND 'l'`

`#define NODEINFO_COMMAND 'i'`

`#define REMOVE_NODE_COMMAND 'r'`

`#define KEY_REFRESH_COMMAND 'k'`

`#define KEY_EXPORT_COMMAND 'x'`

`#define RESET_COMMAND 'e'`

`#define PROV_UI_MENU `

#### BT Mesh Remote Provisioner UI Application Component

BT Mesh Remote Provisioner UI Application component provides user interface functionality for remote provisioning applications in Bluetooth Mesh networks. 

##### Macros

`#define REMOTE_SERVERLIST_COMMAND 'm'`

`#define REMOTE_SCAN_COMMAND 'o'`

`#define REMOTE_PROVISION_COMMAND 'v'`

`#define PROV_UI_MENU `

#### BT Mesh Provisioner Component

BT Mesh Provisioner component provides functionality for provisioning devices into a Bluetooth Mesh network. 

##### Functions

###### btmesh_prov_on_event

`void btmesh_prov_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Received BT Mesh event|

Provisioner Process Action.

###### btmesh_prov_start_scanning

`sl_status_t btmesh_prov_start_scanning(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Start scanning for unprovisioned beaconing nodes

**Returns**

- Status of the scan.

**Return values**

- SL_STATUS_OK: if scan started successfully. Error value otherwise.

###### btmesh_prov_stop_scanning

`sl_status_t btmesh_prov_stop_scanning(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Stop scanning of unprovisioned beaconing nodes

**Returns**

- Status of the scan.

**Return values**

- SL_STATUS_OK: if scan stopped successfully. Error value otherwise.

###### btmesh_prov_setup_provisioning

`sl_status_t btmesh_prov_setup_provisioning(uint16_t netkey_index, uuid_128 uuid, uint8_t bearer_type, uint8_t attention_timer_sec)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|uuid_128|[in]|uuid|UUID of the node|
|uint8_t|[in]|bearer_type|Provisioning bearer type. Either PB-ADV or PB-GATT|
|uint8_t|[in]|attention_timer_sec|Attention timer value in seconds|

Setup provisioning

**Returns**

- Status of the provisioning.

**Return values**

- SL_STATUS_OK: If provisioning is set up successfully. Error code otherwise.

###### btmesh_prov_provision_adv_device

`sl_status_t btmesh_prov_provision_adv_device(uint16_t netkey_index, uuid_128 uuid, bd_addr mac_address, uint8_t bearer_type, uint8_t attention_timer_sec)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|uuid_128|[in]|uuid|UUID of the node|
|bd_addr|[in]|mac_address|Bluetooth address of the node|
|uint8_t|[in]|bearer_type|Provisioning bearer type. Either PB-ADV or PB-GATT|
|uint8_t|[in]|attention_timer_sec|Attention timer value in seconds|

Provision device into network

**Returns**

- Status of the provisioning.

**Return values**

- SL_STATUS_OK: If provisioning is **started** successfully. Error code otherwise.

###### btmesh_prov_get_unprov_uuid_by_id

`sl_status_t btmesh_prov_get_unprov_uuid_by_id(uint16_t id, uuid_128 *uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|id|ID for which the UUID was requested|
|uuid_128 *|[out]|uuid|UUID of the node|

Get UUID based on the ID of an unprovisioned node

**Returns**

- Status of the provisioning.

**Return values**

- SL_STATUS_OK: If the ID is valid and the related UUID was copied to the output parameter Error code otherwise.

###### btmesh_prov_get_prov_uuid_by_id

`sl_status_t btmesh_prov_get_prov_uuid_by_id(uint16_t id, uuid_128 *uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|id|ID for which the UUID was requested|
|uuid_128 *|[out]|uuid|UUID of the node|

Get UUID based on the ID of a provisioned node

**Returns**

- Status of the provisioning.

**Return values**

- SL_STATUS_OK: If the ID is valid and the related UUID was copied to the output parameter Error code otherwise.

###### btmesh_prov_get_prov_uuid_by_address

`sl_status_t btmesh_prov_get_prov_uuid_by_address(uint16_t primary_address, uuid_128 *uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|primary_address|primary address for which UUID was requested|
|uuid_128 *|[out]|uuid|UUID of the node|

Get UUID based on the primary address of a node

**Returns**

- Status of the provisioning.

**Return values**

- SL_STATUS_OK: If the address is valid and the related UUID was copied to the output parameter Error code otherwise.

###### btmesh_prov_remove_node_by_uuid

`sl_status_t btmesh_prov_remove_node_by_uuid(uuid_128 uuid, btmesh_conf_on_job_notification_t on_job_notification)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the node|
|[btmesh_conf_on_job_notification_t](btmesh-conf-job#btmesh-conf-on-job-notification-t)|[in]|on_job_notification|Job status notification callback|

Remove a node from a network by UUID

**Returns**

- Status of the node removal.

**Return values**

- SL_STATUS_OK: if node removal **started** successfully. Error code otherwise.

Node removal success or failure is reported in on_job_notification callback. 

###### btmesh_prov_list_unprovisioned_nodes

`sl_status_t btmesh_prov_list_unprovisioned_nodes(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

List all unprovisioned nodes found in a previous scan

**Returns**

- Status of the command.

**Return values**

- SL_STATUS_OK: If all known nodes are listed.
- SL_STATUS_EMPTY: If no unprovisioned nodes are known.

###### btmesh_prov_list_provisioned_nodes

`sl_status_t btmesh_prov_list_provisioned_nodes(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

List all provisioned nodes present

**Returns**

- Status of the command.

**Return values**

- SL_STATUS_OK: If all known nodes are listed.
- SL_STATUS_EMPTY: If no provisioned nodes are known.

###### btmesh_prov_list_ddb_entries

`sl_status_t btmesh_prov_list_ddb_entries(uint16_t *count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|count|Number of nodes in the DDB|

List all entries in the device database of the provisioner node

**Returns**

- Status of the list command.

**Return values**

- SL_STATUS_OK: If the listing started successfully. Error code otherwise.

The provisioner will trigger **count** sl_btmesh_evt_prov_ddb_list events. 

###### btmesh_prov_delete_ddb_entry

`sl_status_t btmesh_prov_delete_ddb_entry(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the node to be deleted|

Delete a node from the device database of the provisioner node

**Returns**

- Status of the command.

**Return values**

- SL_STATUS_OK: If deletion started successfully. Error code otherwise.

The provisioner will trigger an sl_btmesh_evt_prov_delete_ddb_entry_complete event when the deletion is finished. 

###### btmesh_prov_create_appkey

`sl_status_t btmesh_prov_create_appkey(uint16_t netkey_index, uint16_t appkey_index, size_t key_len, const uint8_t *key, size_t max_application_key_size, size_t *application_key_len, uint8_t *application_key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network.|
|uint16_t|[in]|appkey_index|Appkey index to use.|
|size_t|[in]|key_len|Length of the appkey data.|
|const uint8_t *|[in]|key|Key value to use. Set to zero-length to generate random key.|
|size_t|[in]|max_application_key_size|Size of output buffer passed in application_key.|
|size_t *|[out]|application_key_len|The length of output data written to application_key.|
|uint8_t *|[out]|application_key|New application key. Ignore it if the result was non-zero.|

Create a new application key on the provisioner node

**Returns**

- Status of the key creation procedure.

**Return values**

- SL_STATUS_OK: If successful. Error code otherwise.

###### btmesh_prov_create_network

`sl_status_t btmesh_prov_create_network(uint16_t netkey_index, size_t key_len, const uint8_t *key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index to use.|
|size_t|[in]|key_len|Length of the netkey data.|
|const uint8_t *|[in]|key|Key value to use. Set to zero-length array to generate a random key.|

Create a new network on the provisioner node

**Returns**

- Status of the network creation.

**Return values**

- SL_STATUS_OK: If successful. Error code otherwise.

###### btmesh_prov_on_device_provisioned_evt

`void btmesh_prov_on_device_provisioned_evt(uint16_t address, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Primary element address of the node|
|uuid_128|[in]|uuid|UUID of the node|

Callback to inform the application that a new node was provisioned

###### btmesh_prov_on_provision_failed_evt

`void btmesh_prov_on_provision_failed_evt(uint8_t reason, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|reason|Reason of the failure|
|uuid_128|[in]|uuid|UUID of the node|

Callback to inform the application that a provisioning session failed

###### btmesh_prov_on_unprovisioned_node_list_evt

`void btmesh_prov_on_unprovisioned_node_list_evt(uint16_t id, uuid_128 uuid, uint16_t oob_capabilities)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|id|List ID of the node|
|uuid_128|[in]|uuid|UUID of the node|
|uint16_t|[in]|oob_capabilities|OOB capability bitmask|

Callback to inform the application of an unprovisioned node

###### btmesh_prov_on_provisioned_node_list_evt

`void btmesh_prov_on_provisioned_node_list_evt(uint16_t id, uuid_128 uuid, uint16_t primary_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|id|List ID of the node|
|uuid_128|[in]|uuid|UUID of the node|
|uint16_t|[in]|primary_address|Primary element address of the node|

Callback to inform the application of a provisioned node

###### btmesh_prov_on_ddb_list_ready

`void btmesh_prov_on_ddb_list_ready(uint16_t count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|count|Number of nodes in the DDB|

Callback to inform the application that the DDB list is ready

###### btmesh_prov_free_remote_serverlist

`void btmesh_prov_free_remote_serverlist(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Free remote provisioner internal server lists 

###### btmesh_prov_setup_cbp

`sl_status_t btmesh_prov_setup_cbp(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the device to be provisioned|

Setup certificate-based provisioning

**Returns**

- Status of the setup sequence

**Return values**

- SL_STATUS_OK: If successful Error code otherwise

###### btmesh_prov_setup_oob

`sl_status_t btmesh_prov_setup_oob(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the device to be provisioned|

Setup out-of-band provisioning

**Returns**

- Status of the setup sequence

**Return values**

- SL_STATUS_OK: If successful Error code otherwise

###### btmesh_prov_init_provisioning_records

`sl_status_t btmesh_prov_init_provisioning_records(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Wrapper for provisioning records initialization

**Returns**

- Status of the initialization sequence

###### btmesh_cbp_on_event

`void btmesh_cbp_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|The received event|

BT Mesh event handler for CBP

###### btmesh_oob_on_event

`void btmesh_oob_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|The received event|

BT Mesh event handler for OOB

##### Macros

`#define BTMESH_OOB_FLAG_CBP_CAPABLE 0x180`

#### BT Mesh Database Component

BT Mesh Database component provides database functionality for managing Bluetooth Mesh network information.

#### BT Mesh Configurator Component

BT Mesh Configurator component provides configuration functionality for managing Bluetooth Mesh network configuration.

#### BT Mesh Key Export Component

BT Mesh Key Export component provides functionality for exporting cryptographic keys from the Bluetooth Mesh network.

### Proprietary

This group includes components that implement proprietary features for Bluetooth Mesh networks. These components provide advanced functionalities, such as Advertisement Extension for faster data transfer and custom configuration models, which may deviate from standard Bluetooth Mesh specifications. They are designed for seamless integration into SOC and NCP applications and are primarily No-Code components. 

#### Modules

[Advertisement Extension Client](btmesh-ae-client)

[NCP Advertisement Extension Server](ncp-btmesh-ae-server)

[Advertisement Extension Server](btmesh-ae-server)

[NCP Advertisement Extension Client](ncp-btmesh-ae-client)

#### Advertisement Extension Client

Advertisement Extension Client component enables the Silabs Configuration Client vendor model for the node. Silabs Configuration Client can setup other nodes with Silabs Configuration Server Feature enabled (e.g. by the Advertisement Extension Server component). This is a proprietary feature which breaks compliance with AE in BT Mesh 1.1 specification. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_ae_client_on_event

`void sl_btmesh_ae_client_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle Advertisement Extension Client events.

This function is called automatically after enabling the component.

#### NCP Advertisement Extension Server

NCP Advertisement Extension Server component enables the Silabs Configuration Server vendor model for the node to allow data transfer over Advertisement Extension. This is a proprietary feature which breaks compliance with AE in BT Mesh 1.1 specification. Mesh data over Advertisement Extension can be used in message-heavy applications (e.g. Device Firmware Update) to speed up data transfer between nodes. All nodes must have the Silabs Configuration Server vendor model enabled, and a Silabs Configuration Client (enabled by e.g. the Advertisement Extension Client component) must configure the clients to use Advertisement Extension. This component is prepared for integration into NCP applications. This is a No-Code component.

#### Advertisement Extension Server

Advertisement Extension Server component enables the Silabs Configuration Server vendor model for the node to allow data transfer over Advertisement Extension. This is a proprietary feature which breaks compliance with AE in BT Mesh 1.1 specification. Mesh data over Advertisement Extension can be used in message-heavy applications (e.g. Device Firmware Update) to speed up data transfer between nodes. All nodes must have the Silabs Configuration Server vendor model enabled, and a Silabs Configuration Client (enabled by e.g. the Advertisement Extension Client component) must configure the clients to use Advertisement Extension. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_ae_server_on_event

`void sl_btmesh_ae_server_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle Advertisement Extension Server events.

This function is called automatically after enabling the component.

#### NCP Advertisement Extension Client

NCP Advertisement Extension Client component enables the Silabs Configuration Client vendor model for the node. Silabs Configuration Client can setup other nodes with Silabs Configuration Server Feature enabled (e.g. by the Advertisement Extension Server component). This is a proprietary feature which breaks compliance with AE in BT Mesh 1.1 specification. This component is prepared for integration into NCP applications. This is a No-Code component.

### Features

This group includes components that implement Bluetooth Mesh core features such as Friend, Low Power Node (LPN), and Proxy functionality. These components are designed for seamless integration into SOC applications and provide configurable options for runtime behavior. They are primarily No-Code components. 

#### Modules

[Low Power Node](btmesh-lpn)

[Friend](btmesh-friend)

[Proxy](btmesh-proxy)

#### Friend

Friend component enables Bluetooth Mesh Friend Feature for the node. Friend nodes are required when Low Power Nodes (LPN) are present in the mesh network. When a friendship is established between an LPN and Friend node, the friend node starts to store incoming messages targeted for the LPN. These mesages are forwarded to the LPN upon request. Logging for these messages can be enabled as a configuration option in Simplicity Studio. Callback functions are provided for friendship establishment and termination. Friend functionality can be enabled or disabled during runtime via node configuration. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_friend_feature_init

`void sl_btmesh_friend_feature_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize FRIEND functionality. This function is called automatically by the FRIEND component. 

###### sl_btmesh_friend_on_event

`void sl_btmesh_friend_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming friend event.|

Handling of mesh friend events.

###### sl_btmesh_friend_on_friendship_established

`void sl_btmesh_friend_on_friendship_established(uint16_t netkey_index, uint16_t lpn_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key used in friendship|
|uint16_t|[in]|lpn_address|Low Power Node address|

Called when the Friend Node establishes friendship with another node. This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_friend_on_friendship_terminated

`void sl_btmesh_friend_on_friendship_terminated(uint16_t netkey_index, uint16_t lpn_address, uint16_t reason)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Index of the network key used in friendship|
|uint16_t|[in]|lpn_address|Low Power Node address|
|uint16_t|[in]|reason|Reason for friendship termination|

Called when the friendship that was successfully established with a Low Power Node has been terminated. This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

#### Proxy

Proxy component enables Bluetooth Mesh Proxy Server Feature for the node. Proxy nodes send their messages over GATT and ADV bearers (GATT and Advertisement packages), which is mandatory if the provisioner is a mobile phone. Proxy functionality can be enabled or disabled during runtime via node configuration. This component is suitable for use in both NCP and SOC applications. This is a No-Code component.

#### Low Power Node

Low Power component enables Bluetooth Mesh Low Power Node (LPN) Feature for the node. LPNs consume less power by remaining in sleep for the majority of their operation cycle, waking up to poll incoming messages from a Friend Node. LPN operation can be achieved only by having an established friendship. Numerous timing and queue parameters can be configured in Simplicity Studio, more details can be found on the configuration panel or in sl_btmesh_lpn_config.h. Several callback functions, which can be implemented in the application, are available for initialization and friendship related events. More details about the functions can be found in sl_btmesh_lpn.h. LPN functionality can be enabled or disabled during runtime via node configuration. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Modules

[sl_btmesh_lpn_high_throughput_timer_s](sl-btmesh-lpn-high-throughput-timer-s)

##### Enumerations

###### sl_btmesh_lpn_high_throughput_operation_mode_t

```
enum sl_btmesh_lpn_high_throughput_operation_mode_t {
    SL_BTMESH_LPN_HIGH_THROUGHPUT_NORMAL
    SL_BTMESH_LPN_HIGH_THROUGHPUT_SLOWING
}
```

**Description:**

Operational modes for the high throughput timer.

**Enumerator:**

|   |   |
|---|---|
|SL_BTMESH_LPN_HIGH_THROUGHPUT_NORMAL|Normal, periodic operation with the provided value.|
|SL_BTMESH_LPN_HIGH_THROUGHPUT_SLOWING|Slows down over time, doubling its timeout after every expiration.|

##### Typedefs

###### sl_btmesh_lpn_high_throughput_timer_t

`typedef struct sl_btmesh_lpn_high_throughput_timer_s sl_btmesh_lpn_high_throughput_timer_t`

**Description:**

Handler structure for the high throughput timer.

##### Functions

###### sl_btmesh_lpn_feature_init

`void sl_btmesh_lpn_feature_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize LPN functionality. This function is called automatically by the LPN component. 

###### sl_btmesh_lpn_feature_deinit

`void sl_btmesh_lpn_feature_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize LPN functionality. This function is called automatically by the LPN component. 

###### sl_btmesh_lpn_is_friendship_active

`bool sl_btmesh_lpn_is_friendship_active(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Return if the friendship is active between LPN and friend node

**Returns**

- Friendship active state

**Return values**

- true: If friendship is active with a friend node
- false: If friendship is not established with any friend node

###### sl_btmesh_lpn_poll_request

`sl_status_t sl_btmesh_lpn_poll_request(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Poll the Friend node for stored messages and security updates

This command may be used if the application is expecting to receive messages at a specific time. However, it is not required for correct operation, because the procedure will be performed autonomously before the poll timeout expires.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_lpn_on_event

`void sl_btmesh_lpn_on_event(sl_btmesh_msg_t *pEvt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|pEvt|Pointer to incoming lpn event.|

Handling of mesh lpn events.

###### sl_btmesh_lpn_high_throughput_register

`sl_status_t sl_btmesh_lpn_high_throughput_register(sl_btmesh_lpn_high_throughput_timer_t *handle, uint32_t timeout, sl_btmesh_lpn_high_throughput_operation_mode_t mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_lpn_high_throughput_timer_t](btmesh-lpn#sl-btmesh-lpn-high-throughput-timer-t) *|[in]|handle|Pointer to the handler of the high throughput timer structure, provided by the user|
|uint32_t|[in]|timeout|The timeout of this timer, in milliseconds|
|[sl_btmesh_lpn_high_throughput_operation_mode_t](btmesh-lpn#sl-btmesh-lpn-high-throughput-operation-mode-t)|[in]|mode|The mode of operation|

Registers high throughput request

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: Timer successfully registered
- SL_STATUS_ALREADY_EXISTS: Timer is already present, list unchanged

###### sl_btmesh_lpn_high_throughput_unregister

`sl_status_t sl_btmesh_lpn_high_throughput_unregister(sl_btmesh_lpn_high_throughput_timer_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_lpn_high_throughput_timer_t](btmesh-lpn#sl-btmesh-lpn-high-throughput-timer-t) *|[in]|handle|Pointer to the handler to be unregistered|

Unregisters high throughput request

**Note**

- Will not stop the already running timer if it belongs to the handler passed.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: Timer successfully unregistered
- SL_STATUS_ALREADY_EXISTS: Timer was not present in the list

###### sl_btmesh_lpn_on_init

`void sl_btmesh_lpn_on_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Called when the Low Power Node is initialized.

This is a callback which can be implemented in the application. **Note**

- Do not call blocking api from here as during this call the btmesh resource guard is being used and it can lead to undefined behaviour. If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_lpn_on_deinit

`void sl_btmesh_lpn_on_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Called when the Low Power Node is deinitialized.

This is a callback which can be implemented in the application. **Note**

- Do not call blocking api from here as during this call the btmesh resource guard is being used and it can lead to undefined behaviour. If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_lpn_on_friendship_established

`void sl_btmesh_lpn_on_friendship_established(uint16_t friend_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|friend_address|Node address of the new friend|

Called when the Low Power Node establishes friendship with another node

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_lpn_on_friendship_failed

`void sl_btmesh_lpn_on_friendship_failed(uint16_t reason)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|reason|Reason for friendship establishment failure|

Called when the friendship establishment attempt of Low Power Node fails

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_lpn_on_friendship_terminated

`void sl_btmesh_lpn_on_friendship_terminated(uint16_t reason)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|reason|Reason for friendship termination|

Called when friendship that was successfully established has been terminated

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

Handler structure for the high throughput timer. 

###### Public Attributes

###### timeout (heading level 7)

```
uint32_t sl_btmesh_lpn_high_throughput_timer_s::timeout
```

**Description:** The timeout in milliseconds.

###### mode (heading level 7)

```
sl_btmesh_lpn_high_throughput_operation_mode_t sl_btmesh_lpn_high_throughput_timer_s::mode
```

**Description:** The operational mode.

###### next (heading level 7)

```
struct sl_btmesh_lpn_high_throughput_timer_s* sl_btmesh_lpn_high_throughput_timer_s::next
```

**Description:** Pointer to the next registered handler.

### Btmesh Roles

This group includes components that define and manage the roles of devices in a Bluetooth Mesh network. The components are designed for seamless integration into SOC applications and support both automatic and customizable role configurations. 

#### Modules

[Btmesh Custom Role](btmesh-custom-role)

[Btmesh Provisioner](btmesh-provisioner)

[Btmesh Provisionee](btmesh-provisionee)

#### Btmesh Custom Role

This component makes it possible to initialize a mesh device as a provisionee or provisioner based on application logic. For example an application could be implemented in a way that the device becomes a provisioner permanently when button is pressed at power up, otherwise it is just a provisionee. The sl_btmesh_custom_role_init weak callback function is called on boot event and the application is able to override this function to call one of the following initializer BT Mesh stack APIs: - sl_btmesh_node_init - sl_btmesh_node_init_oob - sl_btmesh_prov_init This component is prepared for integration into SOC applications. 

##### Functions

###### sl_bt_custom_role_on_event

`void sl_bt_custom_role_on_event(sl_bt_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_msg_t *|[in]|evt|Pointer to incoming event.|

Handle BLE events for the mesh custom role.

This function is called automatically after enabling the component.

###### sl_btmesh_custom_role_init

`void sl_btmesh_custom_role_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Called on boot event and the application is able to override this function to initialize the device as a provisioner or as a provisionee.

The application should call one of the following BT Mesh stack initializer APIs based on implementation-specific logic:

- sl_btmesh_node_init
- sl_btmesh_node_init_oob
- sl_btmesh_prov_init

This is a callback (weak function) which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function, and the application shall handle the sl_bt_evt_system_boot_id event by calling the mentioned APIs.

#### Btmesh Provisioner

This component automatically initializes the device as a provisioner on boot event. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_provisioner_on_init

`void sl_btmesh_provisioner_on_init(sl_status_t result)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_status_t|[in]|result|return value of the function call|

This function is called after the sl_btmesh_prov_init() function.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_bt_provisioner_on_event

`void sl_bt_provisioner_on_event(sl_bt_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_msg_t *|[in]|evt|Pointer to incoming event.|

Handle BLE events for the provisioner.

This function is called automatically after enabling the component.

#### Btmesh Provisionee

Btmesh Provisionee This component is prepared for integration into SOC applications. This component provides the following features:

- Automatic node initialization on boot event
- Automatic unprovisioned device beaconing on the selected bearers (PB-ADV, PB-GATT)
- Out-of-band authentication settings
- Helper functions for OOB authentication

This is a No-Code component. 

##### Functions

###### sl_btmesh_provisionee_on_init

`void sl_btmesh_provisionee_on_init(sl_status_t result)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_status_t|[in]|result|return value of the function call|

This function is called after the provisionee called the sl_btmesh_node_init() or the sl_btmesh_node_init_oob() function.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_provisionee_on_event

`void sl_btmesh_provisionee_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handle BT Mesh events for the provisionee.

This function is called automatically after enabling the component.

###### sl_bt_provisionee_on_event

`void sl_bt_provisionee_on_event(sl_bt_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_msg_t *|[in]|evt|Pointer to incoming event.|

Handle BLE events for the provisionee.

This function is called automatically after enabling the component.

### Time and Scenes

This group includes components that enable time tracking, scene management, and scheduling functionality in a Bluetooth Mesh network. These components support both client and server roles, allowing nodes to interact and manage time-based operations or scene transitions. They are designed for seamless integration into SOC applications and are primarily No-Code components. 

#### Modules

[Scheduler Server](btmesh-scheduler-server)

[Scene Client](btmesh-scene-client)

[Time Server](btmesh-time-server)

[Scene Server](btmesh-scene-server)

#### Scheduler Server

Used to support the control and reporting functionality of a node that can store a schedule. It has a corresponding Scheduler Setup Server model which is present in the same element. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_scheduler_init

`sl_status_t sl_btmesh_scheduler_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Scheduler initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed. This function is called automatically after enabling the component.

**Returns**

- Status of the initialization operation. Returns SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_scheduler_server_on_event

`void sl_btmesh_scheduler_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming time event.|

Handling of mesh scheduler events.

This function is called automatically after enabling the component.

#### Scene Client

Used to support the functionality of a node that can configure scenes on a network and trigger a state transition to a scene on another node. This component provides a function to recall a scene identified by its number. This component is prepared for integration into SOC applications. This is a No-Code component, if it is used with other compatible software components (eg.: CTL client). 

##### Functions

###### sl_btmesh_select_scene

`void sl_btmesh_select_scene(uint8_t scene_to_recall)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|scene_to_recall|Scene to recall, possible values 1-255.|

This function select scene and send it to the server.

###### sl_btmesh_handle_scene_client_on_event

`void sl_btmesh_handle_scene_client_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handle Sensor Server events.

This function is called automatically after enabling the component.

#### Time Server

Used to support the control and reporting functionality of a node that tracks time. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_scenes_init

`sl_status_t sl_btmesh_scenes_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Scenes initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed. This function is called automatically after enabling the component.

**Returns**

- Status of the initialization operation. Returns SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_time_server_on_event

`void sl_btmesh_time_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming time event.|

Handling of mesh time events. It handles:

- time_server_time_updated
- time_server_time_zone_offset_updated
- time_server_tai_utc_delta_updated
- time_server_time_role_updated

This function is called automatically after enabling the component.

#### Scene Server

Used to support the control and reporting functionality of a node that can participate in a scene. This component is prepared for integration into SOC applications. This is a No-Code component, if it is used with other compatible software components (eg.: CTL server). 

##### Functions

###### sl_btmesh_scenes_init

`sl_status_t sl_btmesh_scenes_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Scenes initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed. This function is called automatically after enabling the component.

**Returns**

- Status of the initialization operation. Returns SL_STATUS_OK (0) if successful. Error code otherwise.

###### sl_btmesh_scene_server_on_event

`void sl_btmesh_scene_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming scene server event.|

Handling of mesh scene events.

This function is called automatically after enabling the component.

### Utility

This group includes components that provide various utility functions and modules to enhance the functionality and usability of Bluetooth Mesh applications. These components are designed for seamless integration into SOC and NCP applications and offer both No-Code and Low-Code implementations for recurring tasks such as event logging, factory reset, provisioning, and sensor simulation. 

#### Modules

[Self Provisioning CLI](btmesh-self-provisioning-cli)

[Provisioning Decorator](btmesh-provisioning-decorator)

[BLOB Storage](btmesh-blob-storage)

[Event Logging](btmesh-event-log)

[Power consumption mock sensor](btmesh-sensor-power-consumption)

[NCP DFU Utility](ncp-btmesh-dfu)

[NCP User Commands](ncp-btmesh-user-cmd)

[WSTK LCD Driver](btmesh-wstk-lcd)

[App Utility](app-btmesh-util)

[People Count Sensor](btmesh-sensor-people-count)

[Factory Reset](btmesh-factory-reset)

#### Self Provisioning CLI

The Self Provisioning CLI is an application-level software component that provides a self provisioning functionality trough CLI. The goal of this component is to provide this function for the users who want to run their devices directly in a Bluetooth Mesh network without using a provisioner. This component is mainly used for development and testing purposes and is not recommended to run on final products. This component is prepared for integration into SOC applications. This is a No-Code component.

#### Provisioning Decorator

The Provisioning Decorator is an application-level software module that ensures callbacks at main provisioning process steps. There are callbacks for initialization phase, for starting and successful finishing or for failed provisioning. A general callback for handling Provisioning Decorator events is also available. This component is prepared for integration into SOC applications. This is a No-Code component, it automatically handles retries after failed provisioning attempts. Additionally, the following weak callbacks can be implemented in Low-Code fashion to handle different stages of the provisioning process: - void [sl_btmesh_on_provision_init_status(bool provisioned, uint16_t address, uint32_t iv_index)](btmesh-provisioning-decorator#sl-btmesh-on-provision-init-status) - void [sl_btmesh_on_node_provisioning_started(uint16_t result)](btmesh-provisioning-decorator#sl-btmesh-on-node-provisioning-started) - void [sl_btmesh_on_node_provisioned(uint16_t address, uint32_t iv_index)](btmesh-provisioning-decorator#sl-btmesh-on-node-provisioned) - void [sl_btmesh_on_node_provisioning_failed(uint16_t result)](btmesh-provisioning-decorator#sl-btmesh-on-node-provisioning-failed)

##### Functions

###### sl_btmesh_on_provision_init_status

`void sl_btmesh_on_provision_init_status(bool provisioned, uint16_t address, uint32_t iv_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|provisioned|true: provisioned, false: unprovisioned|
|uint16_t|[in]|address|Unicast address of the primary element of the node. Ignored if unprovisioned.|
|uint32_t|[in]|iv_index|IV index for the first network of the node Ignored if unprovisioned.|

Callbacks Called at node initialization time to provide provisioning information

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_on_node_provisioning_started

`void sl_btmesh_on_node_provisioning_started(uint16_t result)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|result|Result code. 0: success, non-zero: error|

Called when the Provisioning starts

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_on_node_provisioned

`void sl_btmesh_on_node_provisioned(uint16_t address, uint32_t iv_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Unicast address of the primary element of the node. Ignored if unprovisioned.|
|uint32_t|[in]|iv_index|IV index for the first network of the node Ignored if unprovisioned.|

Called when the Provisioning finishes successfully

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_on_node_provisioning_failed

`void sl_btmesh_on_node_provisioning_failed(uint16_t result)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|result|Result code. 0: success, non-zero: error|

Called when the Provisioning fails

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_handle_provisioning_decorator_event

`void sl_btmesh_handle_provisioning_decorator_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to the event type|

Functions which are automatically called when the component is selected Handling of Provisioning Decorator stack events.

#### Event Logging

The Event Logging is an application-level software module that logs stack events. Its main purpose is to log application related stack events. Both Bluetooth LE and Bluetooth mesh events are handled by the Event Logging component. This component is suitable for use in both NCP and SOC applications. This is a No-Code component (UART communication can be enabled/disabled in the Platform/Board Control software component). 

##### Functions

###### sl_btmesh_log_btmesh_events

`void sl_btmesh_log_btmesh_events(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event|

Log Bluetooth mesh events 

###### sl_btmesh_log_bt_connection_events

`void sl_btmesh_log_bt_connection_events(sl_bt_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_msg_t *|[in]|evt|Pointer to incoming event|

Log Bluetooth LE connection events 

###### sl_btmesh_log_on_node_reset

`void sl_btmesh_log_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Component node reset handler.

#### Power consumption mock sensor

The power consumption mock sensor is an application-level software module that simulates power consumption measurements. This module provides interface for setting and getting the simulated power consumption. This component is prepared for integration into SOC applications. This is a No-Code component, if it is used with Sensor Server to broadcast power consumption data to sensor clients. 

##### Functions

###### sl_btmesh_set_power_consumption

`void sl_btmesh_set_power_consumption(energy32_t energy_usage)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|energy32_t|[in]|energy_usage|Power consumption value to set|

Set the power consumption value. It could be used to initialize the sensor.

###### sl_btmesh_get_power_consumption

`energy32_t sl_btmesh_get_power_consumption(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get the current power consumption value measured by sensor.

**Returns**

- Current value of power consumption.

#### NCP DFU Utility

Implements the Firmware Update Information Status message assembly, with provided interfaces for setting FWIDs and URIs with indexing. This component is prepared for integration into NCP applications. 

##### Functions

###### sl_btmesh_ncp_dfu_set_fwid

`sl_status_t sl_btmesh_ncp_dfu_set_fwid(uint8_t idx, uint8_t len, uint8_t *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|idx|Index of the FW|
|uint8_t|[in]|len|Length of the data|
|uint8_t *|[in]|data|Firmware ID data; containing CID and version information|

Sets the Firmware ID for the given index, as part of the FW information

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_PARAMETER: If length is less than 2 or greater than 108
- SL_STATUS_NO_MORE_RESOURCE: In case memory allocation error

###### sl_btmesh_ncp_dfu_set_uri

`sl_status_t sl_btmesh_ncp_dfu_set_uri(uint8_t idx, uint8_t type, uint8_t len, uint8_t *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|idx|Index of the FW|
|uint8_t|[in]|type|Type of the command; '0' erases and writes new URI, '1' appends to existing URI.|
|uint8_t|[in]|len|Length of the data|
|uint8_t *|[in]|data|The data to write or append|

Sets the URI for given index, as part of the FW information

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NO_MORE_RESOURCE: In case of memory allocation error
- SL_STATUS_INVALID_PARAMETER: In case the combined length of the URI is longer than 255 bytes

###### sl_btmesh_ncp_dfu_handle_cmd

`void sl_btmesh_ncp_dfu_handle_cmd(void *data, bool *cmd_handled)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void *|[in]|data|Pointer to the command.|
|bool *|[inout]|cmd_handled|Status of the command: true - cmd handled, no further interpretation is required false - cmd unhandled, interpretation is required|

User command (message_to_target) handler callback. Handles user defined commands received from NCP host.

**Note**

- If the value of the parameter 'cmd_handled' is false, the incoming command needs to be interpreted. If the command is recognized and handled, the 'cmd_handled' flag should be set to true. If the value of the 'cmd_handled' parameter is already true, the function will return without executing any further operations.

##### Macros

`#define USER_SUB_CMD_URI_ID_WRT '0'`

**Description**: User sub-command to write FW URI.

`#define USER_SUB_CMD_URI_ID_APP '1'`

**Description**: User sub-command to append to FW URI.

#### NCP User Commands

Demonstrates the communication between an NCP host and NCP target using BGAPI user messages, responses and events. Can be used as a starting point for creating custom commands or for testing purposes. 

##### Functions

###### sl_ncp_app_user_cmd_message_to_target_cb

`void sl_ncp_app_user_cmd_message_to_target_cb(void *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void *|[in]|data|Data received from NCP through UART.|

Application user command (message_to_target) handler callback.

Handle user defined commands received from NCP-host in application.

###### ncp_cmd_to_target_handler

`void ncp_cmd_to_target_handler(void *data, bool *cmd_handled)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void *|[in]|data|Pointer to the data received from NCP host|
|bool *|[out]|cmd_handled|Flag to indicate if the command is handled|

This function handles user defined commands received from NCP host.

#### WSTK LCD Driver

The WSTK LCD Driver is an application-level software module which implements an interface for WSTK board's LCD screen usage, ensuring the uniform display of BT Mesh specific values. The interface contains an initialization and a write function. The LCD initialization is executed automatically at startup. The write interface is used to write one specified line of text to the LCD. This component is prepared for integration into SOC applications. This is a No-code component (The LCD can be enabled/disabled in the Platform/Board Control software component). 

##### Enumerations

###### sl_btmesh_LCD_arrow

```
enum sl_btmesh_LCD_arrow {
    SL_BTMESH_LCD_LEFT_ARROW = 1 << 0
    SL_BTMESH_LCD_RIGHT_ARROW = 1 << 1
    SL_BTMESH_LCD_LEFT_RIGHT_ARROW = SL_BTMESH_LCD_LEFT_ARROW
                                   | SL_BTMESH_LCD_RIGHT_ARROW
}
```

**Description:**

Enumeration of possible arrows to be drawn.

**Enumerator:**

|   |   |
|---|---|
|SL_BTMESH_LCD_LEFT_ARROW|Left arrow.|
|SL_BTMESH_LCD_RIGHT_ARROW|Right arrow.|
|SL_BTMESH_LCD_LEFT_RIGHT_ARROW|Left arrow and right arrow.|

##### Functions

###### graphInit

`void graphInit(char *header)`

**Description:** Initialize graphics stack.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *|[in]|header|Header Text on display|

###### graphWriteString

`sl_status_t graphWriteString(char *string)`

**Description:** Display a string on the LCD center aligned.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *|[in]|string|String to be displayed|

**Returns**

- Status of the command.

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: In case of failure

###### graphDrawArrow

`sl_status_t graphDrawArrow(sl_btmesh_LCD_arrow arrow)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_LCD_arrow](btmesh-wstk-lcd#sl-btmesh-lcd-arrow)|[in]|arrow|Arrow to be drawn|

Draw arrows on the page.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: In case of failure

###### sl_btmesh_LCD_init

`sl_status_t sl_btmesh_LCD_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize LCD.

Called once at startup.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: If writing header failed

###### sl_btmesh_LCD_write

`sl_status_t sl_btmesh_LCD_write(const char *str, uint8_t row)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|str|Pointer to string which is displayed in the specified row.|
|uint8_t|[in]|row|Selects which line of LCD display is written, possible values are defined as LCD_ROW_xxx.|

This function is used to write one line on the LCD.

**Note**

- This uses [sl_btmesh_LCD_write_paged](btmesh-wstk-lcd#sl-btmesh-lcd-write-paged) to write onto page 0.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_PARAMETER: If row is invalid
- SL_STATUS_FAIL: If writing failed

###### sl_btmesh_LCD_write_paged

`sl_status_t sl_btmesh_LCD_write_paged(const char *str, uint8_t row, uint8_t page)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|str|Pointer to string which is displayed in the specified row.|
|uint8_t|[in]|row|Selects which line of LCD display is written, possible values are defined as LCD_ROW_xxx.|
|uint8_t|[in]|page|Page identifier. Zero-based.|

This function is used to write one line on the LCD onto the given page.

Pages are handled dynamically

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_PARAMETER: If row is invalid
- SL_STATUS_FAIL: If writing failed

###### sl_btmesh_LCD_select_page

`sl_status_t sl_btmesh_LCD_select_page(uint8_t page)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|page|Page index to display. Zero-based.|

Select page to be displayed and display it.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: If page refresh failed
- SL_STATUS_INVALID_INDEX: If page index is out of range

###### sl_btmesh_LCD_next_page

`sl_status_t sl_btmesh_LCD_next_page(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Select next page to be displayed and display it.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success, or last page is displayed
- SL_STATUS_FAIL: If page refresh failed

###### sl_btmesh_LCD_prev_page

`sl_status_t sl_btmesh_LCD_prev_page(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Select previous page to be displayed and display it.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success, or last page is displayed
- SL_STATUS_FAIL: If page refresh failed

###### sl_btmesh_LCD_remove_page

`sl_status_t sl_btmesh_LCD_remove_page(uint8_t page)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|page|Page index to remove. Zero-based.|

Remove page.

If currently displayed page is removed, display a valid one. If last page is removed, display the first one. If page is removed from before the currently displayed page refresh page so consistency is upheld.

Page 0 can't be removed.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_INDEX: If page is out of range or 0.
- SL_STATUS_FAIL: If page needed to be refreshed and was unsuccessful

###### sl_btmesh_LCD_clear_pages

`sl_status_t sl_btmesh_LCD_clear_pages(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Remove every page except the first.

Refreshes page.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: If page refresh is unsuccessful

##### Macros

`#define LCD_ROW_MAX 9`

**Description**: up to 9 rows available on screen

`#define LCD_ROW_LEN 22`

**Description**: up to 21 characters, plus line break each row

#### App Utility

The App BT Mesh Utility provides collection of stateless utility functions and macros to solve recurring tasks in the BT Mesh components and examples. This component supports logging of missing application key binding and missing model publication data configuration errors. The logging level of these errors are configurable. This component is suitable for use in both NCP and SOC applications. 

##### Functions

###### app_btmesh_nvm_init

`sl_status_t app_btmesh_nvm_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the NVM interface.

Calls the default initializer of NVM3.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_ALREADY_INITIALIZED: In case it was initialized earlier with parameters different from default

###### app_btmesh_nvm_read

`sl_status_t app_btmesh_nvm_read(uint16_t key, void *buf, size_t *len)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key|Identifier of the data.|
|void *|[out]|buf|Buffer to the data to read.|
|size_t *|[inout]|len|Pointer to the length of the read data. As in input it takes the length of buffer. As an output it contains the length of the read data.|

Reads data from NVM.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case NVM has not been initialized
- SL_STATUS_INVALID_KEY: In case key is invalid
- SL_STATUS_NOT_FOUND: In case key has not been found
- SL_STATUS_INVALID_PARAMETER: In case any of the input parameters is invalid

###### app_btmesh_nvm_write

`sl_status_t app_btmesh_nvm_write(uint16_t key, const void *buf, size_t len)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key|Identifier of the data.|
|const void *|[in]|buf|Buffer to the data to write.|
|size_t|[in]|len|Length of the data in the buffer.|

Writes data into the NVM.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case NVM has not been initialized
- SL_STATUS_FULL: In case NVM is full
- SL_STATUS_NO_MORE_RESOURCE: In case NVM doesn't have the resources to store the data
- SL_STATUS_FLASH_PROGRAM_FAILED: In case writing to NVM has failed
- SL_STATUS_INVALID_PARAMETER: In case any of the input parameters is invalid

###### app_btmesh_nvm_erase

`sl_status_t app_btmesh_nvm_erase(uint16_t key)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key|Identifier of the data.|

Erases data from NVM.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case NVM has not been initialized
- SL_STATUS_INVALID_KEY: In case key is invalid
- SL_STATUS_NOT_FOUND: In case key has not been found
- SL_STATUS_FLASH_PROGRAM_FAILED: In case writing to NVM has failed
- SL_STATUS_INVALID_PARAMETER: In case any of the input parameters is invalid

###### app_btmesh_nvm_erase_all

`sl_status_t app_btmesh_nvm_erase_all(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Erases all NVM data.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case NVM has not been initialized
- SL_STATUS_INVALID_PARAMETER: In case any of the input parameters is invalid

###### app_btmesh_uuid_64_to_string

`const char * app_btmesh_uuid_64_to_string(char *buffer, uint32_t buffer_size, const sl_bt_uuid_64_t *uuid_64, char separator, bool uppercase)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *|[out]|buffer|Output buffer where the string representation is written|
|uint32_t|[in]|buffer_size|Size of output buffer|
|const sl_bt_uuid_64_t *|[in]|uuid_64|Input UUID64 which shall be converted to string|
|char|[in]|separator|Separator character to be used between two hex characters. If the separator is the null character then no separator is used.|
|bool|[in]|uppercase|If true hex characters are upper case otherwise lower case|

Provides string representation of UUID64

It is guaranteed that this function returns a valid string even in case of invalid parameters.

**Returns**

- Output buffer which contains the string representation of UUID64

**Return values**

- INVALID: if an error occurs due to invalid parameters

###### app_btmesh_bytes_to_hex

`const char * app_btmesh_bytes_to_hex(char *buffer, uint32_t buffer_size, const uint8_t *bytes, uint32_t bytes_size, char separator, bool uppercase)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *|[out]|buffer|Output buffer where the hex representation is written|
|uint32_t|[in]|buffer_size|Size of output buffer|
|const uint8_t *|[in]|bytes|Input byte array which shall be converted to hex|
|uint32_t|[in]|bytes_size|Size of input byte array|
|char|[in]|separator|Separator character to be used between two hex characters. If the separator is the null character then no separator is used.|
|bool|[in]|uppercase|If true hex characters are upper case otherwise lower case|

Provides hex representation of byte array as a string

It is guaranteed that this function returns a valid string even in case of invalid parameters.

**Returns**

- Output buffer which contains the hex representation of byte array

**Return values**

- INVALID: if an error occurs due to invalid parameters

##### Macros

`#define app_btmesh_util_log_status_f (sc, ...)`

**Description**: Logs the btmesh API failures.

`#define APP_BTMESH_UTIL_COMPONENT_LOGGING `

**Description**: This macro calculates the number of precompile logging enable request in the specific c file where the this header file is included from

`#define log_nl ()`

`#define log (...)`

`#define log_level (level, ...)`

`#define log_debug (...)`

`#define log_info (...)`

`#define log_warning (...)`

`#define log_error (...)`

`#define log_critical (...)`

`#define log_append (...)`

`#define log_append_level (level, ...)`

`#define log_append_debug (...)`

`#define log_append_info (...)`

`#define log_append_warning (...)`

`#define log_append_error (...)`

`#define log_append_critical (...)`

`#define log_status_debug (sc)`

`#define log_status_info (sc)`

`#define log_status_warning (sc)`

`#define log_status_error (sc)`

`#define log_status_critical (sc)`

`#define log_status_debug_f (sc, ...)`

`#define log_status_info_f (sc, ...)`

`#define log_status_warning_f (sc, ...)`

`#define log_status_error_f (sc, ...)`

`#define log_status_critical_f (sc, ...)`

`#define log_status (sc)`

`#define log_status_level (level, sc)`

`#define log_status_f (sc, ...)`

`#define log_status_level_f (level, sc, ...)`

`#define log_btmesh_status_f (sc, ...)`

`#define log_hexdump_debug (p_data, len)`

`#define log_hexdump_info (p_data, len)`

`#define log_hexdump_warning (p_data, len)`

`#define log_hexdump_error (p_data, len)`

`#define log_hexdump_critical (p_data, len)`

`#define log_hexdump_level (level, p_data, len)`

`#define log_hexdump_debug_s (separator, p_data, len)`

`#define log_hexdump_info_s (separator, p_data, len)`

`#define log_hexdump_warning_s (separator, p_data, len)`

`#define log_hexdump_error_s (separator, p_data, len)`

`#define log_hexdump_critical_s (separator, p_data, len)`

`#define log_hexdump_level_s (level, separator, p_data, len)`

`#define APP_BTMESH_UUID_64_STR_MAX_SIZE 24`

**Description**: Maximum size of UUID64 string representation with separators (including null char)

`#define NL APP_LOG_NL`

`#define APP_BTMESH_UUID_64_TO_STRING (uuid_64, separator, uppercase)`

**Description**: Provides string representation of UUID64 in a compound literal

It is guaranteed that this macro returns a valid string even in case of invalid parameters.

**Warnings**

- This macro calls [app_btmesh_uuid_64_to_string](app-btmesh-util#app-btmesh-uuid-64-to-string) function with a compound literal which means the lifetime of returned string representation is the same as the enclosing block so the return value shall not be referenced outside of the most enclosing block where this macro is called from. For example the macro value shall not be returned from the caller function.

This macro can be used in printf-like calls (e.g. log calls) directly because it returns a string under every circumstances and the lifetime of compound literal is not problematic if the value is passed as a parameter directly to another function.

**Returns**

- String representation of UUID64 which has enclosing block lifetime

`#define SL_PROG_TO_PCT (_target, _progress)`

**Description**: Convert progress into percentage, based on target and current values

`#define SL_PROG_TO_PCT_INT (_target, _progress)`

**Description**: Convert progress into percentage, based on target and current values

`#define SL_ARRAY_LENGTH (array)`

**Description**: Calculates how many elements an array contains

`#define SLI_SILABS_CID_INT 0x02FF`

**Description**: Silicon Laboratories Company ID as integer

`#define SLI_SILABS_CID_STR_LE "\xFF\x02"`

**Description**: Silicon Laboratories Company ID as little-endian string

`#define SLI_SILABS_CID_STR_BE "\x02\xFF"`

**Description**: Silicon Laboratories Company ID as big-endian string

#### People Count Sensor

The People Count Sensor is an application-level software module that simulates a people count sensor behavior. Provides interface for setting and getting and also for increasing and decreasing the simulated people count value. This component is prepared for integration into SOC applications. This is a No-Code component, if it is used with Sensor Server to broadcast people count data to sensor clients. 

##### Functions

###### sl_btmesh_set_people_count

`void sl_btmesh_set_people_count(count16_t people_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|count16_t|[in]|people_count|People count value to set|

Set the people count value. It could be used to initialize the sensor.

###### sl_btmesh_get_people_count

`count16_t sl_btmesh_get_people_count(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get the current people count value measured by sensor.

**Returns**

- Current value of people count.

###### sl_btmesh_people_count_increase

`void sl_btmesh_people_count_increase(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Increase people count value by one. After exceeding the maximum value it set people count to value is not known. 

###### sl_btmesh_people_count_decrease

`void sl_btmesh_people_count_decrease(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Decrease people count value by one if value is known and greater than 0.

#### Factory Reset

The Factory Reset is an application-level software module that manages two types of device resets. The Factory Reset provides possibility for node reset and full reset. Node reset removes all the keys and other settings that have been configured for this node previously. Full reset removes all NVM data as well. Callback is available for both reset types. After callback execution the node reboots itself. After reboot in both reset cases the node enters to unprovisioned state. These interface functions are available also for CLI calls. This component is prepared for integration into SOC applications. This is a No-Code component, but it only handles incoming factory reset commands from other nodes by default. 

##### Functions

###### sl_btmesh_initiate_node_reset

`void sl_btmesh_initiate_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function is called to initiate node reset. 

###### sl_btmesh_initiate_full_reset

`void sl_btmesh_initiate_full_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function is called to initiate full reset. 

###### sl_btmesh_factory_reset_on_node_reset

`void sl_btmesh_factory_reset_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Called during the factory reset of the node. **Note**

- If no implementation is provided in the application then a default weak implementation if provided which is a no-operation. (empty function)

###### sl_btmesh_factory_reset_on_full_reset

`void sl_btmesh_factory_reset_on_full_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Called during the factory reset of the device. **Note**

- If no implementation is provided in the application then a default weak implementation if provided which is a no-operation. (empty function)

###### sl_btmesh_app_node_reset_handler

`void sl_btmesh_app_node_reset_handler(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function is called to clear nvm used by application components after node reset.

#### BLOB Storage

Provides an API for storing binary large objects (BLOB) via the bootloader. The number and size of the bootloader slots determines the number and maximum size of BLOBs that can be stored on the device. Please check the bootloader configuration. This component is prepared for integration into SOC applications. This is a No-Code component, if it is used with either BLOB transfer Client or Server components. 

##### Modules

[sl_btmesh_blob_storage_slot_metadata_cache_t](sl-btmesh-blob-storage-slot-metadata-cache-t)

##### Enumerations

###### sl_btmesh_blob_storage_status_e

```
enum sl_btmesh_blob_storage_status_e {
    SL_BTMESH_BLOB_STORAGE_STATUS_EMPTY
    SL_BTMESH_BLOB_STORAGE_STATUS_CORRUPTED
    SL_BTMESH_BLOB_STORAGE_STATUS_INVALIDATED
    SL_BTMESH_BLOB_STORAGE_STATUS_OCCUPIED
    SL_BTMESH_BLOB_STORAGE_STATUS_INTERNAL_ERROR
}
```

**Enumerator:**

|   |   |
|---|---|
|SL_BTMESH_BLOB_STORAGE_STATUS_EMPTY|Slot is empty.|
|SL_BTMESH_BLOB_STORAGE_STATUS_CORRUPTED|Slot data is corrupted

- Data present, but no footer
- Footer present, but no data
- Footer and data present, but one or more app footer metadata is corrupted or missing|
|SL_BTMESH_BLOB_STORAGE_STATUS_INVALIDATED|Slot has valid data but footer was invalidated by application.|
|SL_BTMESH_BLOB_STORAGE_STATUS_OCCUPIED|Slot has data and is valid.|
|SL_BTMESH_BLOB_STORAGE_STATUS_INTERNAL_ERROR|Internal API error.|

###### sl_btmesh_blob_storage_delete_state_e

```
enum sl_btmesh_blob_storage_delete_state_e {
    SL_BTMESH_BLOB_STORAGE_DELETE_INACTIVE
    SL_BTMESH_BLOB_STORAGE_DELETE_BUSY
    SL_BTMESH_BLOB_STORAGE_DELETE_FAILED
    SL_BTMESH_BLOB_STORAGE_DELETE_SUCCESS
}
```

**Enumerator:**

|   |   |
|---|---|
|SL_BTMESH_BLOB_STORAGE_DELETE_INACTIVE|Asynchronous delete inactive.|
|SL_BTMESH_BLOB_STORAGE_DELETE_BUSY|Asynchronous delete active and busy.|
|SL_BTMESH_BLOB_STORAGE_DELETE_FAILED|Asynchronous delete has failed.|
|SL_BTMESH_BLOB_STORAGE_DELETE_SUCCESS|Asynchronous delete has succeeded.|

##### Typedefs

###### sl_btmesh_blob_storage_status_t

`typedef enum sl_btmesh_blob_storage_status_e sl_btmesh_blob_storage_status_t`

###### sl_btmesh_blob_storage_delete_state_t

`typedef enum sl_btmesh_blob_storage_delete_state_e sl_btmesh_blob_storage_delete_state_t`

##### Functions

###### sl_btmesh_blob_storage_init

`void sl_btmesh_blob_storage_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the storage wrapper 

###### sl_btmesh_blob_storage_deinit

`void sl_btmesh_blob_storage_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitializes the storage wrapper 

###### sl_btmesh_blob_storage_read

`sl_status_t sl_btmesh_blob_storage_read(sl_bt_uuid_64_t const *blob_id, uint32_t offset, uint32_t *len, void *buffer)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|
|uint32_t|[in]|offset|Offset relative to BLOB start, where read should start|
|uint32_t *|[inout]|len|Length of the buffer; modified if there's less data then buffer could fit|
|void *|[out]|buffer|Buffer in which data is read|

Reads data from the identified BLOB into a buffer

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: In case BLOB isn't found
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_write_start

`sl_status_t sl_btmesh_blob_storage_write_start(sl_bt_uuid_64_t const *blob_id, uint32_t size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB about to be written into storage|
|uint32_t|[in]|size|Size of the BLOB about to be written into storage|

Starts writing procedure

Sets internal state variables to correspond to writing a BLOB. **Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_ALREADY_EXISTS: In case BLOB ID already exists in storage
- SL_STATUS_WOULD_OVERFLOW: In case BLOB is too big to fit
- SL_STATUS_NO_MORE_RESOURCE: In case no slot is available
- SL_STATUS_BUSY: In case BLOB Storage is processing an async. request

###### sl_btmesh_blob_storage_write

`sl_status_t sl_btmesh_blob_storage_write(uint32_t offset, uint32_t len, void *data)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|offset|Offset of the data inside the BLOB. Must be `SL_BTMESH_BLOB_STORAGE_ALIGNMENT_CFG_VAL` aligned.|
|uint32_t|[in]|len|Length of the data|
|void *|[in]|data|Pointer to the data|

Writes data into storage.

- [sl_btmesh_blob_storage_write_start](btmesh-blob-storage#sl-btmesh-blob-storage-write-start) must be called first.

**Returns**

- Result of write operation

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FLASH_WRITE_INHIBITED: In case of non-word aligned offset
- SL_STATUS_FLASH_PROGRAM_FAILED: In case storage programming failed

###### sl_btmesh_blob_storage_get_cache

`void sl_btmesh_blob_storage_get_cache(sl_btmesh_blob_storage_slot_metadata_cache_t const **cache, uint32_t *len)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_blob_storage_slot_metadata_cache_t](sl-btmesh-blob-storage-slot-metadata-cache-t) const **|[out]|cache|Pointer to the buffer of a pointer for cache start|
|uint32_t *|[out]|len|Pointer to the length cache|

Retrieves a pointer to the cache

###### sl_btmesh_blob_storage_any_blob_corrupted

`bool sl_btmesh_blob_storage_any_blob_corrupted(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Returns if any BLOB is corrupted

**Returns**

- 

**Return values**

- true: If at least one BLOB is corrupted
- false: If no BLOB is corrupted

###### sl_btmesh_blob_storage_verify

`sl_status_t sl_btmesh_blob_storage_verify(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Verifies the BLOB to be considered consistent

**Returns**

- Verification result

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case less data has been written than indicated with [sl_btmesh_blob_storage_write_start](btmesh-blob-storage#sl-btmesh-blob-storage-write-start) or writing has not been started properly
- SL_STATUS_FAIL: In case of internal API error
- SL_STATUS_FLASH_PROGRAM_FAILED: In case writing validity info into storage has failed

###### sl_btmesh_blob_storage_invalidate

`sl_status_t sl_btmesh_blob_storage_invalidate(sl_bt_uuid_64_t const *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB to invalidate|

Invalidates BLOB footer

**Returns**

- Result code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: In case BLOB identifier is not found
- SL_STATUS_FAIL: In case of internal API error
- SL_STATUS_FLASH_PROGRAM_FAILED: In case storage writing has failed
- SL_STATUS_BUSY: In case BLOB Storage is processing an async. request

###### sl_btmesh_blob_storage_invalidate_by_owner

`sl_status_t sl_btmesh_blob_storage_invalidate_by_owner(uint16_t owner_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|owner_id|Identifier of owner|

Invalidates all valid BLOB footer which belongs to a specific owner

**See Also**

- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Result code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: In case of internal API error
- SL_STATUS_FLASH_PROGRAM_FAILED: In case storage writing has failed
- SL_STATUS_BUSY: In case BLOB Storage is processing an async. request

###### sl_btmesh_blob_storage_invalidate_all

`sl_status_t sl_btmesh_blob_storage_invalidate_all(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Invalidates all valid BLOB footer

**Returns**

- Result code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FAIL: In case of internal API error
- SL_STATUS_FLASH_PROGRAM_FAILED: In case storage writing has failed
- SL_STATUS_BUSY: In case BLOB Storage is processing an async. request

###### sl_btmesh_blob_storage_delete

`sl_status_t sl_btmesh_blob_storage_delete(sl_bt_uuid_64_t const *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB to be deleted|

Deletes a BLOB from storage

**Returns**

- Result of erase

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: In case no BLOB has been identified in storage
- SL_STATUS_FLASH_ERASE_FAILED: In case erase has failed

###### sl_btmesh_blob_storage_delete_start

`sl_status_t sl_btmesh_blob_storage_delete_start(sl_bt_uuid_64_t const *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB to be deleted|

Start asynchronous delete of a BLOB

**See Also**

- [sl_btmesh_blob_storage_get_erase_error_code](btmesh-blob-storage#sl-btmesh-blob-storage-get-erase-error-code)

**Returns**

- Request status

**Return values**

- SL_BTMESH_OK: Request successful
- SL_BTMESH_BUSY: Erase handler busy

###### sl_btmesh_blob_storage_delete_managed_by_owner

`sl_status_t sl_btmesh_blob_storage_delete_managed_by_owner(uint16_t owner_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|owner_id|Identifier of owner|

Deletes all BLOB from storage which belongs to a specific owner

**See Also**

- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Result of erase

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: No managed slot was found which belongs to the owner
- SL_STATUS_FLASH_ERASE_FAILED: In case erase has failed

###### sl_btmesh_blob_storage_delete_managed_by_owner_start

`sl_status_t sl_btmesh_blob_storage_delete_managed_by_owner_start(uint16_t owner_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|owner_id|Identifier of owner|

Start asynchronous delete of BLOBs that are unmanaged

**See Also**

- [sl_btmesh_blob_storage_get_erase_error_code](btmesh-blob-storage#sl-btmesh-blob-storage-get-erase-error-code)
- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Request status

**Return values**

- SL_BTMESH_OK: Request successful
- SL_BTMESH_BUSY: Erase handler busy

###### sl_btmesh_blob_storage_delete_all

`sl_status_t sl_btmesh_blob_storage_delete_all(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deletes all BLOBs from storage

**Returns**

- Result of erase

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FLASH_ERASE_FAILED: In case erase has failed

###### sl_btmesh_blob_storage_delete_all_start

`sl_status_t sl_btmesh_blob_storage_delete_all_start(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Start asynchronous delete of all BLOBs

**See Also**

- [sl_btmesh_blob_storage_get_erase_error_code](btmesh-blob-storage#sl-btmesh-blob-storage-get-erase-error-code)

**Returns**

- Request status

**Return values**

- SL_BTMESH_OK: Request successful
- SL_BTMESH_BUSY: Erase handler busy

###### sl_btmesh_blob_storage_delete_invalid_slots

`sl_status_t sl_btmesh_blob_storage_delete_invalid_slots(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Clear slots with invalid data

**Returns**

- Result of erase

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: No invalid slot was found
- SL_STATUS_FLASH_ERASE_FAILED: In case erase has failed

###### sl_btmesh_blob_storage_delete_invalid_slots_start

`sl_status_t sl_btmesh_blob_storage_delete_invalid_slots_start(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Start asynchronous delete of invalid BLOBs

**See Also**

- [sl_btmesh_blob_storage_get_erase_error_code](btmesh-blob-storage#sl-btmesh-blob-storage-get-erase-error-code)

**Returns**

- Request status

**Return values**

- SL_BTMESH_OK: Request successful
- SL_BTMESH_BUSY: Erase handler busy

###### sl_btmesh_blob_storage_delete_unmanaged_slots

`sl_status_t sl_btmesh_blob_storage_delete_unmanaged_slots(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Clear slots that are unmanaged

**See Also**

- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Result of erase

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: No unmanaged slot was found
- SL_STATUS_FLASH_ERASE_FAILED: In case erase has failed

###### sl_btmesh_blob_storage_delete_unmanaged_slots_start

`sl_status_t sl_btmesh_blob_storage_delete_unmanaged_slots_start(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Start asynchronous delete of BLOBs that are unmanaged

**See Also**

- [sl_btmesh_blob_storage_get_erase_error_code](btmesh-blob-storage#sl-btmesh-blob-storage-get-erase-error-code)
- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Request status

**Return values**

- SL_BTMESH_OK: Request successful
- SL_BTMESH_BUSY: Erase handler busy

###### sl_btmesh_blob_storage_set_delete_separation_time

`sl_status_t sl_btmesh_blob_storage_set_delete_separation_time(uint16_t separation_time_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|separation_time_ms|Separation time between two async erase steps|

Set asynchronous delete separation time

Asynchronous delete separation time is measured in milliseconds between two asynchronous delete steps. The BLOB storage async delete is performed in multiple steps and each delete step blocks the code execution. If delete steps are executed too often then it could starve other timing sensitive SW components so delete separation time feature can be used to prevent this scenario.

**Returns**

- Request status

**Return values**

- SL_STATUS_OK: In case of success

###### sl_btmesh_blob_storage_is_present

`bool sl_btmesh_blob_storage_is_present(sl_bt_uuid_64_t const *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB inquired about|

Checks whether BLOB identified is present in storage

**Returns**

- Boolean value

**Return values**

- true: BLOB is present
- false: BLOB is not present

###### sl_btmesh_blob_storage_get_blob_size

`sl_status_t sl_btmesh_blob_storage_get_blob_size(sl_bt_uuid_64_t const *blob_id, uint32_t *blob_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB inquired about|
|uint32_t *|[out]|blob_size|Length of the BLOB|

Queries the BLOB size

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: In case no BLOB has been identified

###### sl_btmesh_blob_storage_calc_app_footer_size

`uint32_t sl_btmesh_blob_storage_calc_app_footer_size(uint16_t footer_data_length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|footer_data_length|Length of the application specific footer data|

Calculates the size of application specific footer on BLOB storage medium.

**Note**

- BLOB storage stores some additional metadata (id, length) with the footer data and it takes into consideration the alignment requirements of the underlying medium.

**Returns**

- Size of application specific footer on BLOB storage medium.

###### sl_btmesh_blob_storage_write_app_footer

`sl_status_t sl_btmesh_blob_storage_write_app_footer(sl_bt_uuid_64_t const *blob_id, void const *footer, uint16_t app_id, uint16_t length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|
|void const *|[in]|footer|Footer data|
|uint16_t|[in]|app_id|Identifier of the application data. Must be unique to the application layer user in the compiled software. Used to identify footer.|
|uint16_t|[in]|length|Length of the data|

Writes application specific footer into storage belonging to identified the BLOB and application

**Returns**

- Result of app footer write

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_PARAMETER: If app_id or length is invalid
- SL_STATUS_FLASH_PROGRAM_FAILED: In case write failed
- SL_STATUS_FULL: If there is no free space for app footer
- SL_STATUS_NOT_FOUND: If blob_id doesn't identify any footer
- SL_STATUS_INVALID_SIGNATURE: If any footer is corrupted during search for empty space to write new app footer
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_get_app_footer_length

`sl_status_t sl_btmesh_blob_storage_get_app_footer_length(sl_bt_uuid_64_t const *blob_id, uint16_t app_id, uint16_t *length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|
|uint16_t|[in]|app_id|Identifier of the application data|
|uint16_t *|[out]|length|Length of application data in case of success|

Queries footer information length assigned to a given BLOB, belonging to an application identifier.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of successful query
- SL_STATUS_NOT_FOUND: If app_id and blob_id don't identify a footer
- SL_STATUS_INVALID_SIGNATURE: In case of corrupted app footer metadata
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_get_app_footer

`sl_status_t sl_btmesh_blob_storage_get_app_footer(sl_bt_uuid_64_t const *blob_id, uint16_t app_id, void *buffer, uint16_t *length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|
|uint16_t|[in]|app_id|Identifier of the application data|
|void *|[out]|buffer|Pointer to footer buffer|
|uint16_t *|[inout]|length|Length of the buffer; contains the length of the data read in case of success|

Extracts footer information assigned to a given BLOB, belonging to an application identifier.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of successful reading
- SL_STATUS_NOT_FOUND: If app_id and blob_id don't identify a footer
- SL_STATUS_INVALID_SIGNATURE: In case of corrupted app footer metadata
- SL_STATUS_INVALID_PARAMETER: If buffer is too short
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_set_managed

`sl_status_t sl_btmesh_blob_storage_set_managed(sl_bt_uuid_64_t const *blob_id, uint16_t owner_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|
|uint16_t|[in]|owner_id|Identifier of owner which the BLOB belongs to|

Set BLOB to be managed, meaning it won't be deleted.

Each managed BLOB is managed by a specific owner which is stored with BLOB. Unmanaged BLOBs will be deleted when out of available space.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_FLASH_PROGRAM_FAILED: In case write failed
- SL_STATUS_FULL: If there is no free space to store owner_id
- SL_STATUS_NOT_FOUND: If blob_id doesn't identify any footer
- SL_STATUS_INVALID_SIGNATURE: If any footer is corrupted during search for empty space to write new app footer
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_is_managed

`bool sl_btmesh_blob_storage_is_managed(sl_bt_uuid_64_t const *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|

Check if BLOB is managed.

**See Also**

- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Boolean value

**Return values**

- true: BLOB is managed
- false: BLOB isn't managed or BLOB does not exist

###### sl_btmesh_blob_storage_is_managed_by_owner

`bool sl_btmesh_blob_storage_is_managed_by_owner(sl_bt_uuid_64_t const *blob_id, uint16_t owner_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *|[in]|blob_id|Identifier of the BLOB|
|uint16_t|[in]|owner_id|Identifier of expected owner|

Check if BLOB is managed by a specific owner.

**See Also**

- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Boolean value

**Return values**

- true: BLOB belongs to the specified owner
- false: BLOB belongs to another owner or BLOB is not managed or BLOB does not exist

###### sl_btmesh_blob_storage_get_managed_flag_size

`uint32_t sl_btmesh_blob_storage_get_managed_flag_size(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Return the size of managed flag on BLOB storage medium.

BLOB storage needs to distinguish managed and unmanaged BLOBs so it marks managed BLOBs as such which requires some space on the medium.

**Returns**

- Size of managed flag on BLOB storage medium

###### sl_btmesh_blob_storage_get_blob_id_by_owner

`sl_status_t sl_btmesh_blob_storage_get_blob_id_by_owner(uint16_t owner_id, uint32_t occurrence_idx, sl_bt_uuid_64_t *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|owner_id|Identifier of owner which the BLOB belongs to|
|uint32_t|[in]|occurrence_idx|Selects a BLOB from BLOBs managed by the same owner. Zero means the first BLOB with matching owner found during the search.|
|sl_bt_uuid_64_t *|[out]|blob_id|Identifier of the BLOB|

Searches BLOBs managed by a specific owner and provides the BLOB ID of the requested occurrence.

The search order for managed BLOBs of an owner is not specified but it is guaranteed that the order does not change unless new BLOB is added or an existing BLOB of the same owner is removed (delete, invalidate) from the BLOB storage.

When a managed BLOB belonging to an owner is removed from BLOB storage then occurrence_idx of BLOBs with same owner is decremented if the occurrence_idx of the BLOB was greater than the occurrence_idx of the removed BLOB otherwise the occurrence_idx does not change. In other words the BLOBs are shifted to lower indexes.

If a new managed BLOB is added by an owner to the BLOB storage then the search order of BLOBs with the same owner may change arbitrarily because it is not guaranteed which occurrence_idx the added BLOB is assigned to.

**See Also**

- [sl_btmesh_blob_storage_set_managed](btmesh-blob-storage#sl-btmesh-blob-storage-set-managed)

**Returns**

- Result of managed BLOB ID get operation

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: If no BLOBs are found with owner_id or the occurrence_idx is greater or equal to the number of BLOBs managed by owner
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_get_blob_id_by_footer

`sl_status_t sl_btmesh_blob_storage_get_blob_id_by_footer(uint16_t app_id, const void *expected_footer, uint16_t length, sl_bt_uuid_64_t *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|app_id|Identifier of the application data|
|const void *|[in]|expected_footer|Expected footer data for comparison|
|uint16_t|[in]|length|Length of the data|
|sl_bt_uuid_64_t *|[out]|blob_id|Identifier of the BLOB of the first match|

Searches for a specific app_id and data in the footer of each valid BLOB and returns the BLOB ID of the first match

**Returns**

- Result of footer based BLOB ID query (propagates other internal errors)

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_NOT_FOUND: If app_id is not found or the data is different
- SL_STATUS_FAIL: In case of internal API error

###### sl_btmesh_blob_storage_get_total_space

`uint32_t sl_btmesh_blob_storage_get_total_space(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Queries total space for BLOB data storage in bytes (used + empty)

**Returns**

- Total space in bytes

###### sl_btmesh_blob_storage_get_remaining_space

`uint32_t sl_btmesh_blob_storage_get_remaining_space(bool include_unmanaged_blobs)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|include_unmanaged_blobs|If true then unmanaged blobs are calculated into the remaining empty space.|

Queries remaining empty bytes in the BLOB storage

**Returns**

- Remaining empty bytes

###### sl_btmesh_blob_storage_get_max_blob_size

`uint32_t sl_btmesh_blob_storage_get_max_blob_size(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Queries maximum BLOB size which can be stored if the whole BLOB storage is empty

**Note**

- This might not be available even if one BLOB is stored

**Returns**

- Maximum BLOB size

###### sl_btmesh_blob_storage_get_max_blob_size_free

`uint32_t sl_btmesh_blob_storage_get_max_blob_size_free(bool include_unmanaged_blobs)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|include_unmanaged_blobs|If true then unmanaged blobs are calculated into the maximum free BLOB size.|

Queries maximum BLOB size which can be stored in the free space of BLOB storage

**Returns**

- Maximum supported BLOB size in free part of the BLOB storage

###### sl_btmesh_blob_storage_get_max_blob_count

`uint32_t sl_btmesh_blob_storage_get_max_blob_count(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Queries maximum number of BLOBs which can be stored

**Returns**

- Maximum number of BLOBs

###### sl_btmesh_blob_storage_get_alignment

`uint8_t sl_btmesh_blob_storage_get_alignment(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Queries the BLOB storage alignment

Writes to the BLOB storage must have an offset that is aligned to this value. Apart from the last write of a writing procedure, the length of the data must be a multiple of this value. The last write can be of any length.

**Returns**

- The BLOB storage alignment

###### sl_btmesh_blob_storage_get_erase_error_code

`sl_btmesh_blob_storage_delete_state_t sl_btmesh_blob_storage_get_erase_error_code(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Queries the error code/state of the asynchronous erase

**Returns**

- State of asynchronous erase

**Return values**

- SL_BTMESH_BLOB_STORAGE_DELETE_INACTIVE: If erase is inactive
- SL_BTMESH_BLOB_STORAGE_DELETE_BUSY: If erase is ongoing
- SL_BTMESH_BLOB_STORAGE_DELETE_FAILED: If erase has failed
- SL_BTMESH_BLOB_STORAGE_DELETE_SUCCESS: If erase is successful

###### sl_btmesh_blob_storage_delete_step_handle

`void sl_btmesh_blob_storage_delete_step_handle(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Handles the asynchronous erase state machine 

###### sl_btmesh_blob_storage_is_ok_to_sleep

`bool sl_btmesh_blob_storage_is_ok_to_sleep()`

Check if BLOB Storage allows the system to sleep

**Returns**

- If it is ok to sleep

**Return values**

- true: The system is allowed to sleep
- false: The system shall be kept awake

Asynchronous erase requires the device to stay awake to finish. 

###### sl_btmesh_blob_storage_calculate_checksum

`uint32_t sl_btmesh_blob_storage_calculate_checksum(const uint8_t *data, uint16_t length, uint32_t initial_value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|data|Pointer to the app footer data|
|uint16_t|[in]|length|Length of the app footer length|
|uint32_t|[in]|initial_value|Initial value for checksum calculation|

Called when app footer is written to BLOB storage to calculate the checksum over app footer data

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation calculates Berger code.

**Returns**

- Checksum calculated from app footer data

##### Macros

`#define BLOB_STORAGE_OWNER_ID_FW_DIST_SERVER 0x1000`

**Description**: Reserved BLOB Storage owner ID of FW Distribution Server.

`#define BLOB_STORAGE_APP_ID_DFU_FWID 0x1001`

**Description**: Reserved BLOB Storage app ID of Firmware ID (BT Mesh DFU)

`#define BLOB_STORAGE_APP_ID_DFU_METADATA 0x1002`

**Description**: Reserved BLOB Storage app ID of Metadata (BT Mesh DFU)

`#define BLOB_STORAGE_APP_ID_MANAGED_FLAG 0x8000`

**Description**: Reserved BLOB Storage app ID of managed flag.

Cached data about a certain slot. 

###### Public Attributes

###### blob_id (heading level 7)

```
sl_bt_uuid_64_t sl_btmesh_blob_storage_slot_metadata_cache_t::blob_id
```

**Description:** BLOB ID contained in the slot.

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_blob_storage_slot_metadata_cache_t::blob_size
```

**Description:** Size of the BLOB residing in the slot.

###### status (heading level 7)

```
sl_btmesh_blob_storage_status_t sl_btmesh_blob_storage_slot_metadata_cache_t::status
```

**Description:** Status of the slot (empty or otherwise)

### Lighting

This group includes components that provide control and reporting functionality for lighting in a Bluetooth Mesh network. These components support various lighting models such as Lightness, CTL (Color Tunable Lighting), and HSL (Hue, Saturation, Lightness). They are designed for seamless integration into SOC applications and offer both No-Code and Low-Code implementations for features like dimming, color temperature adjustment, and occupancy-based light control. 

#### Modules

[CTL Server](btmesh-ctl-server)

[Lightness Server](btmesh-lighting-server)

[HSL Server](btmesh-hsl-server)

[Lightness Client](btmesh-lighting-client)

[CTL Client](btmesh-ctl-client)

[LC Server](btmesh-lc-server)

#### CTL Server

Color Tunable Lighting (CTL) Server model. Used to support the control and reporting functionality of a node with a light source that is dimmable and whose color temperature can be selected. This component implements this control and reporting functionality, extending on lighting server, and also provides callbacks on lighting related events. For more details about lighting, please see Lighting Server. This component is prepared for integration into SOC applications. This is a Low-Code component. The following weak callbacks are available to implement the relevant light source handling: void sl_btmesh_lighting_level_pwm_cb(uint16_t level); void [sl_btmesh_lighting_color_pwm_cb(uint16_t color)](btmesh-ctl-server#sl-btmesh-lighting-color-pwm-cb); 

##### Functions

###### sl_btmesh_ctl_server_on_event

`void sl_btmesh_ctl_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handle CTL Server events.

This function is called automatically after enabling the component.

###### sl_btmesh_ctl_server_init

`void sl_btmesh_ctl_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

CTL Server initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed. This function is called automatically after enabling the component. 

###### sl_btmesh_ctl_server_on_node_reset

`void sl_btmesh_ctl_server_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Component node reset handler. Clearing component specific nvm content during node reset. This function is called automatically by Universal Configurator after enabling the component. 

###### sl_btmesh_get_temperature

`uint16_t sl_btmesh_get_temperature(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Function for retrieving actual temperature.

**Returns**

- Actual temperature level.

###### sl_btmesh_get_deltauv

`uint16_t sl_btmesh_get_deltauv(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Function for retrieving actual delta UV.

**Returns**

- Actual delta UV level.

###### sl_btmesh_ctl_set_temperature_deltauv_level

`void sl_btmesh_ctl_set_temperature_deltauv_level(uint16_t temperature, int16_t deltauv, uint32_t transition_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|temperature|Temperature of color.|
|int16_t|[in]|deltauv|Delta UV value.|
|uint32_t|[in]|transition_ms|Transition time in milliseconds.|

Set LED temperature and delta UV in given transition time.

###### sl_btmesh_ctl_server_snprint_deltauv

`int sl_btmesh_ctl_server_snprint_deltauv(char *buffer, uint16_t buffer_size, uint16_t deltauv_raw)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *|[out]|buffer|Character buffer where the formatted delta UV is stored|
|uint16_t|[in]|buffer_size|Size of the character buffer|
|uint16_t|[in]|deltauv_raw|Raw value of the Delta UV CTL parameter|

Utility function to print the delta UV raw value into the passed character buffer in the <sign>X.XX format.

**Returns**

- same as snprintf

###### sl_btmesh_lighting_color_pwm_cb

`void sl_btmesh_lighting_color_pwm_cb(uint16_t color)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|color|Desired light color PWM level.|

Callback for setting Light Color by PWM level (0x0001 - FFFE)

###### sl_btmesh_ctl_on_ui_update

`void sl_btmesh_ctl_on_ui_update(uint16_t temperature, uint16_t deltauv)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|temperature|Temperature of color.|
|uint16_t|[in]|deltauv|Delta UV value.|

Called when the UI shall be updated with the changed CTL Model state during a transition. The rate of this callback can be controlled by changing the SL_BTMESH_CTL_SERVER_UI_UPDATE_PERIOD_CFG_VAL macro.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

#### Lightness Server

Used to support the control and reporting functionality of a node with a light source that is dimmable. Lightness Server extends Generic Power OnOff Server model and Generic Level Server model. It also has a corresponding Lightness Setup Server model which is present in the same element. The component provides the reporting functions, and the possibility to set current, default, and last values of the lightness value. This component is prepared for integration into SOC applications. This is a Low-Code component. The following weak callback is available to implement the relevant light source handling: void sl_btmesh_lighting_level_pwm_cb(uint16_t level); 

##### Functions

###### sl_btmesh_lighting_set_level

`void sl_btmesh_lighting_set_level(uint16_t level, uint32_t transition_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|level||
|uint32_t|N/A|transition_ms||

###### sl_btmesh_set_state

`void sl_btmesh_set_state(int state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|N/A|state||

###### sl_btmesh_get_level

`uint16_t sl_btmesh_get_level(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

###### sl_btmesh_lighting_level_pwm_cb

`void sl_btmesh_lighting_level_pwm_cb(uint16_t level)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|level||

###### sl_btmesh_lighting_server_on_ui_update

`void sl_btmesh_lighting_server_on_ui_update(uint16_t lightness_level)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lightness_level|lightness level (0x0001 - FFFE)|

Called when the UI shall be updated with the changed state of lightning server during a transition. The rate of this callback can be controlled by changing the SL_BTMESH_LIGHTING_SERVER_UI_UPDATE_PERIOD_CFG_VAL macro.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_stop_transition_timer

`sl_status_t sl_btmesh_stop_transition_timer(void)`

**Description:** Stop the lighting level transition timer.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- Status code indicating success or error.

###### sl_btmesh_lighting_server_init

`void sl_btmesh_lighting_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Lighting Server initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed. This function is called automatically after enabling the component. 

###### sl_btmesh_lighting_server_on_event

`void sl_btmesh_lighting_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handling of mesh lighting server events.

This function is called automatically after enabling the component.

###### sl_btmesh_lighting_server_on_node_reset

`void sl_btmesh_lighting_server_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Handle node reset.

Function for clearing component specific nvm content during node reset. This function is called automatically by Universal Configurator after enabling the component. 

###### sl_btmesh_get_lightness_current

`uint16_t sl_btmesh_get_lightness_current(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get current lightness value

**Returns**

- Current lightness

###### sl_btmesh_set_lightness_current

`void sl_btmesh_set_lightness_current(uint16_t lightness)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lightness|Current lightness|

Set current lightness value

###### sl_btmesh_get_lightness_target

`uint16_t sl_btmesh_get_lightness_target(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get target lightness value

**Returns**

- Target lightness

###### sl_btmesh_set_lightness_target

`void sl_btmesh_set_lightness_target(uint16_t lightness)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lightness|Target lightness|

Set target lightness value

###### sl_btmesh_get_lightness_default

`uint16_t sl_btmesh_get_lightness_default(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get default lightness value

**Returns**

- Default lightness

###### sl_btmesh_set_lightness_default

`void sl_btmesh_set_lightness_default(uint16_t lightness)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lightness|Default lightness|

Set default lightness value

###### sl_btmesh_set_lightness_last

`void sl_btmesh_set_lightness_last(uint16_t lightness)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lightness|Last lightness|

Set last lightness value

###### sl_btmesh_get_default_transition_time

`uint32_t sl_btmesh_get_default_transition_time(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function converts mesh format of default transition time to milliseconds.

**Returns**

- Default transition time in milliseconds.

###### sl_btmesh_get_lightness_onpowerup

`uint8_t sl_btmesh_get_lightness_onpowerup(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get default lightness value on power up

**Returns**

- Default lightness on power up

###### sl_btmesh_update_lightness

`void sl_btmesh_update_lightness(uint16_t lightness, uint32_t remaining_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|lightness|Current lightness level within the transition|
|uint32_t|[in]|remaining_ms|Remaining transition time in milliseconds|

This function updates the lightness level in the mesh stack during a transition

###### pri_level_move_stop

`void pri_level_move_stop(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function stops generic level move on primary element. 

###### lightness_validate_and_correct

`uint16_t lightness_validate_and_correct(uint16_t)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|undefined|The input lightness value to validate and correct|

Checks whether the provided lightness value is within the allowed range for the lighting server. If the value is out of range, it will be corrected to the nearest valid value

**Returns**

- uint16_t The validated and possibly corrected lightness value

##### Macros

`#define LED_STATE_OFF 0`

**Description**: light off (both LEDs turned off)

`#define LED_STATE_ON 1`

**Description**: light on (both LEDs turned on)

`#define LED_STATE_PROV 2`

**Description**: provisioning (LEDs blinking)

#### HSL Server

sl_btmesh_hsl_server.h 

sl_btmesh_hsl_signal_transition_handler.h

Hue, Saturation and Lightness (HSL) Server model. Used to support the control and reporting functionality of a node with a light source that is dimmable and whose color can be selected. It extends Lightness Server and corresponds with HSL Hue Server and HSL Saturation Server models. It also has a corresponding HSL Setup Server model. This component implements callbacks, control, and report functionality. This component is prepared for integration into SOC applications. This is a Low-Code component. The following weak callbacks are available to implement the relevant light source handling: void sl_btmesh_hsl_hue_cb(uint16_t hue); void sl_btmesh_hsl_saturation_cb(uint16_t saturation);

##### License

**Copyright 2023 Silicon Laboratories Inc. www.silabs.com**

SPDX-License-Identifier: Zlib

The licensor of this software is Silicon Laboratories Inc.

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

##### License

**Copyright 2022 Silicon Laboratories Inc. www.silabs.com**

SPDX-License-Identifier: Zlib

The licensor of this software is Silicon Laboratories Inc.

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

##### Functions

###### sl_btmesh_hsl_server_on_event

`void sl_btmesh_hsl_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handle HSL Server events.

This function is called automatically after enabling the component.

###### sl_btmesh_hsl_server_init

`void sl_btmesh_hsl_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

HSL Server initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed. This function is called automatically after enabling the component. 

###### sl_btmesh_hsl_server_on_node_reset

`void sl_btmesh_hsl_server_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Component node reset handler. Clearing component specific nvm content during node reset. This function is called automatically by Universal Configurator after enabling the component. 

###### sl_btmesh_get_hue

`uint16_t sl_btmesh_get_hue(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Function for retrieving current hue.

**Returns**

- Current hue level.

###### sl_btmesh_get_saturation

`uint16_t sl_btmesh_get_saturation(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Function for retrieving current saturation.

**Returns**

- Current saturation level.

###### sl_btmesh_hsl_set_hue_level

`void sl_btmesh_hsl_set_hue_level(uint16_t hue, uint32_t transition_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|hue|Hue level.|
|uint32_t|[in]|transition_ms|Transition time in milliseconds.|

Set LED hue in given transition time.

###### sl_btmesh_hsl_set_saturation_level

`void sl_btmesh_hsl_set_saturation_level(uint16_t saturation, uint32_t transition_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|saturation|Saturation level.|
|uint32_t|[in]|transition_ms|Transition time in milliseconds.|

Set LED saturation in given transition time.

###### sl_btmesh_hsl_hue_cb

`void sl_btmesh_hsl_hue_cb(uint16_t hue)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|hue||

###### sl_btmesh_hsl_saturation_cb

`void sl_btmesh_hsl_saturation_cb(uint16_t saturation)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|saturation||

###### sl_btmesh_hsl_hue_on_ui_update

`void sl_btmesh_hsl_hue_on_ui_update(uint16_t hue)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|hue|Hue value.|

Called when the UI shall be updated with the changed HSL Model state during a transition. The rate of this callback can be controlled by changing the SL_BTMESH_HSL_SERVER_HUE_UI_UPDATE_PERIOD_CFG_VAL macro.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_hsl_saturation_on_ui_update

`void sl_btmesh_hsl_saturation_on_ui_update(uint16_t saturation)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|saturation|Saturation value.|

Called when the UI shall be updated with the changed HSL Model state during a transition. The rate of this callback can be controlled by changing the SL_BTMESH_HSL_SERVER_SATURATION_UI_UPDATE_PERIOD_CFG_VAL macro.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

#### Lightness Client

Used to support the functionality of a node that can set the dim level of a light source (Lightness Server) on another node. This component integrates the Generic OnOff Client functionality, for ease of use. It provides functions to change the dim value by, or set the dim value to a certain percentage, and a function for getting the current lightness level. This component is prepared for integration into SOC applications. This is a Low-Code component. For example, toggling all Light Lightness Servers in the network can be achieved by adding an event handler for mesh events and calling the following code: #include "sl_btmesh_lighting_client.h" void event_handler(sl_btmesh_msg_t *evt) { case sl_btmesh_evt_node_initialized_id: if (evt->data.evt_node_initialized.provisioned) { sl_btmesh_change_switch_position(SL_BTMESH_LIGHTING_CLIENT_TOGGLE); } break; } 

##### Functions

###### sl_btmesh_set_lightness

`void sl_btmesh_set_lightness(uint8_t new_lightness_percentage)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|new_lightness_percentage|Defines new lightness value as percentage Valid values 0-100 %|

This function change the lightness and send it to the server.

###### sl_btmesh_change_switch_position

`void sl_btmesh_change_switch_position(uint8_t position)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|position|Defines switch position change, possible values are:<br/><br/>- SL_BTMESH_LIGHTING_CLIENT_OFF<br/>- SL_BTMESH_LIGHTING_CLIENT_ON<br/>- SL_BTMESH_LIGHTING_CLIENT_TOGGLE|

This function change the switch position and send it to the server.

###### sl_btmesh_get_lightness

`uint16_t sl_btmesh_get_lightness(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get lightness.

This function returns actual lightness to set.

**Returns**

- Actual lightness value

##### Macros

`#define SL_BTMESH_LIGHTING_CLIENT_OFF 0`

**Description**: Set switch state to off.

`#define SL_BTMESH_LIGHTING_CLIENT_ON 1`

**Description**: Set switch state to on.

`#define SL_BTMESH_LIGHTING_CLIENT_TOGGLE 2`

**Description**: Toggle switch state.

#### CTL Client

Color Tunable Lighting (CTL) Client model. Used to set the dim level or the color temperature of a light source (CTL Server) on another node. This component extends the lighting client with functions to change the temperature by, or to change the temperature to a certain percentage. For more details about lighting please see Lighting Client. This component is prepared for integration into SOC applications. This is a Low-Code component. For example, changing all CTL Server nodes' color temperature by 1 percent can be achieved by adding an event handler for mesh events and calling the following code: #include "sl_btmesh_ctl_client.h" void event_handler(sl_btmesh_msg_t *evt) { case sl_btmesh_evt_node_initialized_id: if (evt->data.evt_node_initialized.provisioned) { sl_btmesh_change_temperature(1); } break; } 

##### Functions

###### sl_btmesh_ctl_client_set_temperature

`void sl_btmesh_ctl_client_set_temperature(uint8_t temperature_percent)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|temperature_percent|Defines new color temperature value as percentage Valid values 0-100 %|

This function changes the temperature and send it to the server.

###### sl_btmesh_ctl_client_set_lightness

`void sl_btmesh_ctl_client_set_lightness(uint8_t lightness_percent)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|lightness_percent|Defines new lightness value as percentage Valid values 0-100 %|

This function changes the lightness and send it to the server.

#### LC Server

Lightness Control (LC) Server model. Used to support the control and reporting functionality of a node with a light lightness controller that can monitor occupancy and ambient light level sensors and adjust the dim level of a light. LC Server extends Lightness Server model and Generic OnOff Server. It also has a corresponding LC Setup Server model which is present in the same element. This component is prepared for integration into SOC applications. This is a No-Code component when added to an existing project using Light Lightness Server. 

##### Functions

###### sl_btmesh_lc_init

`sl_status_t sl_btmesh_lc_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

LC initialization. This should be called at each boot if provisioning is already done. Otherwise this function should be called after provisioning is completed.

**Returns**

- Status of the initialization operation. Returns SL_STATUS_OK (0) if succeed, non-zero otherwise.

###### sl_btmesh_lc_get_mode

`uint8_t sl_btmesh_lc_get_mode(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function is getter for current light controller mode.

**Returns**

- current light controller mode

###### sl_btmesh_lc_server_on_event

`void sl_btmesh_lc_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handle LC Server events.

This function is called automatically after enabling the component.

###### sl_btmesh_lc_server_on_node_reset

`void sl_btmesh_lc_server_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Component node reset handler. Clearing component specific nvm content during node reset. This function is called automatically by Universal Configurator after enabling the component.

### Remote Provisioning

This group includes components that enable the provisioning of devices into a Bluetooth Mesh network remotely. These components support both client and server roles, allowing devices to interact over the mesh network to perform provisioning tasks. They are designed for seamless integration into SOC applications and are primarily No-Code components. 

#### Modules

[Remote Provisioning Client](btmesh-remote-provisioning-client)

[Remote Provisioning Server](btmesh-remote-provisioning-server)

#### Remote Provisioning Client

Used to support remote provisioning client functionality of provisioning devices into a mesh network by interacting with a mesh node that supports the Remote Provisioning Server model. This component is prepared for integration into SOC applications. This is a No-Code component.

#### Remote Provisioning Server

Used to support remote provisioning server functionality of provisioning a remote device over the mesh network and to perform the Node Provisioning Protocol Interface procedures. This component is prepared for integration into SOC applications. This is a No-Code component.

### NLC

This group includes components that implement the Network Lighting Control (NLC) profiles in Bluetooth Mesh networks. These components provide functionality for various roles. They are designed for seamless integration into SOC applications and offer both No-Code and Low-Code implementations for specific NLC tasks. 

#### Modules

[Basic Lightness Controller Profile](btmesh-nlc-basic-lightness-controller)

[Occupancy Sensor Profile](btmesh-nlc-occupancy-sensor)

[Dimming Control Profile](btmesh-nlc-dimming-control)

[Basic Scene Selector Profile](btmesh-nlc-basic-scene-selector)

[Ambient Light Sensor Profile](btmesh-nlc-ambient-light-sensor)

[Energy Monitor Sensor Profile](btmesh-nlc-energy-monitor)

#### Basic Lightness Controller Profile

Basic Lightness Controller role in an NLC network. This component includes other components needed for an SoC application to act as a Basic Lightness Controller node in an NLC network, as well as components providing the relevant metadata for the role.

#### Occupancy Sensor Profile

Occupancy Sensor role in an NLC network. This component includes other components needed for an SoC application to act as an Occupancy Sensor node in an NLC network, as well as components providing the relevant metadata for the role.

#### Dimming Control Profile

BaDimming Control role in an NLC network. This component includes other components needed for an SoC application to act as a Dimming Control node in an NLC network, as well as components providing the relevant metadata for the role.

#### Basic Scene Selector Profile

Basic Scene Selector role in an NLC network. This component includes other components needed for an SoC application to act as a Basic Scene Selector node in an NLC network, as well as components providing the relevant metadata for the role.

#### Ambient Light Sensor Profile

Ambient Light Sensor role in an NLC network. This component includes other components needed for an SoC application to act as an Ambient Light Sensor node in an NLC network, as well as components providing the relevant metadata for the role.

#### Energy Monitor Sensor Profile

Energy monitor role in an NLC network. This component includes other components needed for an SoC application to act as a mock Energy monitor node in an NLC network, as well as components providing the relevant metadata for the role.

### Sensors

This group includes components that enable sensor functionality in a Bluetooth Mesh network. These components support both client and server roles, allowing nodes to monitor and report sensor data. They are designed for seamless integration into SOC applications and provide both No-Code and Low-Code implementations for various sensor-related tasks. 

#### Modules

[Sensor Server](btmesh-sensor-server)

[Sensor Client](btmesh-sensor-client)

#### Sensor Server

Used to support the reporting functionality of a node with a set of sensors whose data is available on the network. It also has a corresponding Sensor Setup Server model which is present on the same element. This component implements temperature, people count, and illuminance measurements. It provides callback functions for each property. This component is prepared for integration into SOC applications. This is a No-Code component if using a Silicon Labs device and the relevant components for their respective hardware. 

##### Functions

###### sl_btmesh_sensor_server_node_init

`void sl_btmesh_sensor_server_node_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize Sensor Server.

This function is called automatically after enabling the component. 

###### sl_btmesh_handle_sensor_server_events

`void sl_btmesh_handle_sensor_server_events(sl_btmesh_msg_t *pEvt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|pEvt|Sensor server event to handle|

Handle Sensor Server events.

This function is called automatically after enabling the component.

###### sl_btmesh_sensor_server_on_temperature_measurement

`void sl_btmesh_sensor_server_on_temperature_measurement(temperature_8_t temperature)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|temperature_8_t|[in]|temperature|Temperature value in 0.5 degree Celsius steps|

Called when a temperature measurement is done **Note**

- If no implementation is provided in the application then a default weak implementation if provided which is a no-operation. (empty function)

###### sl_btmesh_sensor_server_on_light_measurement

`void sl_btmesh_sensor_server_on_light_measurement(illuminance_t light)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|illuminance_t|[in]|light|Lightness value in lux|

Called when a light measurement is done **Note**

- If no implementation is provided in the application then a default weak implementation if provided which is a no-operation. (empty function)

###### sl_btmesh_sensor_server_on_people_count_measurement

`void sl_btmesh_sensor_server_on_people_count_measurement(count16_t people)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|count16_t|[in]|people|People count sensor value|

Called when a people count sensor measurement is done **Note**

- If no implementation is provided in the application then a default weak implementation if provided which is a no-operation. (empty function)

###### sl_btmesh_sensor_server_on_energy_monitor_measurement

`void sl_btmesh_sensor_server_on_energy_monitor_measurement(energy32_t power_consumption)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|energy32_t|[in]|power_consumption|Power consumption measured by the energy monitor|

Called when an energy monitor measurement is done **Note**

- If no implementation is provided in the application then a default weak implementation if provided which is a no-operation. (empty function)

##### Macros

`#define SL_BTMESH_SENSOR_POWER_CONSUMPTION_VALUE_UNKNOWN (0xFFFFFFFF)`

**Description**: Represents an unknown value for power consumption sensor data.

`#define SL_BTMESH_SENSOR_POWER_CONSUMPTION_VALUE_INVALID (0xFFFFFFFE)`

**Description**: Represents an invalid value for power consumption sensor data.

`#define SL_BTMESH_SENSOR_LIGHT_VALUE_UNKNOWN (0xFFFFFFFF)`

**Description**: Represents an unknown light measurement value for the light sensor.

`#define SL_BTMESH_SENSOR_TEMPERATURE_VALUE_UNKNOWN (0x7F)`

**Description**: Represents an unknown temperature value for the temperature sensor.

#### Sensor Client

Used to support the functionality of a node that can monitor sensor data and configure a set of sensors on another node. Sensor Client can connect to multiple Sensor Servers. It may operate on states defined by Sensor Server model and Sensor Setup model via Sensor messages. This component supports temperature, people count, and illuminance data. It provides callback functions for receiving these data, for events, such as when Sensor Server discovery has started, when a device is found. There is an interface to change the current property listened to and request data on said property. This component is prepared for integration into SOC applications. This can be a Low-Code component. The bare minimum for e.g. listening to a broadcast sensor server data is calling sl_btmesh_sensor_client_update_registered_devices on initialization and implementing the relevant weak callbacks. The provided callbacks are the following: void sl_btmesh_sensor_client_on_discovery_started void sl_btmesh_sensor_client_on_new_device_found void sl_btmesh_sensor_client_on_new_temperature_data void sl_btmesh_sensor_client_on_new_people_count_data void sl_btmesh_sensor_client_on_new_illuminance_data 

##### Functions

###### SL_ENUM

`SL_ENUM(sl_btmesh_sensor_client_data_status_t)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_sensor_client_data_status_t|N/A|undefined||

Enumeration representing the status of the sensor data received from the sensor server. 

###### sl_btmesh_sensor_client_on_discovery_started

`void sl_btmesh_sensor_client_on_discovery_started(uint16_t property_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|property_id|property id of the device being discovered.|

Called when Sensor Server discovery is started

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_sensor_client_on_new_device_found

`void sl_btmesh_sensor_client_on_new_device_found(uint16_t property_id, uint16_t address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|property_id|New property ID for which the new device was registered.|
|uint16_t|[in]|address|Address of the new device.|

Called when a Device with the current Device Property ID was found

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_sensor_client_on_new_temperature_data

`void sl_btmesh_sensor_client_on_new_temperature_data(uint8_t sensor_idx, uint16_t address, sl_btmesh_sensor_client_data_status_t status, temperature_8_t temperature)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|sensor_idx|The sensor index represents the order the sensor servers were registered.|
|uint16_t|[in]|address|Address of the sensor server.|
|sl_btmesh_sensor_client_data_status_t|[in]|status|Determines if the data is valid, available or unknown|
|temperature_8_t|[in]|temperature|Measured temperature on the sensor server in 0.5 degree Celsius steps.|

Called when temperature sensor data is received from one of the registered devices

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_sensor_client_on_new_people_count_data

`void sl_btmesh_sensor_client_on_new_people_count_data(uint8_t sensor_idx, uint16_t address, sl_btmesh_sensor_client_data_status_t status, count16_t people_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|sensor_idx|The sensor index represents the order the sensor servers were registered.|
|uint16_t|[in]|address|Address of the sensor server.|
|sl_btmesh_sensor_client_data_status_t|[in]|status|Determines if the data is valid, available or unknown|
|count16_t|[in]|people_count|Measured people count on the sensor server.|

Called when people count sensor data is received from one of the registered devices.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_sensor_client_on_new_illuminance_data

`void sl_btmesh_sensor_client_on_new_illuminance_data(uint8_t sensor_idx, uint16_t address, sl_btmesh_sensor_client_data_status_t status, illuminance_t illuminance)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|sensor_idx|The sensor index represents the order the sensor servers were registered.|
|uint16_t|[in]|address|Address of the sensor server.|
|sl_btmesh_sensor_client_data_status_t|[in]|status|Determines if the data is valid, available or unknown|
|illuminance_t|[in]|illuminance|Measured illuminance on the sensor server in lux with a resolution of 0.01. (0xFFFFFF represents unknown data)|

Called when illuminance sensor data is received from one of the registered devices.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_sensor_client_on_new_power_consumption_data

`void sl_btmesh_sensor_client_on_new_power_consumption_data(uint8_t sensor_idx, uint16_t address, sl_btmesh_sensor_client_data_status_t status, energy32_t power_consumption)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|sensor_idx|The sensor index represents the order the sensor servers were registered.|
|uint16_t|[in]|address|Address of the sensor server.|
|sl_btmesh_sensor_client_data_status_t|[in]|status|Determines if the data is valid, available or unknown|
|energy32_t|[in]|power_consumption|Measured power consumption on the sensor server in units of kilowatt-hours, with a precision of 1 Watt-hour|

Called when energy monitor sensor data is received from one of the registered devices.

This is a callback which can be implemented in the application. **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_sensor_client_update_registered_devices

`sl_status_t sl_btmesh_sensor_client_update_registered_devices(mesh_device_properties_t property)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|mesh_device_properties_t|[in]|property|New property ID for which devices need to be registered.|

Updating the list of registered devices. All previously registered device will be lost.

Generated callback: SL_WEAK void [sl_btmesh_sensor_client_on_discovery_started(uint16_t property_id)](btmesh-sensor-client#sl-btmesh-sensor-client-on-discovery-started); SL_WEAK void [sl_btmesh_sensor_client_on_new_device_found(uint16_t property_id,
                                                         uint16_t address)](btmesh-sensor-client#sl-btmesh-sensor-client-on-new-device-found);

**Returns**

- Status of the operation. Returns SL_STATUS_OK(0) if succeeded, non-zero otherwise.

###### sl_btmesh_sensor_client_get_sensor_data

`sl_status_t sl_btmesh_sensor_client_get_sensor_data(mesh_device_properties_t property)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|mesh_device_properties_t|[in]|property|New property ID for which devices need to be registered.|

Requesting new sensor data for the currently selected sensor property ID.

Generated callback:

Called callback signature depends on the received sensor data type. The <> symbols marks the part which is different due to the different sensor types in these callbacks.

SL_WEAK void sl_btmesh_sensor_client_on_new_<sensor>_data(
                         uint8_t sensor_idx,
                         uint16_t address,
                         sl_btmesh_sensor_client_data_status_t status,
                         <sensor_data_type_t> <sensor_data>)

**Returns**

- Status of the operation. Returns SL_STATUS_OK(0) if succeeded, non-zero otherwise.

###### sl_btmesh_handle_sensor_client_on_event

`void sl_btmesh_handle_sensor_client_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event|

Handle Sensor Client events.

This function is called automatically after enabling the component.

##### Macros

`#define SL_BTMESH_SENSOR_POWER_CONSUMPTION_UNKNOWN ((energy32_t)      0xFFFFFFFF)`

**Description**: Represents an unknown value for power consumption sensor data.

`#define SL_BTMESH_SENSOR_POWER_CONSUMPTION_INVALID ((energy32_t)      0xFFFFFFFE)`

**Description**: Represents an invalid value for power consumption sensor data.

`#define SL_BTMESH_SENSOR_CLIENT_ILLUMINANCE_UNKNOWN ((illuminance_t)   0xFFFFFF)`

**Description**: Represents an unknown value for illuminance sensor data.

`#define SL_BTMESH_SENSOR_CLIENT_PEOPLE_COUNT_UNKNOWN ((count16_t)       0xFFFF)`

**Description**: Represents an unknown value for people count sensor data.

`#define SL_BTMESH_SENSOR_CLIENT_TEMPERATURE_UNKNOWN ((temperature_8_t) 0x7F)`

**Description**: Represents an unknown value for temperature sensor data.

### Transport

This group includes components that provide functionality for managing data transport in a Bluetooth Mesh network. They are designed for seamless integration into SOC applications and offer both No-Code and Low-Code implementations for various transport-related tasks. 

#### Modules

[BLOB Transfer Server](btmesh-blob-transfer-server)

[BLOB Transfer Server Core](btmesh-blob-transfer-server-core)

[BLOB Transfer Client](btmesh-blob-transfer-client)

#### BLOB Transfer Server Core

Provides BT Mesh BLOB (Binary Large OBject) Transfer Server Core API for managing the BLOB Transfer Server instances. This component includes only the core functionality. To configure and create instances of BLOB Transfer Server, the BLOB Transfer Server component shall be added to the project. This component is prepared for integration into SOC applications.

#### BLOB Transfer Server

Provides BT Mesh BLOB (Binary Large OBject) Transfer Server functionality, defined in mesh specification. The BLOB Transfer Server model is used to receive a BLOB from a BLOB Transfer Client. The BLOB is delivered to a higher-layer application for further processing once the transfer is complete. This component is instantiable, meaning that several named instances can be created. For each instance, a configuration header, an instance header and a source file is generated to encapsulate functionalities and initialize and manage the instance. Each BLOB Transfer Server instance shall be assigned to different elements by instance configuration in accordance with mesh specification. Selecting this component will also include the BLOB Transfer Server Core component, which is the implementation of the BLOB Transfer Server API. This component is prepared for integration into SOC applications. This is a Low-Code component. For example, the following weak callback function is called when a BLOB transfer is completed: void [sl_btmesh_blob_transfer_server_transfer_done(sl_bt_uuid_64_t const *const blob_id)](mesh-blob-transfer-server-api#sl-btmesh-blob-transfer-server-transfer-done)

##### Modules

[Mesh_blob_transfer_server_api](mesh-blob-transfer-server-api)

##### Functions

###### sl_btmesh_blob_transfer_server_init

`void sl_btmesh_blob_transfer_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the BLOB Transfer Server application 

###### sl_btmesh_blob_transfer_server_on_event

`void sl_btmesh_blob_transfer_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|BT Mesh stack event|

Processes BT Mesh stack events related to BLOB Trasnfer Server

###### sl_btmesh_blob_transfer_server_start

`sl_status_t sl_btmesh_blob_transfer_server_start(uint16_t elem_index, sl_bt_uuid_64_t const *const blob_id, const uint16_t timeout_10s, const uint8_t ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of BLOB to be received|
|const uint16_t|[in]|timeout_10s|Timeout of reception in 10 seconds. If no data is received for this time, the transfer will be suspended. The actual timeout is calculated as (1 + `timeout_10s`) × 10 s|
|const uint8_t|[in]|ttl|The TTL used for communicating with the client|

Let BLOB Transfer Server accept an incoming BLOB with given ID

This function needs to be called from other application components, that can determine incoming BLOB ID's, before any transfer can be done.

**Note**

- Firmware Update Server automatically handles this operation when it receives a firmware update start message ( `sl_btmesh_evt_fw_update_server_update_start_req_id` ).

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case transmission is already ongoing

###### sl_btmesh_blob_transfer_server_set_pull_mode_parameters

`sl_status_t sl_btmesh_blob_transfer_server_set_pull_mode_parameters(uint16_t elem_index, uint16_t pull_mode_retry_interval_ms, uint16_t pull_mode_retry_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The server model element index.|
|uint16_t|[in]|pull_mode_retry_interval_ms|Retry interval in milliseconds|
|uint16_t|[in]|pull_mode_retry_count|Number of times to retry|

Set PULL transfer retry parameters

The new values will take effect at the next transfer start. The command does not modify parameters of the ongoing transfer.

**Returns**

- Status code

**Return values**

- SL_STATUS_OK: In case of success
- SL_STATUS_INVALID_STATE: In case state is invalid

###### sl_btmesh_blob_transfer_server_step_handle

`void sl_btmesh_blob_transfer_server_step_handle(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Handles the BLOB transfer state machine

Used for asynchronously erasing BLOBs

##### Mesh_blob_transfer_server_api

BT Mesh BLOB Transfer Server user-overridable API 

###### Functions

###### sl_btmesh_blob_transfer_server_transfer_start (heading level 7)

`void sl_btmesh_blob_transfer_server_transfer_start(sl_bt_uuid_64_t const *const blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of BLOB to be transferred|

Called when starting BLOB transfer

###### sl_btmesh_blob_transfer_server_transfer_progress (heading level 7)

`void sl_btmesh_blob_transfer_server_transfer_progress(sl_bt_uuid_64_t const *const blob_id, float progress)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of the BLOB being transferred|
|float|[in]|progress|Progress in floating point percentage|

Called when new block is started

**Note**

- Progress is incremented on a chunk basis, but user callback is called on block basis to avoid too frequent calls.

###### sl_btmesh_blob_transfer_server_transfer_done (heading level 7)

`void sl_btmesh_blob_transfer_server_transfer_done(sl_bt_uuid_64_t const *const blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of BLOB transferred|

Called when BLOB transfer is done

###### sl_btmesh_blob_transfer_server_transfer_abort (heading level 7)

`void sl_btmesh_blob_transfer_server_transfer_abort(sl_bt_uuid_64_t const *const blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of BLOB being transferred|

Called when BLOB transfer is aborted

###### sl_btmesh_blob_transfer_server_storage_full (heading level 7)

`void sl_btmesh_blob_transfer_server_storage_full(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Called when BLOB storage signals it's full

#### BLOB Transfer Client

Provides BT Mesh BLOB (binary large object) Transfer Client functionality, defined in mesh specification. The BLOB Transfer Client model is used by a higher-layer application to transfer a BLOB to one or more BLOB Transfer Servers. The higher-layer application provides the inputs to the procedures executed by the client. This component is prepared for integration into SOC applications. 

##### Modules

[sl_btmesh_blob_transfer_client_progress_t](sl-btmesh-blob-transfer-client-progress-t)

[sl_btmesh_blob_transfer_client_server_failed_t](sl-btmesh-blob-transfer-client-server-failed-t)

[sl_btmesh_blob_transfer_client_notification_t](sl-btmesh-blob-transfer-client-notification-t)

##### Typedefs

###### sl_btmesh_blob_transfer_client_notify_cb_t

`sl_btmesh_blob_transfer_client_notify_cb_t`

**Description:**

Callback function type for BLOB transfer client notifications.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
||[in]|notification|Pointer to the notification structure containing details about the event or update.|

**Details:**

This callback is invoked to notify the application about events or updates related to the BLOB transfer client. The notification details are provided through the `sl_btmesh_blob_transfer_client_notification_t` structure.

##### Functions

###### SL_ENUM

`SL_ENUM(sl_btmesh_blob_transfer_client_notification_kind_t)`

**Description:** BLOB Transfer Client Kind.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_blob_transfer_client_notification_kind_t|N/A|undefined||

###### SL_ENUM

`SL_ENUM(sl_btmesh_blob_transfer_client_result_t)`

**Description:** BLOB Transfer Client Result.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_blob_transfer_client_result_t|N/A|undefined||

###### sl_btmesh_blob_transfer_client_setup

`sl_status_t sl_btmesh_blob_transfer_client_setup(uint16_t elem_index, sl_bt_uuid_64_t blob_id, uint32_t blob_size, uint16_t appkey_index, uint8_t ttl, uint16_t timeout_base, uint16_t group_address, uuid_128 virtual_address, uint16_t multicast_threshold, size_t servers_len, const uint8_t *servers)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|The client model element index.|
|sl_bt_uuid_64_t|[in]|blob_id|The ID of the BLOB.|
|uint32_t|[in]|blob_size|The size of the BLOB.|
|uint16_t|[in]|appkey_index|Index of the application key to be used for communicating with the servers|
|uint8_t|[in]|ttl|The TTL to use when communicating with the servers.|
|uint16_t|[in]|timeout_base|If a Server does not respond within this time frame, it will be marked as inactive.|
|uint16_t|[in]|group_address|The group address to used if the `multicast_threshold` is exceeded. Zero to only use unicast.|
|uuid_128|[in]|virtual_address|Virtual address in case virtual addresses are used|
|uint16_t|[in]|multicast_threshold|If the number of servers for any step exceeds this number, the group address will be used. Otherwise, servers will be looped through one by one.|
|size_t|[in]|servers_len|Length of data in servers|
|const uint8_t *|[in]|servers|List of MBT server addresses, represented as little endian two byte sequences.|

Set up a new BLOB transfer.

**Note**

- This shall not be called when the Distribution Server initiates the BLOB transfer because BT Mesh stack sets up the BLOB transfer inside the BT Mesh stack automatically.

**Returns**

- Result of the BLOB Transfer setup

**Return values**

- SL_STATUS_OK: if successful. Error code otherwise.
- SL_STATUS_INVALID_STATE: if not Idle

###### sl_btmesh_blob_transfer_client_setup_data_provider_array

`sl_status_t sl_btmesh_blob_transfer_client_setup_data_provider_array(uint16_t elem_index, const uint8_t *array, uint32_t length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|const uint8_t *|[in]|array|Pointer to an array which stores the BLOB data|
|uint32_t|[in]|length|Length of the array|

Set up an array data provider for a new BLOB transfer.

The BLOB transfer client reads the BLOB data from this array during chunk transfer.

**Returns**

- Result of the Data Provider setup

**Return values**

- SL_STATUS_OK: if successful
- SL_STATUS_INVALID_STATE: Data Provider setup called in non-idle state
- SL_STATUS_INVALID_PARAMETER: BLOB size inconsistency between the [sl_btmesh_blob_transfer_client_setup](btmesh-blob-transfer-client#sl-btmesh-blob-transfer-client-setup) and this Data Provider setup call

###### sl_btmesh_blob_transfer_client_setup_data_provider_blob_storage

`sl_status_t sl_btmesh_blob_transfer_client_setup_data_provider_blob_storage(uint16_t elem_index, const sl_bt_uuid_64_t *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|const sl_bt_uuid_64_t *|[in]|blob_id|Pointer to the BLOB id|

Set up a BLOB storage data provider for a new BLOB transfer.

The BLOB Transfer Client reads the BLOB data from the BLOB storage based on the passed BLOB id.

**Note**

- The BLOB id used to identify the BLOB data in the BLOB storage (on the client side) is likely not the same as the BLOB id used during the BLOB transfer to the servers.

**Returns**

- Result of the Data Provider setup

**Return values**

- SL_STATUS_OK: if successful
- SL_STATUS_INVALID_STATE: Data Provider setup called in non-idle state
- SL_STATUS_NOT_FOUND: BLOB is not found in the BLOB storage
- SL_STATUS_INVALID_PARAMETER: BLOB size inconsistency between the [sl_btmesh_blob_transfer_client_setup](btmesh-blob-transfer-client#sl-btmesh-blob-transfer-client-setup) and this Data Provider setup call

###### sl_btmesh_blob_transfer_client_set_params

`sl_status_t sl_btmesh_blob_transfer_client_set_params(uint16_t elem_index, uint16_t separation_time_ms, uint16_t retry_time_local_ms, uint16_t retry_time_push_ms, uint16_t retry_time_pull_ms, uint16_t retry_max_local, uint16_t retry_threshold_remote)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|uint16_t|[in]|separation_time_ms|Minimum separation time between two chunks in the same block, in milliseconds|
|uint16_t|[in]|retry_time_local_ms|Local retry time of message transmission requests during query info, transfer start, block start, block query, chunk transfer and transfer cancel procedures. Local retry time is used when the BT Mesh stack rejects sending BLOB Transfer messages due to a recoverable error, so BT Mesh stack API returns with recoverable error code, for example due to lack of memory. Local retry time shall be greater than zero.|
|uint16_t|[in]|retry_time_push_ms|Retry time of message transmissions during push transfer. The transfer start, block start, block query and transfer cancel procedures use this retry time during push transfer to send the procedure specific message again if at least one receiver haven't responded when retry timeout is reached. The query info procedure use this retry time value when the push transfer mode is selected explicitly by upper layer or both transfer modes (push & pull) are allowed by the upper layer.|
|uint16_t|[in]|retry_time_pull_ms|Retry time of message transmissions during pull transfer. The transfer start, block start, block query and transfer cancel procedures use this retry time during pull transfer to send the procedure specific message again if at least one receiver haven't responded when this retry timeout is reached.The query info procedure use this retry time when the pull transfer mode is selected explicitly by upper layer.|
|uint16_t|[in]|retry_max_local|Local max retries of message transmission requests during query info, transfer start, block start, block query chunk transfer and transfer cancel procedures. Max local retry is used when the BT Mesh stack rejects sending BLOB Transfer messages due to a recoverable error, so BT Mesh stack API returns with recoverable error code, for example due to lack of memory|
|uint16_t|[in]|retry_threshold_remote|Retry threshold of frequent message transmissions during query info, transfer start, block start, block query and transfer cancel procedures before infrequent message transmission is activated with doubled retry time.|

Set up additional parameters for new BLOB transfers

The separation and retry parameters are set for all future BLOB Transfers until the next reset (stored in RAM). On reset, the respective default separation and retry parameters are set based on the component configuration at component initialization time.

**Note**

- This function is separated from [sl_btmesh_blob_transfer_client_setup](btmesh-blob-transfer-client#sl-btmesh-blob-transfer-client-setup) because the [sl_btmesh_blob_transfer_client_setup](btmesh-blob-transfer-client#sl-btmesh-blob-transfer-client-setup) shall not be called when [Firmware Distribution Server](btmesh-fw-distribution-server) initiates the BLOB transfer because BT Mesh stack sets up the BLOB transfer inside the BT Mesh stack automatically.

**Returns**

- Result of the parameter setup

**Return values**

- SL_STATUS_OK: if successful
- SL_STATUS_INVALID_STATE: Parameter setup called in non-idle state
- SL_STATUS_INVALID_PARAMETER: One or more parameters are invalid

###### sl_btmesh_blob_transfer_client_start

`sl_status_t sl_btmesh_blob_transfer_client_start(uint16_t elem_index, sl_btmesh_mbt_client_transfer_mode_t transfer_mode, sl_btmesh_blob_transfer_client_notify_cb_t notify)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|
|sl_btmesh_mbt_client_transfer_mode_t|[in]|transfer_mode|Allowed transfer mode|
|[sl_btmesh_blob_transfer_client_notify_cb_t](btmesh-blob-transfer-client#sl-btmesh-blob-transfer-client-notify-cb-t)|[in]|notify|Function pointer to a notification callback function which is called in the following cases: <br/><br/>- BLOB Transfer completed<br/>- BLOB Transfer failed<br/>- BLOB Transfer canceled<br/>- BLOB Transfer progress changes<br/>- BLOB Transfer Server failed<br/><br/><br/>It is valid to pass NULL as notify parameter. If the callback function is null then no notification is initiated. If `transfer_mode` is set to `sl_btmesh_mbt_client_mbt_transfer_mode_both` then the BLOB transfer client selects the transfer mode based on the result of query information. If one transfer mode is supported by all receiving nodes only then that transfer mode is selected otherwise push mode is selected. If `transfer_mode` is set to `sl_btmesh_mbt_client_mbt_transfer_mode_push` or `sl_btmesh_mbt_client_mbt_transfer_mode_pull` then that is used as transfer mode.|

Starts a previously set up BLOB Transfer.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise

**Return values**

- SL_STATUS_INVALID_PARAMETER: Invalid transfer mode
- SL_STATUS_INVALID_STATE: BLOB Transfer Client busy with another transfer
- SL_STATUS_INVALID_CONFIGURATION: No data provider was specified

###### sl_btmesh_blob_transfer_client_cancel

`void sl_btmesh_blob_transfer_client_cancel(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Cancels an ongoing BLOB Transfer.

###### sl_btmesh_blob_transfer_client_abort

`sl_status_t sl_btmesh_blob_transfer_client_abort(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Aborts an ongoing BLOB Transfer.

**Note**

- This function is not to be used when the MBT client is interfaced by a higher layer component (e.g. distribution server).

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_blob_transfer_client_on_aborted

`sl_status_t sl_btmesh_blob_transfer_client_on_aborted(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Informs BLOB Transfer Client SDK component that the transfer in MBT Client model of BT Mesh stack was aborted.

**Note**

- This function shall be used only when the MBT client is interfaced by a higher layer component (e.g. distribution server). The MBT Client model can be aborted by higher layer models in the BT Mesh stack which is not reported in MBT Client model events so it shall be reported by calling this API.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_blob_transfer_client_on_suspended

`sl_status_t sl_btmesh_blob_transfer_client_on_suspended(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Informs BLOB Transfer Client SDK component that the transfer in MBT Client model of BT Mesh stack was suspended.

**Note**

- This function shall be used only when the MBT client is interfaced by a higher layer component (e.g. distribution server). The MBT Client model can be suspended by higher layer models in the BT Mesh stack which is not reported in MBT Client model events so it shall be reported by calling this API.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_blob_transfer_client_on_resumed

`sl_status_t sl_btmesh_blob_transfer_client_on_resumed(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Client model element index|

Informs BLOB Transfer Client SDK component that the transfer in MBT Client model of BT Mesh stack was resumed.

**Note**

- This function shall be used only when the MBT client is interfaced by a higher layer component (e.g. distribution server). The MBT Client model can be resumed by higher layer models in the BT Mesh stack which is not reported in MBT Client model events so it shall be reported by calling this API.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_blob_transfer_client_on_event

`void sl_btmesh_blob_transfer_client_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle BLOB Transfer Client events.

This function is called automatically after enabling the component.

###### sl_btmesh_blob_transfer_client_calculate_block_size_log

`uint8_t sl_btmesh_blob_transfer_client_calculate_block_size_log(uint32_t blob_size, uint8_t block_size_log_min, uint8_t block_size_log_max, uint16_t block_count_max, uint16_t max_chunk_size_min, uint16_t max_chunks_min)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|blob_size|Size of the BLOB|
|uint8_t|[in]|block_size_log_min|Min allowed binary logarithm of the block size|
|uint8_t|[in]|block_size_log_max|Max allowed binary logarithm of the block size|
|uint16_t|[in]|block_count_max|Max allowed number of blocks|
|uint16_t|[in]|max_chunk_size_min|Max allowed chunk size in the current transfer|
|uint16_t|[in]|max_chunks_min|Max allowed number of chunks per block in the current transfer|

Calculates the binary logarithm of the block size for the current BLOB transfer from the provided parameters which are the result of the Retrieve Capabilities procedure of the BLOB Transfer.

The parameters passed represent the aggregated capabilities of the BLOB transfer client and every BLOB transfer server which participates in the current transfer.

The default implementation calculates the greatest possible block size from the parameters. If another implementation is required then the strong symbol definition shall be provided for this function with the implementation in the application code.

**Returns**

- Binary logarithm of the selected block size for the current transfer

**Return values**

- SL_BTMESH_BLOB_TRANSFER_CLIENT_INVALID_BLOCK_SIZE_LOG: Invalid parameters

###### sl_btmesh_blob_transfer_client_calculate_chunk_size

`uint16_t sl_btmesh_blob_transfer_client_calculate_chunk_size(uint8_t block_size_log, uint16_t max_chunk_size_min, uint16_t max_chunks_min, uint16_t nw_pdu_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|block_size_log|The selected binary logarithm of the block size during previous phase of the BLOB transfer|
|uint16_t|[in]|max_chunk_size_min|Max allowed chunk size in the current transfer|
|uint16_t|[in]|max_chunks_min|Max allowed number of chunks per block in the current transfer|
|uint16_t|[in]|nw_pdu_size|Size of Network PDU. If the Silicon Labs BT Mesh over advertisement extension proprietary feature is turned on then it can be greater than 29 bytes.|

Calculates the chunk size for the next block in the current BLOB transfer from the previously selected binary logarithm of the block size and from the result of the Retrieve Capabilities procedure of the BLOB Transfer.

If the configurable preferred chunk size is supported by all BLOB Transfer Servers then the default chunk size calculation algorithm selects it as chunk size of the block otherwise the chunk size is set to the closest value which fills all segments of the chunk. If another implementation is required then the strong symbol definition shall be provided for this function with the implementation in the application code.

**Returns**

- Chunk size for next block in the current BLOB transfer

###### sl_btmesh_blob_transfer_client_transfer_mode_to_string

`const char * sl_btmesh_blob_transfer_client_transfer_mode_to_string(sl_btmesh_mbt_client_transfer_mode_t transfer_mode)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_mbt_client_transfer_mode_t|[in]|transfer_mode|transfer mode|

Provides string representation of transfer mode

It is guaranteed that this function returns a valid string even in case of invalid transfer mode.

**Note**

- The to_string functions are used for log calls only in this component. If the logging is disabled then the linker can eliminate these functions.

**Returns**

- String representation of transfer mode

**Return values**

- INVALID: if the transfer mode is invalid

###### sl_btmesh_blob_transfer_client_mbt_phase_to_string

`const char * sl_btmesh_blob_transfer_client_mbt_phase_to_string(sl_btmesh_mbt_server_phase_t mbt_phase)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_mbt_server_phase_t|[in]|mbt_phase|MBT phase|

Provides string representation of MBT phase

It is guaranteed that this function returns a valid string even in case of invalid MBT phase.

**Note**

- The to_string functions are used for log calls only in this component. If the logging is disabled then the linker can eliminate these functions.

**Returns**

- String representation of MBT phase

**Return values**

- INVALID: if the MBT phase is invalid

###### sl_btmesh_blob_transfer_client_mbt_status_to_string

`const char * sl_btmesh_blob_transfer_client_mbt_status_to_string(sl_btmesh_mbt_server_status_t mbt_status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_mbt_server_status_t|[in]|mbt_status|MBT status|

Provides string representation of MBT status

It is guaranteed that this function returns a valid string even in case of invalid MBT status.

**Note**

- The to_string functions are used for log calls only in this component. If the logging is disabled then the linker can eliminate these functions.

**Returns**

- String representation of MBT status

**Return values**

- INVALID: if the MBT status is invalid

###### sl_btmesh_blob_transfer_client_get_max_servers

`uint16_t sl_btmesh_blob_transfer_client_get_max_servers(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Provides the maximum number of MBT servers the client is configured to handle

**Returns**

- Value of SL_BTMESH_BLOB_TRANSFER_CLIENT_MAX_SERVERS_CFG_VAL

##### Macros

`#define SL_BTMESH_BLOB_TRANSFER_CLIENT_INVALID_BLOCK_SIZE_LOG 0xFF`

**Description**: Invalid value for the binary logarithm of the block size.

BLOB Transfer progress

This structure represent the progress of the active BLOB Transfer Servers

**Note**

- Some servers could fail with error or timeout, but if there is at least one active BLOB Transfer Server then the transfer continues

###### Public Attributes

###### confirmed_tx_bytes (heading level 7)

```
uint32_t sl_btmesh_blob_transfer_client_progress_t::confirmed_tx_bytes
```

**Details:** Number of BLOB bytes which have been received by every active BLOB Transfer Server

**Note**

- The progress is calculated at the end of the blocks because in the block, chunks could be retransmitted multiple times

###### blob_size (heading level 7)

```
uint32_t sl_btmesh_blob_transfer_client_progress_t::blob_size
```

**Description:** BLOB size in bytes.

BLOB Transfer Server Failed Notification. 

###### Public Attributes

###### server_address (heading level 7)

```
uint16_t sl_btmesh_blob_transfer_client_server_failed_t::server_address
```

**Description:** Address of the BLOB Transfer Server.

###### timeout (heading level 7)

```
uint8_t sl_btmesh_blob_transfer_client_server_failed_t::timeout
```

**Details:** If a BLOB Transfer Server doesn't respond until a specified time then the timeout is set to 1

###### error (heading level 7)

```
uint8_t sl_btmesh_blob_transfer_client_server_failed_t::error
```

**Details:** The error is set only if the timeout is zero and a BLOB Transfer Server has responded with non-zero status code (error) in BLOB Transfer Status or BLOB Block Status message

Notification data for upper layers. 

###### Public Attributes

###### kind (heading level 7)

```
sl_btmesh_blob_transfer_client_notification_kind_t sl_btmesh_blob_transfer_client_notification_t::kind
```

**Description:** Identifies the notification type.

###### elem_index (heading level 7)

```
uint16_t sl_btmesh_blob_transfer_client_notification_t::elem_index
```

**Description:** Index of the element which triggered the notification.

###### transfer_result (heading level 7)

```
sl_btmesh_blob_transfer_client_result_t sl_btmesh_blob_transfer_client_notification_t::transfer_result
```

**Description:** Status of the active BLOB transfer on the element.

###### progress (heading level 7)

```
sl_btmesh_blob_transfer_client_progress_t sl_btmesh_blob_transfer_client_notification_t::progress
```

**Description:** Progress of the active BLOB Transfer on the element.

###### server_failed (heading level 7)

```
sl_btmesh_blob_transfer_client_server_failed_t sl_btmesh_blob_transfer_client_notification_t::server_failed
```

**Description:** Reason of BLOB Transfer Server failure during the active BLOB Transfer.

###### params (heading level 7)

```
union sl_btmesh_blob_transfer_client_notification_t::@0 sl_btmesh_blob_transfer_client_notification_t::params
```

**Description:** Notification specific parameters.

### SAR

This group includes components that enable the configuration and management of Segmentation and Reassembly (SAR) behavior in Bluetooth Mesh networks. These components provide both client and server roles, allowing nodes to configure SAR settings locally or remotely. They are designed for seamless integration into SOC applications and are primarily No-Code components. 

#### Modules

[SAR Configuration Server](btmesh-sar-config-server)

[SAR Configuration Client](btmesh-sar-config-client)

#### SAR Configuration Server

SAR Configuration Server component enables the local and remote configuration of the segmentation and reassembly behavior of a node. This component extends the DCD with SAR Configuration Server model ID and initializes the SAR Configuration Server model in the BT Mesh stack automatically. The local node configuration shall be performed through the SAR Configuration Server BT Mesh API calls. The BT Mesh stack reports in SAR Configuration Server events when the SAR Configuration Transmitter and Receiver states are set by SAR Configuration Client. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_sar_config_server_on_event

`void sl_btmesh_sar_config_server_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle SAR Configuration Server events.

This function is called automatically after enabling the component.

#### SAR Configuration Client

SAR Configuration Client component enables the configuration of the lower transport layer on nodes that support the SAR Configuration Server model. This component extends the DCD with SAR Configuration Client model ID and initializes the SAR Configuration Client model in the BT Mesh stack automatically. The node configuration shall be performed through the SAR Configuration Client BT Mesh API calls. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_sar_config_client_on_event

`void sl_btmesh_sar_config_client_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle SAR Configuration Client events.

This function is called automatically after enabling the component.

### Generic

This group includes components that initialize and manage Generic Server and Client Models in a Bluetooth Mesh network. These components provide interfaces for registering event handlers and extend functionality for specific Generic Models. They are designed for seamless integration into SOC applications and support both No-Code and Low-Code implementations. 

#### Modules

[Generic Level Client Extension](btmesh-generic-level-client-ext)

[Generic Base](btmesh-generic-base)

#### Generic Level Client Extension

Generic Level extension that supports Generic Move and Generic Delta messages. This component extends the Generic Base component with the additional support of sending Generic Move Unacknowledged and Generic Delta Unacknownledged messages. This allows the user to create an example that provides the Dimming Control NLC Profile functionality. This is a no-code component. 

##### Functions

###### sl_btmesh_generic_level_client_ext_init

`void sl_btmesh_generic_level_client_ext_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Generic Level Client state initialization

This is called at each boot if provisioning is already done, otherwise this function is called after provisioning is completed 

###### sl_btmesh_generic_level_client_ext_on_event

`void sl_btmesh_generic_level_client_ext_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event|

Handling of mesh generic level client events

This function is called automatically by Universal Configurator after enabling the component

###### sl_btmesh_generic_level_client_ext_delta_set_unack

`void sl_btmesh_generic_level_client_ext_delta_set_unack(int32_t delta)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|delta|The Delta change of the Generic Level state in absolute value|

Send Generic Level Delta Set Unacknowledged message

###### sl_btmesh_generic_level_client_ext_move_set_unack

`void sl_btmesh_generic_level_client_ext_move_set_unack(int16_t delta_level_step)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int16_t|[in]|delta_level_step|The Delta Level step to calculate Move speed for the Generic Level state|

Send Generic Level Move Set Unacknowledged message

###### sl_btmesh_generic_level_client_ext_halt

`void sl_btmesh_generic_level_client_ext_halt(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Halt previous Generic Level Move command

#### Generic Base

This Component initializes the Generic Server and Client Models which are added to the project as components and provides an interface to register handlers for their events. Note that the Generic Base Component alone does not add support for Generic Models (e.g. Generic OnOff Server/Client, Generic Level Server/Client, etc), that has to be done from another component or application software. This component is prepared for integration into SOC applications.

### Firmware Update

This group includes components that provide functionality for managing firmware updates in a Bluetooth Mesh network. These components enable seamless integration into SOC applications and support roles. They facilitate firmware image transfer, update management, and reporting, ensuring efficient and reliable firmware updates across the network. 

#### Modules

[Firmware Update Server](btmesh-firmware-update-server)

[Firmware Distribution Server](btmesh-fw-distribution-server)

[Firmware Update Client](btmesh-firmware-update-client)

#### Firmware Distribution Server

Provides BT Mesh Firmware Distribution Server functionality, defined in mesh specification. This model is used by the Distributor to receive from the Initiator the firmware update parameters, the set of Target nodes to update, and the firmware image to transfer. This model uses the Firmware Update Client model and the BLOB Transfer Client model to manage the firmware update. The Firmware Distribution Server can transfer one firmware image at a time. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Functions

###### sl_btmesh_fw_distribution_server_set_multicast_threshold

`sl_status_t sl_btmesh_fw_distribution_server_set_multicast_threshold(uint16_t elem_index, uint16_t multicast_threshold)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution Server model element index|
|uint16_t|[in]|multicast_threshold|If the number of servers for any step exceeds or is equal to this number then the group address will be used, otherwise servers will be looped through one by one. Value of 0 disables the feature.|

Set the multicast threshold value

The FW Distribution Server BT Mesh stack model caches the value of multicast threshold when the distribution is started and it passes the value to the MBT Client model (BLOB Transfer Client) in BT Mesh stack when the BLOB transfer is started. If the number of servers for any step exceeds or equal to this number then the group address will be used, otherwise the servers will be looped through one by one. Value of 0 disables the feature.

The MBT Client BT Mesh stack model tracks the number of servers which it needs to send specific messages to. It tracks for each server if the proper status message is received from the server in case of BLOB Information Get, BLOB Transfer Start, BLOB Block Start and BLOB Block Get messages. If some servers don't receive these BLOB messages or the response status messages are lost due to interference then the retry logic in BLOB Transfer Client SDK component requests to send the necessary BLOB messages to the servers by calling the proper MBT Client API again. If number of servers with missing status messages exceeds or equal to the multicast threshold value then the mentioned messages are sent to the group address, otherwise servers will be looped through one by one.

The tracking of successful reception of Chunk Transfer Messages are different because these are tracked by block status procedure in case of push transfer mode or by partial block report procedure in case of pull transfer mode.

The advantage of multicast messages is that the client needs to send one message only to the servers which is much faster if the number of servers which haven't received the message is high. This is especially true for chunk transfer because Chunk Transfer messages can be quite big and there are quite many of them in the BLOB Transfer.

The advantage of unicast addressing in case of non-chunk messages is that only those server respond with status messages which really need to. This can have significant effect when the node count is high. For example if there are hundreds of nodes in the BLOB transfer then each group message triggers hundreds of status messages even when only some status messages from specific servers are missing on the client side. The transport layer uses segment acknowledgment for segmented unicast mesh messages which improves the reliability of segmented message transfer especially when the number of segments are high but it tends to be slower because the segment acknowledgment messages needs to be waited.

**Warnings**

- The MBT client stack model allocates and sends all unicast BLOB messages to each server at the same time below the multicast threshold. This could lead to exhaustive buffer allocation and the maximum number of parallel segmented messages can be exceeded as well in case of high multicast threshold level. The multicast threshold shall not be greater than SL_BTMESH_CONFIG_MAX_SEND_SEGS from sl_btmesh_config.h.

**Note**

- The multicast threshold shall be set when the distribution is started (or before) in order to have an effect on the BLOB transfer otherwise it affects the next transfer only. The multicast threshold can be set in [sl_btmesh_fw_distribution_server_on_distribution_started](btmesh-fw-distribution-server#sl-btmesh-fw-distribution-server-on-distribution-started) callback as well to tune it to the specific FW distribution.

**Returns**

- SL_STATUS_OK if successful. Error code otherwise.

###### sl_btmesh_fw_distribution_server_on_event

`void sl_btmesh_fw_distribution_server_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle Firmware Distribution Server events

This function is called automatically after enabling the component.

###### sl_btmesh_fw_distribution_server_distribution_state_to_string

`const char * sl_btmesh_fw_distribution_server_distribution_state_to_string(sl_btmesh_fw_dist_server_dist_step_t state)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_fw_dist_server_dist_step_t|[in]|state|Distribution state|

Provides string representations of Distribution states

**Returns**

- String representation of distribution state

**Return values**

- INVALID: if the state is invalid

###### sl_btmesh_fw_distribution_server_node_phase_to_string

`const char * sl_btmesh_fw_distribution_server_node_phase_to_string(sl_btmesh_fw_dist_server_dist_node_phase_t node_phase)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_fw_dist_server_dist_node_phase_t|[in]|node_phase|Phase of Firmware Update Server on Target Node|

Provides string representations of Firmware Update phase

**Returns**

- String representation of node update phase

**Return values**

- INVALID: if the node_phase is invalid

###### sl_btmesh_fw_distribution_server_firmware_update_status_to_string

`const char * sl_btmesh_fw_distribution_server_firmware_update_status_to_string(sl_btmesh_fw_update_server_update_status_t node_status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_fw_update_server_update_status_t|[in]|node_status|Status of Firmware Update Server on Target Node|

Provides string representations of Firmware Update status

**Returns**

- String representation of node's firmware update status

**Return values**

- INVALID: if the node_status is invalid

###### sl_btmesh_fw_distribution_server_generate_blob_id

`sl_status_t sl_btmesh_fw_distribution_server_generate_blob_id(sl_bt_uuid_64_t *blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t *|[out]|blob_id|Pointer to blob_id where the generated bytes shall be stored|

Called to generate BLOB ID for firmware distribution

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application then a default weak implementation is provided which uses the sl_bt_system_get_random_data BT stack API to generate random bytes for BLOB identifier.

**Returns**

- Status of BLOB id generation. If it is not SL_STATUS_OK then the firmware distribution server component uses the storage BLOB id for the firmware distribution. The storage BLOB id was used during firmware upload.

###### sl_btmesh_fw_distribution_server_on_node_added

`void sl_btmesh_fw_distribution_server_on_node_added(uint16_t elem_index, uint16_t server_address, uint8_t update_fw_image_idx, uint16_t node_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|server_address|Unicast address of the added target node|
|uint8_t|[in]|update_fw_image_idx|Firmware image index on target node to be updated during the distribution|
|uint16_t|[in]|node_count|Total number of target nodes which participates in the firmware distribution (including this new one)|

Called when a receiver target node is added to the firmware distribution list

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_all_nodes_deleted

`void sl_btmesh_fw_distribution_server_on_all_nodes_deleted(uint16_t elem_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|

Called when all receiver target nodes are deleted from the firmware distribution list

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_distribution_started

`void sl_btmesh_fw_distribution_server_on_distribution_started(uint16_t elem_index, uint16_t client_address, uint16_t group_address, uint8_t ttl, sl_btmesh_fw_dist_server_dfu_policy_t update_policy, uint16_t fw_list_index, uint16_t timeout_base, sl_btmesh_mbt_client_transfer_mode_t transfer_mode, uint16_t node_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client|
|uint16_t|[in]|group_address|Group address of the distribution|
|uint8_t|[in]|ttl|Distribution TTL|
|sl_btmesh_fw_dist_server_dfu_policy_t|[in]|update_policy|1 if the Update Policy is Verify and Apply, otherwise 0|
|uint16_t|[in]|fw_list_index|Index of the firmware in the Distributor's FW List|
|uint16_t|[in]|timeout_base|Timeout base|
|sl_btmesh_mbt_client_transfer_mode_t|[in]|transfer_mode|Transfer Mode to use in the distribution|
|uint16_t|[in]|node_count|Total number of target nodes which participates in the firmware distribution|

Called when firmware distribution is started

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

The [sl_btmesh_fw_distribution_server_set_multicast_threshold](btmesh-fw-distribution-server#sl-btmesh-fw-distribution-server-set-multicast-threshold) function can be called from this callback to set the multicast threshold value for the current distribution.

###### sl_btmesh_fw_distribution_server_on_distribution_canceled

`void sl_btmesh_fw_distribution_server_on_distribution_canceled(uint16_t elem_index, uint16_t client_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client|

Called when firmware distribution is canceled

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_distribution_suspended

`void sl_btmesh_fw_distribution_server_on_distribution_suspended(uint16_t elem_index, uint16_t client_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client|

Called when firmware distribution is suspended

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_distribution_resumed

`void sl_btmesh_fw_distribution_server_on_distribution_resumed(uint16_t elem_index, uint16_t client_address, uint16_t group_address, uint8_t ttl, sl_btmesh_fw_dist_server_dfu_policy_t update_policy, uint16_t fw_list_index, uint16_t timeout_base, sl_btmesh_mbt_client_transfer_mode_t transfer_mode, uint16_t node_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client|
|uint16_t|[in]|group_address|Group address of the distribution|
|uint8_t|[in]|ttl|Distribution TTL|
|sl_btmesh_fw_dist_server_dfu_policy_t|[in]|update_policy|1 if the Update Policy is Verify and Apply, otherwise 0|
|uint16_t|[in]|fw_list_index|Index of the firmware in the Distributor's FW List|
|uint16_t|[in]|timeout_base|Timeout base|
|sl_btmesh_mbt_client_transfer_mode_t|[in]|transfer_mode|Transfer Mode to use in the distribution|
|uint16_t|[in]|node_count|Total number of target nodes which participates in the firmware distribution|

Called when firmware distribution is suspended

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_distribution_state_changed

`void sl_btmesh_fw_distribution_server_on_distribution_state_changed(uint16_t elem_index, sl_btmesh_fw_dist_server_dist_step_t state, uint16_t num_active_nodes, uint16_t node_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|sl_btmesh_fw_dist_server_dist_step_t|[in]|state|Distribution state|
|uint16_t|[in]|num_active_nodes|Number of target nodes which are still active|
|uint16_t|[in]|node_count|Total number of target nodes|

Called when firmware distribution state has changed

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_distribution_blob_progress_changed

`void sl_btmesh_fw_distribution_server_on_distribution_blob_progress_changed(uint16_t elem_index, uint32_t confirmed_tx_bytes, uint32_t blob_size, uint16_t node_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint32_t|[in]|confirmed_tx_bytes|Number of BLOB bytes which are received by every active BLOB Transfer Server. The progress is calculated at the end of the blocks because in a block some chunks could be retransmitted multiple times.|
|uint32_t|[in]|blob_size|Size of the BLOB|
|uint16_t|[in]|node_count|Number of target nodes|

Called when progress of BLOB transfer step during the firmware distribution has changed

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_distribution_node_failed

`void sl_btmesh_fw_distribution_server_on_distribution_node_failed(uint16_t elem_index, uint16_t server_address, sl_btmesh_fw_dist_server_dist_node_phase_t update_phase, sl_btmesh_fw_update_server_update_status_t update_status, uint8_t mbt_status, uint8_t progress, uint8_t fw_index, uint16_t num_active_nodes, uint16_t node_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|server_address|Unicast address of the failed Target Node|
|sl_btmesh_fw_dist_server_dist_node_phase_t|[in]|update_phase|Update Phase of Firmware Update Server on Target Node|
|sl_btmesh_fw_update_server_update_status_t|[in]|update_status|Update Status of Firmware Update Server on Target Node If the firmware update of the node fails due to Firmware Update Server related error then this field isn't zero and it has sl_btmesh_fw_update_server_update_status_t value.|
|uint8_t|[in]|mbt_status|Transfer status of BLOB Transfer server on Target Node. If the firmware update of a node fails due to BLOB Transfer error then this field won't be zero.|
|uint8_t|[in]|progress|0-100, percentage of BLOB Transfer octets|
|uint8_t|[in]|fw_index|Firmware image index on Target node which is updated during the distribution|
|uint16_t|[in]|num_active_nodes|Number of target nodes which are still active|
|uint16_t|[in]|node_count|Total number of target nodes|

Called when a Target Node fails during the distribution

If one node fails during the distribution, it does not mean, that the distribution fails as well. The distribution only fails, when every Target Node fails.

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_firmware_added

`void sl_btmesh_fw_distribution_server_on_firmware_added(uint16_t elem_index, uint16_t client_address, uint32_t fw_size, uint16_t fw_list_idx, uint16_t current_fw_list_length, uint16_t max_fw_list_length, const uint8_t *fwid, uint8_t fwid_length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client Set to unassigned address (0x0000) when the firmware is added at init time.|
|uint32_t|[in]|fw_size|Size of the firmware binary image|
|uint16_t|[in]|fw_list_idx|Index of the stored firmware in the firmware list|
|uint16_t|[in]|current_fw_list_length|Current number of stored firmware including this uploaded firmware as well.|
|uint16_t|[in]|max_fw_list_length|Maximum number of firmwares which can be stored on the Distributor|
|const uint8_t *|[in]|fwid|Firmware identifier with 2-byte Company ID which is followed by 0-106 bytes of Version Information|
|uint8_t|[in]|fwid_length|Length of the Firmware identifier data|

Called when firmware has been added to the Distributor

- Called when a new firmware has been uploaded to the Distributor
- Called when the firmware has been added based on the NVM content at initialization time

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_firmware_deleted

`void sl_btmesh_fw_distribution_server_on_firmware_deleted(uint16_t elem_index, uint16_t client_address, uint16_t current_fw_list_length, uint16_t max_fw_list_length, const uint8_t *fwid, uint8_t fwid_length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client|
|uint16_t|[in]|current_fw_list_length|Current number of stored firmwares after the firmware is deleted from the Distributor|
|uint16_t|[in]|max_fw_list_length|Maximum number of firmwares which can be stored on the Distributor|
|const uint8_t *|[in]|fwid|Firmware identifier with 2-byte Company ID which is followed by 0-106 bytes of Version Information|
|uint8_t|[in]|fwid_length|Length of the Firmware identifier data|

Called when a firmware has been deleted from the Distributor

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_on_all_firmware_deleted

`void sl_btmesh_fw_distribution_server_on_all_firmware_deleted(uint16_t elem_index, uint16_t client_address, uint16_t max_fw_list_length)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|elem_index|Distribution server model element index|
|uint16_t|[in]|client_address|Address of the Distribution Client It is set to MESH_ADDR_UNASSIGNED when it is caused by an internal event.|
|uint16_t|[in]|max_fw_list_length|Maximum number of firmwares which can be stored on the Distributor|

Called when ALL firmwares are deleted from the Distributor

This is a callback which can be implemented in the application **Note**

- If no implementation is provided in the application, then the default weak implementation will be an empty function.

###### sl_btmesh_fw_distribution_server_delete_step_handle

`void sl_btmesh_fw_distribution_server_delete_step_handle(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Used for asynchronously deleting firmware images from BLOB storage

#### Firmware Update Client

Provides BT Mesh Firmware Update Client functionality, defined in mesh specification. The Firmware Update Client model is used by the Distributor and Initiator. This component is prepared for integration into SOC applications. The Initiator uses this model to retrieve the information about the firmware subsystems installed on the Target node, and to get the location of the new firmware images. The Initiator receives the list of Target nodes from the higher-layer application. The Distributor uses this model to start a firmware image transfer to the Target nodes. The Distributor receives the list of Target nodes from the Initiator. The Distributor uses the procedures on the Firmware Update Client model with the inputs to these procedures being chosen by the Firmware Distribution Server. This is a No-Code component. 

##### Functions

###### sl_btmesh_firmware_update_client_on_event

`void sl_btmesh_firmware_update_client_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle Firmware Update Client events.

This function is called automatically after enabling the component.

#### Firmware Update Server

Provides BT Mesh Firmware Update Server functionality, defined in mesh specification. This model is used by the Target node to report the firmware images installed on the node and the location of new firmware images, and to initiate a firmware update in order to receive a new firmware. The firmware image will be transferred using the BLOB Transfer Server model. This component is prepared for integration into SOC applications. This is a No-Code component. 

##### Modules

[Btmesh_firmware_update_server_api](btmesh-firmware-update-server-api)

##### Functions

###### sl_btmesh_firmware_update_server_init

`void sl_btmesh_firmware_update_server_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the Firmware Update Server application layer component 

###### sl_btmesh_firmware_update_server_on_event

`void sl_btmesh_firmware_update_server_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|BT Mesh event|

Processes BT Mesh stack events for Firmware Update Server application

###### sl_btmesh_firmware_update_server_verify_step_handle

`void sl_btmesh_firmware_update_server_verify_step_handle(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Executes a step of firmware verification

**Note**

- Uses user API callouts.

###### sl_btmesh_firmware_update_server_metadata_check_step_handle

`void sl_btmesh_firmware_update_server_metadata_check_step_handle(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Executes a step of metadata check

**Note**

- Uses user API callouts.

##### Btmesh_firmware_update_server_api

BT Mesh Firmware Update Server user-overridable API 

###### Enumerations

###### sl_btmesh_fw_update_server_verify_state_e (heading level 7)

```
enum sl_btmesh_fw_update_server_verify_state_e {
    BTMESH_FW_UPDATE_SERVER_VERIFY_PENDING
    BTMESH_FW_UPDATE_SERVER_VERIFY_ERROR
    BTMESH_FW_UPDATE_SERVER_VERIFY_SUCCESS
}
```

**Description:**

Verification step results.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_FW_UPDATE_SERVER_VERIFY_PENDING|Verification pending.|
|BTMESH_FW_UPDATE_SERVER_VERIFY_ERROR|Verification error.|
|BTMESH_FW_UPDATE_SERVER_VERIFY_SUCCESS|Verification successful.|

###### sl_btmesh_fw_update_server_metadata_check_state_e (heading level 7)

```
enum sl_btmesh_fw_update_server_metadata_check_state_e {
    BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_PENDING
    BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_ERROR
    BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_SUCCESS
}
```

**Description:**

Metadata check step result.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_PENDING|Metadata check pending.|
|BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_ERROR|Metadata check error.|
|BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_SUCCESS|Metadata check successful.|

###### sl_btmesh_fw_update_server_additional_information_e (heading level 7)

```
enum sl_btmesh_fw_update_server_additional_information_e {
    BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_NO_CHANGE = 0x0
    BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_COMP_DATA_CHANGE_NO_REMOTE_PROV = 0x1
    BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_COMP_DATA_CHANGE_REMOTE_PROV = 0x2
    BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION = 0x3
    BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_RESERVED_START = 0x4
}
```

**Description:**

Definitions taken from BT Mesh Specification v1.1.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_NO_CHANGE|No changes to node composition data.|
|BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_COMP_DATA_CHANGE_NO_REMOTE_PROV|Node composition data changed. The node does not support remote provisioning.|
|BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_COMP_DATA_CHANGE_REMOTE_PROV|Node composition data changed, and remote provisioning is supported. The node supports remote provisioning and composition data page 0x80. Page 0x80 contains different composition data than page 0x0.|
|BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_UNPROVISION|Node unprovisioned. The node is unprovisioned after successful application of a verified firmware image.|
|BTMESH_FW_UPDATE_SERVER_ADDITIONAL_INFORMATION_RESERVED_START|Start of reserved values.|

###### Typedefs

###### sl_btmesh_fw_update_server_verify_state_t (heading level 7)

`typedef enum sl_btmesh_fw_update_server_verify_state_e sl_btmesh_fw_update_server_verify_state_t`

**Description:**

Verification step results.

###### sl_btmesh_fw_update_server_metadata_check_state_t (heading level 7)

`typedef enum sl_btmesh_fw_update_server_metadata_check_state_e sl_btmesh_fw_update_server_metadata_check_state_t`

**Description:**

Metadata check step result.

###### sl_btmesh_fw_update_server_additional_information_t (heading level 7)

`typedef enum sl_btmesh_fw_update_server_additional_information_e sl_btmesh_fw_update_server_additional_information_t`

**Description:**

Definitions taken from BT Mesh Specification v1.1.

###### Functions

###### sl_btmesh_fw_update_server_verify_start (heading level 7)

`sl_btmesh_fw_update_server_verify_state_t sl_btmesh_fw_update_server_verify_start(sl_bt_uuid_64_t const *const blob_id, uint8_t **const verify_chunk_buffer, uint32_t *const verify_chunk_size, const uint32_t blob_size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of the BLOB to be verified|
|uint8_t **const|[out]|verify_chunk_buffer|Verification buffer. User needs to pass the verification buffer to the framework. User also needs to free memory if it was allocated on heap, which could be done in [sl_btmesh_fw_update_server_apply](btmesh-firmware-update-server-api#sl-btmesh-fw-update-server-apply). If it's set to NULL, then no data is read from storage automatically during verification.|
|uint32_t *const|[out]|verify_chunk_size|Size of verification chunk. Progress calculation is based on this value.|
|const uint32_t|[in]|blob_size|Size of the BLOB to be verified|

User callback for determining the maximum chunk size of verification

Used to determine how big chunks can be for [sl_btmesh_fw_update_server_verify_step](btmesh-firmware-update-server-api#sl-btmesh-fw-update-server-verify-step)

**Returns**

- Current state of verification

**Return values**

- BTMESH_FW_UPDATE_SERVER_VERIFY_PENDING: If further processing required
- BTMESH_FW_UPDATE_SERVER_VERIFY_ERROR: In case of an error
- BTMESH_FW_UPDATE_SERVER_VERIFY_SUCCESS: In case verification is done and successful

###### sl_btmesh_fw_update_server_verify_step (heading level 7)

`sl_btmesh_fw_update_server_verify_state_t sl_btmesh_fw_update_server_verify_step(void const *data, const uint32_t len)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void const *|[in]|data|Buffered data|
|const uint32_t|[in]|len|Length of the buffer|

User callback to execute one step of the verification

Receives a chunk of data equal to or less in size defined with [sl_btmesh_fw_update_server_verify_start](btmesh-firmware-update-server-api#sl-btmesh-fw-update-server-verify-start)

**Returns**

- Current state of verification

**Return values**

- BTMESH_FW_UPDATE_SERVER_VERIFY_PENDING: If further processing required
- BTMESH_FW_UPDATE_SERVER_VERIFY_ERROR: In case of an error
- BTMESH_FW_UPDATE_SERVER_VERIFY_SUCCESS: In case verification is done and successful

###### sl_btmesh_fw_update_server_verify_progress_ui_update (heading level 7)

`void sl_btmesh_fw_update_server_verify_progress_ui_update(sl_btmesh_fw_update_server_verify_state_t status, uint32_t progress, uint32_t size)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_fw_update_server_verify_state_t](btmesh-firmware-update-server-api#sl-btmesh-fw-update-server-verify-state-t)|[in]|status|Verification status|
|uint32_t|[in]|progress|Number of verified bytes|
|uint32_t|[in]|size|Total number of bytes which shall be verified|

User callback to update the user interface with verification progress

If `FW_UPDATE_SERVER_VERIFY_PROGRESS_UI_UPDATE_PERIOD` is not zero then it specifies the period of this function call in order to limit the user interface update rate. If the macro is zero then this function is called whenever verification is active and progress is made. 

###### sl_btmesh_fw_update_server_metadata_check_start (heading level 7)

`sl_btmesh_fw_update_server_metadata_check_state_t sl_btmesh_fw_update_server_metadata_check_start(void const *metadata, const uint8_t len, sl_btmesh_fw_update_server_additional_information_t *const additional_information)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void const *|[in]|metadata|Buffered metadata|
|const uint8_t|[in]|len|Metadata length|
|[sl_btmesh_fw_update_server_additional_information_t](btmesh-firmware-update-server-api#sl-btmesh-fw-update-server-additional-information-t) *const|[out]|additional_information|Used in BT Mesh response to metadata check|

User callback indicating start of metadata check

**Returns**

- Current state of metadata check

**Return values**

- BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_PENDING: If further processing required
- BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_ERROR: In case of an error
- BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_SUCCESS: In case metadata check is done and successful

###### sl_btmesh_firmware_update_server_metadata_check_step (heading level 7)

`sl_btmesh_fw_update_server_metadata_check_state_t sl_btmesh_firmware_update_server_metadata_check_step(sl_btmesh_fw_update_server_additional_information_t *additional_information)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_btmesh_fw_update_server_additional_information_t](btmesh-firmware-update-server-api#sl-btmesh-fw-update-server-additional-information-t) *|[out]|additional_information|Used in BT Mesh response to metadata check|

User callback executing one step of metadata check

**Returns**

- Current state of metadata check

**Return values**

- BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_PENDING: If further processing required
- BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_ERROR: In case of an error
- BTMESH_FW_UPDATE_SERVER_METADATA_CHECK_SUCCESS: In case metadata check is done and successful

###### sl_btmesh_fw_update_server_update_start (heading level 7)

`void sl_btmesh_fw_update_server_update_start(sl_bt_uuid_64_t const *const blob_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_bt_uuid_64_t const *const|[in]|blob_id|Identifier of the BLOB containing firmware|

User callback indicating update start

Called after metadata check is done.

Can be redefined to accommodate user application functionality.

###### sl_btmesh_fw_update_server_update_canceled (heading level 7)

`void sl_btmesh_fw_update_server_update_canceled(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

User callback indicating update cancellation

Can be redefined to accommodate user application functionality. 

###### sl_btmesh_fw_update_server_update_aborted (heading level 7)

`void sl_btmesh_fw_update_server_update_aborted(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

User callback indicating update abort

Can be redefined to accommodate user application functionality. 

###### sl_btmesh_fw_update_server_apply (heading level 7)

`void sl_btmesh_fw_update_server_apply(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

User callback indicating firmware apply request

Can be redefined to accommodate user application functionality. 

###### mesh_platform_get_installed_firmware_information (heading level 7)

`sl_status_t mesh_platform_get_installed_firmware_information(uint8_t index, uint8_t *fwid_len, const uint8_t **fwid_ptr, uint8_t *uri_len, const uint8_t **uri_ptr)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|index|DFU Storage index|
|uint8_t *|[out]|fwid_len|Length of the firmware ID|
|const uint8_t **|[out]|fwid_ptr|Pointer to the firmware ID|
|uint8_t *|[out]|uri_len|Length of the Uniform Resource Identifier (URI)|
|const uint8_t **|[out]|uri_ptr|Pointer to the Uniform Resource Identifier (URI)|

Used to retrieve information about firmware stored on the device for DFU **Returns**

- SL_STATUS_OK if successful, SL_STATUS_BT_MESH_DOES_NOT_EXIST if the index is invalid

### DFU Roles

This group includes components that define and manage the roles of devices in a Bluetooth Mesh network for Device Firmware Update (DFU). These components enable seamless integration into SOC applications and provide functionality for DFU distributors and target nodes. 

#### Modules

[DFU distributor](btmesh-distributor)

[DFU target node](btmesh-target-node)

#### DFU distributor

Wrapper software component for DFU distributor role in Bluetooth Mesh applications. This component is prepared for integration into SOC applications.

#### DFU target node

Wrapper software component for DFU target node role in Bluetooth Mesh applications. This component is prepared for integration into SOC applications.

### Bluetooth Mesh

This group encompasses components and functionalities related to Bluetooth Mesh networking. These components are designed for seamless integration into SOC and NCP applications, offering both No-Code implementations to simplify development. 

#### Modules

[Btmesh Automatic IV update](btmesh-iv-update)

#### Btmesh Automatic IV update

This component provides 3 optional functionalities:

- periodic IV Update age backup. Restore on reset.
- automatic IV Update request, if a sequence number exceeds a threshold.
- automatic IV Update request, after a configured time in Normal operation. Turning on this component may increase power consumption. This component is prepared for integration into SOC applications. This is a No-Code component.

##### Functions

###### sl_btmesh_iv_update_on_event

`void sl_btmesh_iv_update_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handling of mesh iv_update related events. 

###### sl_btmesh_iv_update_age_backup_on_event

`void sl_btmesh_iv_update_age_backup_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handling of mesh iv_update_age_backup related events. 

###### sl_btmesh_iv_update_on_node_reset

`void sl_btmesh_iv_update_on_node_reset(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Component node reset handler. Clearing component specific nvm content during node reset. This function is called automatically by Universal Configurator after enabling the component. 

###### sl_btmesh_iv_update_by_age_on_event

`void sl_btmesh_iv_update_by_age_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handling of mesh iv_update_by_age related events. 

###### get_iv_update_age

`uint32_t get_iv_update_age(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Weak function. Implementation should return the current IV Update age. Weak implementation returns zero. It is only called on node init event. iv_update_age_backup implements this function if it is enabled. **Returns**

- IV Update age in seconds

###### sl_btmesh_iv_update_by_seq_num_on_event

`void sl_btmesh_iv_update_by_seq_num_on_event(sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|sl_btmesh_msg_t *|[in]|evt|Pointer to incoming event.|

Handling of mesh iv_update_by_seq_num related events.

### Large Composition Data

This group includes components that enable the automatic generation of Models Metadata Page 0 for Silicon Labs components providing SIG models. These components are designed for seamless integration into SOC applications and simplify the management of large composition data in Bluetooth Mesh networks. 

#### Modules

[Large Composition Data Server](btmesh-lcd-server)

#### Large Composition Data Server

A thin wrapper of the Bluetooth Mesh Stack Large Composition Data component. This component enables automatic Models Metadata Page 0 generation for Silicon Labs components providing SIG models.

### Proxy Solicitation

This group includes components that handle the proxy solicitation functionality in Bluetooth Mesh, which is responsible for managing the process of soliciting proxy nodes in the network. 

#### Modules

[Bluetooth Mesh Solicitation PDU RPL Config Client](btmesh-solicitation-config-client)

#### Bluetooth Mesh Solicitation PDU RPL Config Client

Provides a thin layer to automatically initialize the Solicitation PDU RPL Config Client model. The model then can be used to remove addresses from the solicitation replay protection list of a node that supports the Solicitation PDU RPL Configuration Server model. This is a No-Code component. 

##### Functions

###### sl_btmesh_solicitation_config_client_on_event

`void sl_btmesh_solicitation_config_client_on_event(const sl_btmesh_msg_t *const evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *const|[in]|evt|Pointer to incoming event.|

Handle Solicitation Config Client events.

This function is called automatically after enabling the component.

### BT Mesh Configurator Component

Robust execution of configuration jobs over BT Mesh Stack. 

BT Mesh configuration jobs can be created from one or more configuration tasks. In order to create configuration jobs and tasks the following header files shall be checked:

- BT Mesh Configuration Job interface can be found in btmesh_conf_job.h header file ([BT Mesh Configuration Job](btmesh-conf-job) group).
- BT Mesh Configuration Task interface can be found in btmesh_conf_task.h header file ([BT Mesh Configuration Task](btmesh-conf-task) group).

The created jobs can be submitted for execution to BT Mesh Configurator by calling the [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job).

If the application provides a callback ([btmesh_conf_on_job_notification_t](btmesh-conf-job#btmesh-conf-on-job-notification-t)) when it creates the configuration job then the application is notified about changed job status. <br />
 The [btmesh_conf_job_t::result](btmesh-conf-job-t#result) can be checked in the notification callback to figure out if the configuration job was successful or not. The allocation and deallocation and ownership of configuration jobs are described in [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job).

There are some common configuration use cases when the execution of job with a single configuration task is necessary. Some utility functions are provided in order to simplify the submission of these common configuration jobs:

- [btmesh_conf_dcd_get](btmesh-conf#btmesh-conf-dcd-get)
- [btmesh_conf_reset_node](btmesh-conf#btmesh-conf-reset-node)

These utility functions create configuration jobs and tasks and submit them with [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job) function the same way as the application would do. The finished configuration job which is created by utility function is deallocated automatically. 

#### Modules

[BT Mesh Configuration Distributor](btmesh-conf-distributor)

[BT Mesh Configuration Executor](btmesh-conf-executor-1)

[BT Mesh Configuration Job](btmesh-conf-job)

[BT Mesh Configuration Task](btmesh-conf-task)

[BT Mesh Configuration Types](btmesh-conf-types)

#### Enumerations

##### btmesh_conf_sig_model_attr_bitmask_t

```
enum btmesh_conf_sig_model_attr_bitmask_t {
    BTMESH_CONF_SIG_MODEL_ATTRIBUTES_NONE = 0
    BTMESH_CONF_SIG_MODEL_SUPPORTS_SUBSCRIPTION = (1 << 0)
    BTMESH_CONF_SIG_MODEL_SUPPORTS_PUBLICATION = (1 << 1)
    BTMESH_CONF_SIG_MODEL_SUPPORTS_APPKEY_BINDING = (1 << 2)
}
```

**Description:**

Information about the supported configuration operations on a model.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_CONF_SIG_MODEL_ATTRIBUTES_NONE|No attribute flags.|
|BTMESH_CONF_SIG_MODEL_SUPPORTS_SUBSCRIPTION|Subscription supported.|
|BTMESH_CONF_SIG_MODEL_SUPPORTS_PUBLICATION|Publication supported.|
|BTMESH_CONF_SIG_MODEL_SUPPORTS_APPKEY_BINDING|Application key binding supported.|

#### Functions

##### btmesh_conf_init

`sl_status_t btmesh_conf_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the BT Mesh Configurator component

**Returns**

- Status of the initialization.

**Return values**

- SL_STATUS_OK: If the initialization is successful.
- SL_STATUS_ALLOCATION_FAILED: If the dynamic memory allocation of internal data structures is failed.
- SL_STATUS_INVALID_CONFIGURATION: If the configured model information is not valid. (array elems are not arranged in ascending order by model ID)

The initialization is performed automatically when the BT Mesh Stack triggers the sl_btmesh_evt_prov_initialized_id event. The application code shall call this function if it deinitialized the configurator component beforehand ([btmesh_conf_deinit](btmesh-conf#btmesh-conf-deinit)). 

##### btmesh_conf_deinit

`sl_status_t btmesh_conf_deinit(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Deinitialize the BT Mesh Configurator component

**Returns**

- Status of the deinitialization.

**Return values**

- SL_STATUS_OK: If the deinitialization is successful.
- SL_STATUS_INVALID_STATE: If the deinitialization can't be started because it is initiated from [btmesh_conf_job_t::on_job_notification](btmesh-conf-job-t#on-job-notification) callback.

Deallocates the internal data structures and stops the processing of BT Mesh stack events. Deinitialization shall not be called from [btmesh_conf_job_t::on_job_notification](btmesh-conf-job-t#on-job-notification) callback. 

##### btmesh_conf_submit_job

`sl_status_t btmesh_conf_submit_job(btmesh_conf_job_t *job)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_job_t](btmesh-conf-job-t) *|[in]|job|Configuration job which aggregates the configuration tasks|

Submit a configuration job for execution

**Returns**

- Status of the job submission.

**Return values**

- SL_STATUS_OK: If the job is submitted successfully.
- SL_STATUS_INVALID_STATE: If the BT Mesh configurator is not initialized.

Each configuration job aggregates configuration tasks which targets the same remote node (configuration server model).

If a configuration job is submitted to the BT Mesh Configurator then it is added to the end of a wait queue. Therefore it is not guaranteed that the execution a job is started immediately. Configuration jobs with the same server addresses are executed in the order of submission however jobs with different server addresses might be executed in parallel.

If the submit operation is successful then the BT Mesh Configurator takes over the ownership of the job and consequently the application is no longer allowed to modify the submitted job or its tasks. If the submit operation fails and [btmesh_conf_job_t::auto_destroy](btmesh-conf-job-t#auto-destroy) is set and SL_BTMESH_CONF_JOB_AUTO_DESTROY_ON_SUBMIT_FAILURE_CFG_VAL is turned on then the job is deallocated automatically in the submit call and consequently the job shall not be referenced when the submit returns with failure.

If task execution path ends in the configuration job then the job ends as well and [btmesh_conf_job_t::on_job_notification](btmesh-conf-job-t#on-job-notification) callback is called with the result. The [btmesh_conf_job_t::result](btmesh-conf-job-t#result) structure member contains the result of the job. If the [btmesh_conf_job_t::auto_destroy](btmesh-conf-job-t#auto-destroy) is set to true then the job and its tasks are deallocated automatically after the callback returns.

**Warnings**

- If the auto destroy feature is used then the job shall not be referenced after the callback is executed.

**Note**

- Te BT Mesh Stack does not allow the parallel execution of two configuration requests with the same server address (primary element). The limitation is added to the BT Mesh Stack because the configuration messages don't contain any transaction identifier in accordance with BT Mesh Profile specification so the status messages could not be differentiated.

##### btmesh_conf_dcd_get

`sl_status_t btmesh_conf_dcd_get(uint16_t netkey_index, uint16_t server_address, uint8_t page, btmesh_conf_on_job_notification_t on_job_notification)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key used to encrypt request on network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|uint8_t|[in]|page|Composition data page to query|
|[btmesh_conf_on_job_notification_t](btmesh-conf-job#btmesh-conf-on-job-notification-t)|[in]|on_job_notification|Callback to notify the app about job status|

Submit a configuration job with a DCD get task

**Returns**

- Status of the DCD get request.

**Return values**

- SL_STATUS_OK: If the job is submitted successfully.
- SL_STATUS_INVALID_STATE: If the BT Mesh configurator is not initialized.
- SL_STATUS_ALLOCATION_FAILED: If allocation of job or task is failed.

Configuration job with DCD get task is created automatically and submitted for execution. The allocation and deallocation of task and job is handled automatically in this function.

**Note**

- It is a quite common usecase to get the DCD first and based on the content of the DCD further configuration tasks are defined and executed. <br />  
   This utility function makes it easier to get the DCD however it is possible to query the DCD with the following (basic) API calls as well:  
  - [btmesh_conf_task_dcd_get_create](btmesh-conf-task#btmesh-conf-task-dcd-get-create)  
  - [btmesh_conf_job_create](btmesh-conf-job#btmesh-conf-job-create)  
  - [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job)

##### btmesh_conf_reset_node

`sl_status_t btmesh_conf_reset_node(uint16_t netkey_index, uint16_t server_address, btmesh_conf_on_job_notification_t on_job_notification)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key used to encrypt request on network layer|
|uint16_t|[in]|server_address|Destination node primary element address|
|[btmesh_conf_on_job_notification_t](btmesh-conf-job#btmesh-conf-on-job-notification-t)|[in]|on_job_notification|Callback to notify the app about job status|

Submit a configuration job with a reset node task

**Returns**

- Status of the reset node request.

**Return values**

- SL_STATUS_OK: If the job is submitted successfully.
- SL_STATUS_INVALID_STATE: If the BT Mesh configurator is not initialized.
- SL_STATUS_ALLOCATION_FAILED: If allocation of job or task is failed.

Configuration job with reset node task is created automatically and submitted for execution. The allocation and deallocation of task and job is handled automatically in this function.

**Note**

- This utility function makes it easier to reset a node however it is possible to reset a node with the following (basic) API calls as well:  
  - [btmesh_conf_task_reset_node_create](btmesh-conf-task#btmesh-conf-task-reset-node-create)  
  - [btmesh_conf_job_create](btmesh-conf-job#btmesh-conf-job-create)  
  - [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job)

##### btmesh_conf_on_event

`void btmesh_conf_on_event(const sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *|[in]|evt|BT Mesh Stack event|

BT Mesh Configurator event handler

The BT Mesh Configurator event handler shall be called with event provided sl_btmesh_pop_event or sl_btmesh_wait_event BT Mesh Stack API functions. 

##### btmesh_conf_step

`void btmesh_conf_step(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Process one step of BT Mesh Configurator

The step API shall be called periodically from the main loop of the application. 

##### btmesh_conf_on_job_notification

`void btmesh_conf_on_job_notification(btmesh_conf_job_t *const job)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_job_t](btmesh-conf-job-t) *const|[in]|job|Reference of the job with changed status|

Job status notification callback for lower layers

This callback is called when the status of the job changes because its execution is ended. The result of the job is provided in the [btmesh_conf_job_t::result](btmesh-conf-job-t#result) structure member. This callback calls [btmesh_conf_job_t::on_job_notification](btmesh-conf-job-t#on-job-notification) with the `job` to notify the application. If [btmesh_conf_job_t::on_job_notification](btmesh-conf-job-t#on-job-notification) is NULL then the application is not notified. 

##### btmesh_conf_get_handle_from_event

`sl_status_t btmesh_conf_get_handle_from_event(const sl_btmesh_msg_t *evt, uint32_t *handle)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const sl_btmesh_msg_t *|[in]|evt|BT Mesh Stack event|
|uint32_t *|[out]|handle|Handle from configuration client event is stored here|

Provides the handle value from Configuration Client events of BT Mesh Stack

**Returns**

- Status of the handle retrieval from event.

**Return values**

- SL_STATUS_OK: If config client handle is retrieved successfully.
- SL_STATUS_NOT_FOUND: If the given event is not a config client event.
- SL_STATUS_NULL_POINTER: If any of its parameter is a NULL pointer.

##### btmesh_conf_get_sig_model_attributes

`sl_status_t btmesh_conf_get_sig_model_attributes(uint16_t model_id, btmesh_conf_sig_model_attr_bitmask_t *attributes)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|model_id|Model ID for the BT Mesh SIG model|
|[btmesh_conf_sig_model_attr_bitmask_t](btmesh-conf#btmesh-conf-sig-model-attr-bitmask-t) *|[out]|attributes|Attributes of the model is stored here|

Provide the model attributes of the given BT Mesh SIG model ID

**Returns**

- Status of the get model attributes.

**Return values**

- SL_STATUS_OK: If model attributes are provided successfully.
- SL_STATUS_NOT_FOUND: If the model ID is unknown.
- SL_STATUS_NULL_POINTER: If NULL pointer is given as attributes.

##### btmesh_conf_sig_model_id_to_string

`const char * btmesh_conf_sig_model_id_to_string(uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|model_id|Model ID for the BT Mesh SIG model|

Return string representation of the given BT Mesh SIG model ID

**Returns**

- String representation of BT Mesh SIG model ID (model name)

**Return values**

- UnknownSigModel: If the model ID is unknown.

**Note**

- This function always returns a valid string which makes it easier to use this function with snprintf like functions because those expects valid (non-NULL) for s format specifier.

##### btmesh_conf_is_configuration_event

`bool btmesh_conf_is_configuration_event(uint32_t event_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|event_id|Identifier of the given BT Mesh Stack event|

Check if a given BT Mesh Stack event is a configuration client event

##### btmesh_conf_any_severe_log_level

`bool btmesh_conf_any_severe_log_level(uint8_t start_level)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|start_level|Least severe log level checked|

Check if a given log level or other more severe log levels are enabled

#### BT Mesh Configuration Distributor

BT Mesh Configuration Distributor supports the parallel execution of multiple configuration jobs by distributing the jobs between executors. 

BT Mesh Configuration Distributor instance is created by calling the [btmesh_conf_distributor_create](btmesh-conf-distributor#btmesh-conf-distributor-create) function. The specified number (`executor_count`) of [BT Mesh Configuration Executor](btmesh-conf-executor-1) instances are created which are assigned to the created distributor instance (composition).

BT Mesh Configuration jobs can be submitted to configuration distributor with [btmesh_conf_distributor_submit_job](btmesh-conf-distributor#btmesh-conf-distributor-submit-job) function which stores the job in a wait queue.

The configuration jobs are assigned to executors from the wait queue during distributor scheduling process. The BT Mesh Stack does not support parallel execution of two configuration job with the same server address. Therefore, the scheduling process guarantees that the configuration jobs with the same server addresses are executed one-by-one in the order of submission however jobs with different server addresses might be executed in parallel.

The configuration executors report the job status through [btmesh_conf_distributor_on_job_notification](btmesh-conf-distributor#btmesh-conf-distributor-on-job-notification) function.

**Note**

- The BT Mesh Stack does not allow the parallel execution of two configuration requests with the same server address (primary element). The limitation is added to the BT Mesh Stack because the configuration messages don't contain any transaction identifier in accordance with BT Mesh Profile specification so the status messages could not be differentiated.

##### Modules

[btmesh_conf_distributor_t](btmesh-conf-distributor-t)

##### Functions

###### btmesh_conf_distributor_create

`btmesh_conf_distributor_t * btmesh_conf_distributor_create(uint16_t executor_count)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|executor_count|Number of configuration executors which shall be created and added to this distributor instance.|

Create BT Mesh Configuration Distributor instance with the specified number of configuration executors.

**Returns**

- Created configuration distributor.

**Return values**

- NULL: If the configuration distributor creation fails.

###### btmesh_conf_distributor_destroy

`void btmesh_conf_distributor_destroy(btmesh_conf_distributor_t *const self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_distributor_t](btmesh-conf-distributor-t) *const|[in]|self|Pointer to configuration distributor which shall be destroyed|

Deallocate the BT Mesh Configuration Distributor instance

###### btmesh_conf_distributor_submit_job

`sl_status_t btmesh_conf_distributor_submit_job(btmesh_conf_distributor_t *const self, btmesh_conf_job_t *job)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_distributor_t](btmesh-conf-distributor-t) *const|[in]|self|Pointer to the configuration distributor instance|
|[btmesh_conf_job_t](btmesh-conf-job-t) *|[in]|job|Configuration job which aggregates the configuration tasks|

Submit a configuration job for execution

**Returns**

- Status of the job submission.

**Return values**

- SL_STATUS_OK: If the job is submitted successfully.

BT Mesh Configuration Distributor appends the submitted configuration job to the wait queue and requests a deferred scheduling in order to assign the job to an idle [BT Mesh Configuration Executor](btmesh-conf-executor-1). If all executors are busy then the configuration job remains in the wait queue until an executor transitions to idle state and there is no previously submitted configuration jobs which can be started.

It is important to note that a configuration job might be executed sooner than another configuration job which was submitted earlier if the latter configurator job can't be started because one executor runs a third configuration job with the same server address.

If the execution of a configuration job is finished then the configuration executor calls the [btmesh_conf_distributor_on_job_notification](btmesh-conf-distributor#btmesh-conf-distributor-on-job-notification) to notify the distributor. 

###### btmesh_conf_distributor_on_job_notification

`void btmesh_conf_distributor_on_job_notification(btmesh_conf_distributor_t *const self, btmesh_conf_executor_t *const executor, btmesh_conf_job_t *const job)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_distributor_t](btmesh-conf-distributor-t) *const|[in]|self|Pointer to the configuration distributor instance|
|[btmesh_conf_executor_t](btmesh-conf-executor-1#btmesh-conf-executor-t) *const|[in]|executor|Pointer to the executor which ran the configuration job|
|[btmesh_conf_job_t](btmesh-conf-job-t) *const|[in]|job|Pointer to the job with changed status|

BT Mesh Configuration Distributor job status notification callback for [BT Mesh Configuration Executor](btmesh-conf-executor-1)

This callback is called when the status of the job changes because its execution is ended. 

###### btmesh_conf_distributor_on_event

`void btmesh_conf_distributor_on_event(btmesh_conf_distributor_t *const self, const sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_distributor_t](btmesh-conf-distributor-t) *const|[in]|self|Pointer to the configuration distributor instance|
|const sl_btmesh_msg_t *|[in]|evt|BT Mesh Stack event|

Event handler of BT Mesh Configuration Distributor instance

BT Mesh Configuration Distributor forwards the BT Mesh Stack events to all of its [BT Mesh Configuration Executor](btmesh-conf-executor-1) instances by calling the [btmesh_conf_executor_on_event](btmesh-conf-executor-1#btmesh-conf-executor-on-event) function with each configuration executor instance. 

###### btmesh_conf_distributor_step

`void btmesh_conf_distributor_step(btmesh_conf_distributor_t *const self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_distributor_t](btmesh-conf-distributor-t) *const|[in]|self|Pointer to the configuration distributor instance|

Process one step of BT Mesh Configurator

The step function shall be called periodically by higher layer to perform deferred scheduling.

BT Mesh Configuration Distributor supports the parallel execution of multiple configuration jobs by distributing the jobs between executors. 

###### Public Attributes

###### waiting_jobs (heading level 7)

```
sl_slist_node_t* btmesh_conf_distributor_t::waiting_jobs
```

**Description:** List of waiting jobs.

###### executor_count (heading level 7)

```
uint16_t btmesh_conf_distributor_t::executor_count
```

**Description:** Number of [BT Mesh Configuration Executor](btmesh-conf-executor-1) which belongs to this distributor.

###### executors (heading level 7)

```
btmesh_conf_executor_t** btmesh_conf_distributor_t::executors
```

**Description:** Array of [BT Mesh Configuration Executor](btmesh-conf-executor-1) references. <br />
 Array of pointers are used in order to make it possible to allocate the executor instances by calling the [btmesh_conf_executor_create](btmesh-conf-executor-1#btmesh-conf-executor-create) function.

###### deferred_schedule_request (heading level 7)

```
bool btmesh_conf_distributor_t::deferred_schedule_request
```

**Description:** Deferred schedule request flag is set when new configuration jobs are submitted in order to indicate the [btmesh_conf_distributor_step](btmesh-conf-distributor#btmesh-conf-distributor-step) shall schedule the waiting jobs.

#### BT Mesh Configuration Executor

BT Mesh Configuration Executor executes configuration jobs by executing the tasks in the task tree of the configuration job. 

Each executor shall have one parent [BT Mesh Configuration Distributor](btmesh-conf-distributor). Parent distributor can command the executor to start configuration job execution by calling [btmesh_conf_executor_start_job](btmesh-conf-executor-1#btmesh-conf-executor-start-job) function. The configuration executor reports the status of job execution by calling [btmesh_conf_distributor_on_job_notification](btmesh-conf-distributor#btmesh-conf-distributor-on-job-notification) function of parent distributor.

The relationship between the configuration distributor and its executors is composition so the executors are owned by its parent distributor completely. Only the parent distributor is allowed to start configuration jobs because the executors always report its job statuses to the parent distributor.

The robust execution of configuration tasks is guaranteed by the retry mechanism of the executor. <br />
 Retry mechanism is used in the following cases:

- Configuration request timeout in the BT Mesh Stack due to the following:  
  - BT Mesh message sent to the configuration server is lost  
  - BT Mesh status message sent by the configuration server is lost
- Configuration event is not received maybe due to event lost over NCP communication (quite rare)
- Configuration request is busy due to unavailable resources in the BT Mesh Stack

##### Modules

[btmesh_conf_executor_status_t](btmesh-conf-executor-status-t)

[btmesh_conf_executor](btmesh-conf-executor)

##### Enumerations

###### btmesh_conf_executor_state_t

```
enum btmesh_conf_executor_state_t {
    BTMESH_CONF_EXEC_STATE_IDLE
    BTMESH_CONF_EXEC_STATE_TASK_SET
    BTMESH_CONF_EXEC_STATE_TASK_EVENT_WAIT
    BTMESH_CONF_EXEC_STATE_TASK_REQUEST_BUSY
    BTMESH_CONF_EXEC_STATE_COUNT
}
```

**Description:**

State constants of BT Mesh Configuration Executor.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_CONF_EXEC_STATE_IDLE|Configuration Executor is ready to execute waiting configuration jobs.|
|BTMESH_CONF_EXEC_STATE_TASK_SET|Configuration Executor advanced to the next configuration task.|
|BTMESH_CONF_EXEC_STATE_TASK_EVENT_WAIT|Configuration Executor forwards events to current task and waits for result.|
|BTMESH_CONF_EXEC_STATE_TASK_REQUEST_BUSY|Configuration Executor waits the retry time because the previous task request was busy due to unavailable resources.|
|BTMESH_CONF_EXEC_STATE_COUNT|Number of Configuration Executor states.|

##### Typedefs

###### btmesh_conf_distributor_t

`typedef struct btmesh_conf_distributor_t btmesh_conf_distributor_t`

###### btmesh_conf_executor_state_t

`typedef enum btmesh_conf_executor_state_t btmesh_conf_executor_state_t`

**Description:**

State constants of BT Mesh Configuration Executor.

###### btmesh_conf_executor_status_t

`typedef struct btmesh_conf_executor_status_t btmesh_conf_executor_status_t`

**Description:**

Current status of Configuration Executor.

###### btmesh_conf_executor_t

`typedef struct btmesh_conf_executor btmesh_conf_executor_t`

**Description:**

BT Mesh Configuration Executor executes configuration jobs by executing the tasks in the task tree of the configuration job.

##### Functions

###### btmesh_conf_executor_create

`btmesh_conf_executor_t * btmesh_conf_executor_create(uint16_t id, btmesh_conf_distributor_t *const parent)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|id|Identifier of BT Mesh Configuration Executor instance|
|[btmesh_conf_distributor_t](btmesh-conf-distributor-t) *const|[in]|parent|BT Mesh Configuration Distributor which executor belongs to|

Create BT Mesh Configuration Executor instance which belongs to the specified configuration distributor

**Returns**

- Created configuration executor.

**Return values**

- NULL: If the configuration executor creation fails.

BT Mesh Configuration Executor is allocated and initialized with the provided BT Mesh Configuration Distributor parent. The initialized configuration executor is in idle state and therefore it does not execute any jobs. The identifier of configuration executor shall be unique in the context of parent configuration distributor. 

###### btmesh_conf_executor_destroy

`void btmesh_conf_executor_destroy(btmesh_conf_executor_t *const self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_executor_t](btmesh-conf-executor-1#btmesh-conf-executor-t) *const|[in]|self|Pointer to the configuration executor which shall be destroyed|

Deallocates the BT Mesh Configuration Executor instance

If the configuration executor runs a configuration job then the job and all of its tasks are deallocated as well. 

###### btmesh_conf_executor_start_job

`sl_status_t btmesh_conf_executor_start_job(btmesh_conf_executor_t *const self, btmesh_conf_job_t *job)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_executor_t](btmesh-conf-executor-1#btmesh-conf-executor-t) *const|[in]|self|Pointer to the configuration executor instance|
|[btmesh_conf_job_t](btmesh-conf-job-t) *|[in]|job|Configuration job which shall be started|

Start execution of the specified configuration job in a BT Mesh Configuration Executor instance

**Returns**

- Status of configuration job execution start.

**Return values**

- SL_STATUS_OK: If the configuration job is started properly.
- SL_STATUS_INVALID_STATE: If the executor is busy with the execution of another configuration job.
- SL_STATUS_NOT_FOUND: If the first task of configuration job could not be set.
- SL_STATUS_FAIL: If one or more configuration requests are failed and no further configuration task remains in the task tree which can be executed.

###### btmesh_conf_executor_get_status

`void btmesh_conf_executor_get_status(btmesh_conf_executor_t *const self, btmesh_conf_executor_status_t *status)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_executor_t](btmesh-conf-executor-1#btmesh-conf-executor-t) *const|[in]|self|Pointer to the configuration executor instance|
|[btmesh_conf_executor_status_t](btmesh-conf-executor-status-t) *|[out]|status|Pointer where status of the executor instance is written|

Get status BT Mesh Configuration Executor instance

###### btmesh_conf_executor_on_event

`void btmesh_conf_executor_on_event(btmesh_conf_executor_t *const self, const sl_btmesh_msg_t *evt)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_executor_t](btmesh-conf-executor-1#btmesh-conf-executor-t) *const|[in]|self|Pointer to the configuration executor instance|
|const sl_btmesh_msg_t *|[in]|evt|BT Mesh Stack event|

Event handler of BT Mesh Configuration Executor instance

The BT Mesh Configuration Executor event handler forwards events to the current task of the configuration job which is executed at the moment. If the event is a configuration event then it is forwarded only if the handle in the event matches the handle returned by the last configuration BT Mesh Stack request which belongs to the same configuration task.

Current status of Configuration Executor. 

###### Public Attributes

###### state (heading level 7)

```
btmesh_conf_executor_state_t btmesh_conf_executor_status_t::state
```

**Description:** State of Configuration Executor.

###### enc_netkey_index (heading level 7)

```
uint16_t btmesh_conf_executor_status_t::enc_netkey_index
```

**Description:** Network key index of the executed configuration job <br />
 It is valid if the `state` is not [BTMESH_CONF_EXEC_STATE_IDLE](btmesh-conf-executor-1#btmesh-conf-exec-state-idle).

###### server_address (heading level 7)

```
uint16_t btmesh_conf_executor_status_t::server_address
```

**Description:** Destination node primary element address of executed configuration job <br />
 It is valid if the `state` is not [BTMESH_CONF_EXEC_STATE_IDLE](btmesh-conf-executor-1#btmesh-conf-exec-state-idle).

BT Mesh Configuration Executor executes configuration jobs by executing the tasks in the task tree of the configuration job. 

###### Public Attributes

###### parent (heading level 7)

```
btmesh_conf_distributor_t* btmesh_conf_executor::parent
```

**Description:** BT Mesh Configuration Distributor which the executor belongs to.

###### current_job (heading level 7)

```
btmesh_conf_job_t* btmesh_conf_executor::current_job
```

**Description:** Pointer to configuration job which is executed.

###### handle (heading level 7)

```
uint32_t btmesh_conf_executor::handle
```

**Description:** BT Mesh stack configuration handle which is returned by the last configuration request (BT Mesh Stack API call). Configuration executor processes those configuration events only which matches this handle.

###### state (heading level 7)

```
btmesh_conf_executor_state_t btmesh_conf_executor::state
```

**Description:** Current state of the configuration executor.

###### id (heading level 7)

```
uint16_t btmesh_conf_executor::id
```

**Description:** Identifier of BT Mesh Configuration Executor instance. <br />
 The identifier of configuration executor instance shall be unique in the context of parent configuration distributor.

###### local_retry_counter (heading level 7)

```
uint16_t btmesh_conf_executor::local_retry_counter
```

**Description:** Number of configuration task request retries were executed due to busy BT Mesh Stack. The BT Mesh Stack might reject configuration client requests temporarily due to lack of resources. For example maximum number of parallel segmented message transmissions is reached. <br />
 The local refers to the fact that no messages were sent to the configuration server because the BT Mesh Stack did not accept the request.

###### local_retry_max (heading level 7)

```
uint16_t btmesh_conf_executor::local_retry_max
```

**Description:** Maximum number of configuration task request retries were executed due to busy BT Mesh Stack. <br />
 The local refers to the fact that no messages were sent to the configuration server because the BT Mesh Stack did not accept the request.

###### communication_retry_counter (heading level 7)

```
uint16_t btmesh_conf_executor::communication_retry_counter
```

**Description:** Number of configuration task request retries were executed already due to BT Mesh Stack timeout. An ongoing BT Mesh Stack configuration client request might timeout because the configuration request message sent to the configuration server or the configuration status message sent back to the configuration client is lost. This counter is cleared at the beginning of each configuration task of the configuration job.

###### communication_retry_max (heading level 7)

```
uint16_t btmesh_conf_executor::communication_retry_max
```

**Description:** Maximum number of configuration task request retries due to BT Mesh Stack timeout which indicates lost configuration messages.

###### timer (heading level 7)

```
app_timer_t btmesh_conf_executor::timer
```

**Description:** Timer to measure event timeout and configuration request retry interval.

###### timer_active (heading level 7)

```
bool btmesh_conf_executor::timer_active
```

**Description:** Timer is active from the the moment it is started until it elapses or until it is stopped explicitly.

#### BT Mesh Configuration Job

BT Mesh Configuration Job aggregates group of configuration tasks which targets the same configuration server model on a remote node. 

##### Modules

[btmesh_conf_job_t](btmesh-conf-job-t)

##### Enumerations

###### btmesh_conf_job_result_t

```
enum btmesh_conf_job_result_t {
    BTMESH_CONF_JOB_RESULT_SUCCESS
    BTMESH_CONF_JOB_RESULT_FAIL
    BTMESH_CONF_JOB_RESULT_CRITICAL_ERROR
    BTMESH_CONF_JOB_RESULT_CANCEL
    BTMESH_CONF_JOB_RESULT_UNKNOWN
}
```

**Description:**

Result of BT Mesh Configuration job.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_CONF_JOB_RESULT_SUCCESS|Every executed task of configuration job is successful.|
|BTMESH_CONF_JOB_RESULT_FAIL|At least one executed task is failed during configuration job execution.|
|BTMESH_CONF_JOB_RESULT_CRITICAL_ERROR|Internal error occurred during configuration job execution.|
|BTMESH_CONF_JOB_RESULT_CANCEL|The configuration job is canceled because the configurator is deinitialized.|
|BTMESH_CONF_JOB_RESULT_UNKNOWN|The result of configuration job is not known yet.|

##### Typedefs

###### btmesh_conf_job_result_t

`typedef enum btmesh_conf_job_result_t btmesh_conf_job_result_t`

**Description:**

Result of BT Mesh Configuration job.

###### btmesh_conf_job_t

`typedef struct btmesh_conf_job_t btmesh_conf_job_t`

**Description:**

Type definition of struct [btmesh_conf_job_t](btmesh-conf-job-t).

###### btmesh_conf_on_job_notification_t

`typedef void(* btmesh_conf_on_job_notification_t) (const btmesh_conf_job_t *job)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
||[in]|job|Configuration job with changed status|

**Details:**

Type of BT Mesh Configuration Job status notification callback

If task execution path ends in the configuration job then the job ends as well and job status notification callback is called with the result.

##### Functions

###### btmesh_conf_job_create_default

`btmesh_conf_job_t * btmesh_conf_job_create_default(uint16_t enc_netkey_index, uint16_t server_address, btmesh_conf_task_t *task_tree, btmesh_conf_on_job_notification_t on_job_notification)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the config requests|
|uint16_t|[in]|server_address|Destination node primary element address|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|task_tree|Config tasks which shall be executed in specified order|
|[btmesh_conf_on_job_notification_t](btmesh-conf-job#btmesh-conf-on-job-notification-t)|[in]|on_job_notification|Configuration job status notification callback which is called when the status of the job changes at the end of the job|

Create BT Mesh Configuration Job with default parameters

**Returns**

- Created configuration job.

**Return values**

- NULL: If the configuration job creation fails.

This function calls [btmesh_conf_job_create](btmesh-conf-job#btmesh-conf-job-create) with the following parameters:

- **job_status_param:**[BTMESH_CONF_VARG_NULL](btmesh-conf-types#btmesh-conf-varg-null)
- **auto_destroy:** SL_BTMESH_CONF_JOB_AUTO_DESTROY_CFG_VAL
- **job_id:** NULL

###### btmesh_conf_job_create

`btmesh_conf_job_t * btmesh_conf_job_create(uint16_t enc_netkey_index, uint16_t server_address, btmesh_conf_task_t *task_tree, btmesh_conf_on_job_notification_t on_job_notification, btmesh_conf_varg_t job_status_param, bool auto_destroy, uint32_t *const job_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|enc_netkey_index|Network key used to encrypt the config requests|
|uint16_t|[in]|server_address|Destination node primary element address|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|task_tree|Config tasks which shall be executed in specified order|
|[btmesh_conf_on_job_notification_t](btmesh-conf-job#btmesh-conf-on-job-notification-t)|[in]|on_job_notification|Configuration job status notification callback which is called when the status of the job changes at the end of the job|
|[btmesh_conf_varg_t](btmesh-conf-varg-t)|[in]|job_status_param|Job status param can be set by the application to differentiate config jobs if the same jobs status notification callback function is used in multiple jobs|
|bool|[in]|auto_destroy|Auto destroy deallocates the configuration job and its tasks automatically after the job status notification callback returns. If [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job) operation fails and the definition SL_BTMESH_CONF_JOB_AUTO_DESTROY_ON_SUBMIT_FAILURE_CFG_VAL is turned on then the job is deallocated automatically on submit failure.|
|uint32_t *const|[out]|job_id|Unique job ID generated by [btmesh_conf_job_id_generator](btmesh-conf-job#btmesh-conf-job-id-generator)|

Create BT Mesh Configuration Job with given tasks

**Returns**

- Created configuration job.

**Return values**

- NULL: If the configuration job creation fails.

Configuration job can be created if the tasks are created and linked first in order to provide the `task_tree` parameter. The created configuration job can be submitted for execution by calling [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job) function. 

###### btmesh_conf_job_destroy

`void btmesh_conf_job_destroy(btmesh_conf_job_t *const self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_job_t](btmesh-conf-job-t) *const|[in]|self|Pointer to the configuration job which shall be destroyed|

Deallocates the BT Mesh Configuration Job instance and all of its tasks

###### btmesh_conf_job_id_generator

`uint32_t btmesh_conf_job_id_generator(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Return generated unique BT Mesh Configuration Job identifier.

**Returns**

- Unique configuration job identifier

Default implementation is provided in btmesh_conf_job.c and it generates job identifiers by incrementing the last one. If the deault implementation is not sufficient for the application then the function can be overridden in the application by function definition with strong symbol.

**Note**

- Default implementation is provided with weak symbol.

###### btmesh_conf_job_set_next_task

`sl_status_t btmesh_conf_job_set_next_task(btmesh_conf_job_t *const self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_job_t](btmesh-conf-job-t) *const|[in]|self|Pointer to the configuration job instance|

Set next BT Mesh configuration task based on the current active task of a job

**Returns**

- Status of the next task setup

**Return values**

- SL_STATUS_OK: If next task is set properly.
- SL_STATUS_NOT_FOUND: If next is not set because this was the last task.
- SL_STATUS_FAIL: If fatal error occurred.

BT Mesh Configuration Job aggregates group of configuration tasks which targets the same configuration server model on a remote node. 

###### Public Attributes

###### list_elem (heading level 7)

```
sl_slist_node_t btmesh_conf_job_t::list_elem
```

**Description:** List element (node) to support placement of jobs in singly-linked list.

###### job_id (heading level 7)

```
uint32_t btmesh_conf_job_t::job_id
```

**Description:** Unique job identifier generated by [btmesh_conf_job_id_generator](btmesh-conf-job#btmesh-conf-job-id-generator).

###### task_tree (heading level 7)

```
btmesh_conf_task_t* btmesh_conf_job_t::task_tree
```

**Description:** Configuration tasks which shall be executed in the specified order.

###### current_task (heading level 7)

```
btmesh_conf_task_t* btmesh_conf_job_t::current_task
```

**Description:** Active configuration task.

###### enc_netkey_index (heading level 7)

```
uint16_t btmesh_conf_job_t::enc_netkey_index
```

**Description:** Network key used to encrypt the config requests on the network layer.

###### server_address (heading level 7)

```
uint16_t btmesh_conf_job_t::server_address
```

**Description:** Destination node primary element address.

###### result (heading level 7)

```
btmesh_conf_job_result_t btmesh_conf_job_t::result
```

**Description:** Result of configuration job.

###### on_job_notification (heading level 7)

```
void(* btmesh_conf_job_t::on_job_notification) (const btmesh_conf_job_t *job)
```

**Description:** Configuration job status notification callback which is called when the status of the job changes at the end of the job.

###### job_status_param (heading level 7)

```
btmesh_conf_varg_t btmesh_conf_job_t::job_status_param
```

**Description:** Job status param can be set by the application to differentiate config jobs if the same callback function is used in multiple jobs.

###### auto_destroy (heading level 7)

```
bool btmesh_conf_job_t::auto_destroy
```

**Description:** Auto destroy deallocates the configuration job and its tasks automatically after the job status notification callback returns. If [btmesh_conf_submit_job](btmesh-conf#btmesh-conf-submit-job) operation fails and the definition SL_BTMESH_CONF_JOB_AUTO_DESTROY_ON_SUBMIT_FAILURE_CFG_VAL is turned on then the job is deallocated automatically on submit failure.

#### BT Mesh Configuration Task

BT Mesh Configuration Tasks implement the different configuration procedures to set and get configuration server state of a node. <br />
 Each specific configuration task type implements the interface specified in [btmesh_conf_task_t](btmesh-conf-task-t) structure. 

##### Modules

[btmesh_conf_task_appkey_t](btmesh-conf-task-appkey-t)

[btmesh_conf_task_appkey_list_t](btmesh-conf-task-appkey-list-t)

[btmesh_conf_task_model_binding_t](btmesh-conf-task-model-binding-t)

[btmesh_conf_task_model_bindings_list_t](btmesh-conf-task-model-bindings-list-t)

[btmesh_conf_task_model_pub_t](btmesh-conf-task-model-pub-t)

[btmesh_conf_task_model_sub_t](btmesh-conf-task-model-sub-t)

[btmesh_conf_task_model_sub_clear_t](btmesh-conf-task-model-sub-clear-t)

[btmesh_conf_task_model_sub_list_t](btmesh-conf-task-model-sub-list-t)

[btmesh_conf_task_beacon_t](btmesh-conf-task-beacon-t)

[btmesh_conf_task_default_ttl_t](btmesh-conf-task-default-ttl-t)

[btmesh_conf_task_gatt_proxy_t](btmesh-conf-task-gatt-proxy-t)

[btmesh_conf_task_relay_t](btmesh-conf-task-relay-t)

[btmesh_conf_task_network_transmit_t](btmesh-conf-task-network-transmit-t)

[btmesh_conf_task_friend_t](btmesh-conf-task-friend-t)

[btmesh_conf_task_dcd_get_t](btmesh-conf-task-dcd-get-t)

[btmesh_conf_task_ext_t](btmesh-conf-task-ext-t)

[btmesh_conf_task_t](btmesh-conf-task-t)

##### Enumerations

###### btmesh_conf_task_id_t

```
enum btmesh_conf_task_id_t {
    BTMESH_CONF_TASK_ID_APPKEY_ADD
    BTMESH_CONF_TASK_ID_APPKEY_REMOVE
    BTMESH_CONF_TASK_ID_APPKEY_LIST
    BTMESH_CONF_TASK_ID_MODEL_BIND
    BTMESH_CONF_TASK_ID_MODEL_UNBIND
    BTMESH_CONF_TASK_ID_MODEL_BINDINGS_LIST
    BTMESH_CONF_TASK_ID_MODEL_PUB_SET
    BTMESH_CONF_TASK_ID_MODEL_PUB_GET
    BTMESH_CONF_TASK_ID_MODEL_SUB_ADD
    BTMESH_CONF_TASK_ID_MODEL_SUB_SET
    BTMESH_CONF_TASK_ID_MODEL_SUB_REMOVE
    BTMESH_CONF_TASK_ID_MODEL_SUB_CLEAR
    BTMESH_CONF_TASK_ID_MODEL_SUB_LIST
    BTMESH_CONF_TASK_ID_BEACON_SET
    BTMESH_CONF_TASK_ID_BEACON_GET
    BTMESH_CONF_TASK_ID_DEFAULT_TTL_SET
    BTMESH_CONF_TASK_ID_DEFAULT_TTL_GET
    BTMESH_CONF_TASK_ID_GATT_PROXY_SET
    BTMESH_CONF_TASK_ID_GATT_PROXY_GET
    BTMESH_CONF_TASK_ID_RELAY_SET
    BTMESH_CONF_TASK_ID_RELAY_GET
    BTMESH_CONF_TASK_ID_NETWORK_TRANSMIT_SET
    BTMESH_CONF_TASK_ID_NETWORK_TRANSMIT_GET
    BTMESH_CONF_TASK_ID_FRIEND_SET
    BTMESH_CONF_TASK_ID_FRIEND_GET
    BTMESH_CONF_TASK_ID_DCD_GET
    BTMESH_CONF_TASK_ID_RESET_NODE
    BTMESH_CONF_TASK_ID_COUNT
    BTMESH_CONF_TASK_ID_INVALID
}
```

**Description:**

BT Mesh Configuration Task identifiers.

**Enumerator:**

|   |   |
|---|---|
|BTMESH_CONF_TASK_ID_APPKEY_ADD|Add application key.|
|BTMESH_CONF_TASK_ID_APPKEY_REMOVE|Remove application key.|
|BTMESH_CONF_TASK_ID_APPKEY_LIST|List application keys (all)|
|BTMESH_CONF_TASK_ID_MODEL_BIND|Bind application key to model.|
|BTMESH_CONF_TASK_ID_MODEL_UNBIND|Unbind application key to model.|
|BTMESH_CONF_TASK_ID_MODEL_BINDINGS_LIST|List application keys bound to model.|
|BTMESH_CONF_TASK_ID_MODEL_PUB_SET|Set model publication data.|
|BTMESH_CONF_TASK_ID_MODEL_PUB_GET|Get model publication data.|
|BTMESH_CONF_TASK_ID_MODEL_SUB_ADD|Add address to subscription list of a model.|
|BTMESH_CONF_TASK_ID_MODEL_SUB_SET|Overwrite existing address in the subscription list of a model.|
|BTMESH_CONF_TASK_ID_MODEL_SUB_REMOVE|Remove address from the subscription list of a model.|
|BTMESH_CONF_TASK_ID_MODEL_SUB_CLEAR|Clear addresses from the subscription list of a model.|
|BTMESH_CONF_TASK_ID_MODEL_SUB_LIST|List addresses in the subscription list of a model.|
|BTMESH_CONF_TASK_ID_BEACON_SET|Set Beacon.|
|BTMESH_CONF_TASK_ID_BEACON_GET|Get Beacon.|
|BTMESH_CONF_TASK_ID_DEFAULT_TTL_SET|Set default TTL.|
|BTMESH_CONF_TASK_ID_DEFAULT_TTL_GET|Get default TTL.|
|BTMESH_CONF_TASK_ID_GATT_PROXY_SET|Set proxy feature.|
|BTMESH_CONF_TASK_ID_GATT_PROXY_GET|Get proxy feature.|
|BTMESH_CONF_TASK_ID_RELAY_SET|Set relay feature (feature turn on/off and retransmission parameters)|
|BTMESH_CONF_TASK_ID_RELAY_GET|Get relay feature (feature on/off and retransmission parameters)|
|BTMESH_CONF_TASK_ID_NETWORK_TRANSMIT_SET|Set network transmit count and interval.|
|BTMESH_CONF_TASK_ID_NETWORK_TRANSMIT_GET|Get network transmit count and interval.|
|BTMESH_CONF_TASK_ID_FRIEND_SET|Set friend feature.|
|BTMESH_CONF_TASK_ID_FRIEND_GET|Get friend feature.|
|BTMESH_CONF_TASK_ID_DCD_GET|Get Device Composition Data.|
|BTMESH_CONF_TASK_ID_RESET_NODE|Reset remote node.|
|BTMESH_CONF_TASK_ID_COUNT|Number of configuration tasks.|
|BTMESH_CONF_TASK_ID_INVALID|Invalid configuration task.|

##### Typedefs

###### btmesh_conf_task_id_t

`typedef enum btmesh_conf_task_id_t btmesh_conf_task_id_t`

**Description:**

BT Mesh Configuration Task identifiers.

###### btmesh_conf_task_ext_t

`typedef union btmesh_conf_task_ext_t btmesh_conf_task_ext_t`

**Description:**

Union of BT Mesh Configuration Task specific data structures.

###### btmesh_conf_task_t

`typedef struct btmesh_conf_task_t btmesh_conf_task_t`

##### Functions

###### btmesh_conf_task_create

`btmesh_conf_task_t * btmesh_conf_task_create(btmesh_conf_task_id_t task_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_id_t](btmesh-conf-task#btmesh-conf-task-id-t)|[in]|task_id|Task identifier which shall be set|

Create generic BT Mesh Configuration Task

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

Allocates and initializes a generic configuration task. **Warnings**

- This function shall be called from derived (specific) configuration task create functions only to create an initialized task instance which is further customized by the specific configuration task create function. For example [btmesh_conf_task_appkey_add_create](btmesh-conf-task#btmesh-conf-task-appkey-add-create).

###### btmesh_conf_task_destroy

`void btmesh_conf_task_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task which shall be destroyed|

Deallocates the BT Mesh Configuration Task instance

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_set_next_unconditional

`sl_status_t btmesh_conf_task_set_next_unconditional(btmesh_conf_task_t *self, btmesh_conf_task_t *const next_task)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task|
|[btmesh_conf_task_t](btmesh-conf-task-t) *const|[in]|next_task|Next task which shall be executed after this task (`self`)|

Set next task pointers of the BT Mesh Configuration Task to the specified other task.

**Returns**

- Status of next task setup.

**Return values**

- SL_STATUS_OK: If the next task is set successfully.
- SL_STATUS_NULL_POINTER: If `self` or `next_task` is NULL.
- SL_STATUS_INVALID_PARAMETER: If the `self` and `next_task` is the same or the next task of `next_task` is not NULL.

The task which shall be executed after the end of `self` task is set to `next_task`. The `next_task` is independent from the result of `self` task.

**Warnings**

- It is expected that the `next_task` does not have any next task when this function is called in order to guarantee that there will be no cyclic references in the task tree. Therefore, the task tree shall be built in the order of execution. This is enforced by the implementation and SL_STATUS_INVALID_PARAMETER is returned if this rule is not respected.

###### btmesh_conf_task_set_next_on_success

`sl_status_t btmesh_conf_task_set_next_on_success(btmesh_conf_task_t *self, btmesh_conf_task_t *const next_task)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task|
|[btmesh_conf_task_t](btmesh-conf-task-t) *const|[in]|next_task|Next task which shall be executed if this task (`self`) is completed successfully.|

Set next task pointer of the BT Mesh Configuration Task to the specified other task if this task is completed successfully.

**Returns**

- Status of next task setup.

**Return values**

- SL_STATUS_OK: If the next task is set successfully.
- SL_STATUS_NULL_POINTER: If `self` or `next_task` is NULL.
- SL_STATUS_INVALID_PARAMETER: If the `self` and `next_task` is the same or the next task of `next_task` is not NULL.

**Warnings**

- It is expected that the `next_task` does not have any next task when this function is called in order to guarantee that there will be no cyclic references in the task tree. Therefore, the task tree shall be built in the order of execution. This is enforced by the implementation and SL_STATUS_INVALID_PARAMETER is returned if this rule is not respected.

###### btmesh_conf_task_set_next_on_failure

`sl_status_t btmesh_conf_task_set_next_on_failure(btmesh_conf_task_t *self, btmesh_conf_task_t *const next_task)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task|
|[btmesh_conf_task_t](btmesh-conf-task-t) *const|[in]|next_task|Next task which shall be executed if this task (`self`) fails.|

Set next task pointer of the BT Mesh Configuration Task to the specified other task if this task fails.

**Returns**

- Status of next task setup.

**Return values**

- SL_STATUS_OK: If the next task is set successfully.
- SL_STATUS_NULL_POINTER: If `self` or `next_task` is NULL.
- SL_STATUS_INVALID_PARAMETER: If the `self` and `next_task` is the same or the next task of `next_task` is not NULL.

**Warnings**

- It is expected that the `next_task` does not have any next task when this function is called in order to guarantee that there will be no cyclic references in the task tree. Therefore, the task tree shall be built in the order of execution. This is enforced by the implementation and SL_STATUS_INVALID_PARAMETER is returned if this rule is not respected.

###### btmesh_conf_task_appkey_add_create

`btmesh_conf_task_t * btmesh_conf_task_appkey_add_create(uint16_t appkey_index, uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|appkey_index|Index of the application key|
|uint16_t|[in]|netkey_index|Index of the network key which the application key is bound to|

Create BT Mesh Configuration Task to add an application key to a node.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_appkey_add_destroy

`void btmesh_conf_task_appkey_add_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Add Application Key BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_appkey_remove_create

`btmesh_conf_task_t * btmesh_conf_task_appkey_remove_create(uint16_t appkey_index, uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|appkey_index|Index of the application key|
|uint16_t|[in]|netkey_index|Index of the network key which the application key is bound to|

Create BT Mesh Configuration Task to remove an application key from a node.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_appkey_remove_destroy

`void btmesh_conf_task_appkey_remove_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Remove Application Key BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_appkey_list_create

`btmesh_conf_task_t * btmesh_conf_task_appkey_list_create(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Network key index for the key used as query parameter|

Create BT Mesh Configuration Task to list the application keys on a node.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_appkey_list_destroy

`void btmesh_conf_task_appkey_list_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of List Application Keys BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_bind_create

`btmesh_conf_task_t * btmesh_conf_task_model_bind_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model|
|uint16_t|[in]|appkey_index|Index of the application key to bind to the model|

Create BT Mesh Configuration Task to bind an application key to a model.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_bind_destroy

`void btmesh_conf_task_model_bind_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Bind Model BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_unbind_create

`btmesh_conf_task_t * btmesh_conf_task_model_unbind_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t appkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model|
|uint16_t|[in]|appkey_index|Index of the application key to unbind from the model|

Create BT Mesh Configuration Task to unbind an application key from a model.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_unbind_destroy

`void btmesh_conf_task_model_unbind_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Unbind Model BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_bindings_list_create

`btmesh_conf_task_t * btmesh_conf_task_model_bindings_list_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node|
|uint16_t|[in]|vendor_id|Vendor ID for the model (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model|

Create BT Mesh Configuration Task to list application key bindings of a model.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_bindings_list_destroy

`void btmesh_conf_task_model_bindings_list_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of BT List Model Bindings Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_pub_set_create

`btmesh_conf_task_t * btmesh_conf_task_model_pub_set_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t address, uint16_t appkey_index, uint8_t credentials, uint8_t ttl, uint32_t period_ms, uint8_t retransmit_count, uint16_t retransmit_interval_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|
|uint16_t|[in]|address|The unicast or group address to publish to. It can also be the unassigned address to stop the model from publishing.|
|uint16_t|[in]|appkey_index|Application key index to use for published messages.|
|uint8_t|[in]|credentials|Friendship credential flag. The default value is 0.<br/><br/>- If zero, publication is done using normal credentials.<br/>- If one, it is done with friendship credentials, meaning only the friend can decrypt the published message and relay it forward using the normal credentials.|
|uint8_t|[in]|ttl|Publication time-to-live value|
|uint32_t|[in]|period_ms|Publication period in milliseconds. Note that the resolution of the publication period is limited by the specification to 100ms up to a period of 6.3s, 1s up to a period of 63s, 10s up to a period of 630s, and 10 minutes above that. Maximum period allowed is 630 minutes.|
|uint8_t|[in]|retransmit_count|Publication retransmission count. Valid values range from 0 to 7.|
|uint16_t|[in]|retransmit_interval_ms|Publication retransmission interval in millisecond units. The range of value is 50 to 1600 ms, and the resolution of the value is 50 milliseconds.|

Create BT Mesh Configuration Task to set the model publication state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_pub_set_destroy

`void btmesh_conf_task_model_pub_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Model Publication BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_pub_get_create

`btmesh_conf_task_t * btmesh_conf_task_model_pub_get_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|

Create BT Mesh Configuration Task to get the model publication state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_pub_get_destroy

`void btmesh_conf_task_model_pub_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get Model Publication BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_sub_add_create

`btmesh_conf_task_t * btmesh_conf_task_model_sub_add_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|
|uint16_t|[in]|sub_address|Group address which shall be added to the subscription list of the model.|

Create BT Mesh Configuration Task to add an address to the model subscription list.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_sub_add_destroy

`void btmesh_conf_task_model_sub_add_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Add Model Subscription BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_sub_set_create

`btmesh_conf_task_t * btmesh_conf_task_model_sub_set_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|
|uint16_t|[in]|sub_address|Group address which shall be added to the cleared subscription list of the model.|

Create BT Mesh Configuration Task to set (overwrite) model subscription address list to a single address. See Config Model Subscription Overwrite BT Mesh message in foundation models chapter of BT Mesh Profile Specification.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_sub_set_destroy

`void btmesh_conf_task_model_sub_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Model Subscription BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_sub_remove_create

`btmesh_conf_task_t * btmesh_conf_task_model_sub_remove_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id, uint16_t sub_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|
|uint16_t|[in]|sub_address|Group address which shall be removed from the subscription list of the model.|

Create BT Mesh Configuration Task to remove an address from the model subscription list.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_sub_remove_destroy

`void btmesh_conf_task_model_sub_remove_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Remove Model Subscription BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_sub_clear_create

`btmesh_conf_task_t * btmesh_conf_task_model_sub_clear_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|

Create BT Mesh Configuration Task to clear (empty) the model subscription address list.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_sub_clear_destroy

`void btmesh_conf_task_model_sub_clear_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Clear Model Subscription List BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_model_sub_list_create

`btmesh_conf_task_t * btmesh_conf_task_model_sub_list_create(uint8_t elem_index, uint16_t vendor_id, uint16_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|elem_index|Index of the element where the model resides on the node.|
|uint16_t|[in]|vendor_id|Vendor ID for the model. (0xFFFF for Bluetooth SIG models)|
|uint16_t|[in]|model_id|Model ID for the model.|

Create BT Mesh Configuration Task to get the subscription address list of a model.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_model_sub_list_destroy

`void btmesh_conf_task_model_sub_list_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of List Model Subscription BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_beacon_set_create

`btmesh_conf_task_t * btmesh_conf_task_beacon_set_create(uint8_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|value|Beacon value. Valid values are:<br/><br/>- 0: Node is not broadcasting secure network beacons<br/>- 1: Node is broadcasting secure network beacons|

Create BT Mesh Configuration Task to set node beacon state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_beacon_set_destroy

`void btmesh_conf_task_beacon_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Beacon BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_beacon_get_create

`btmesh_conf_task_t * btmesh_conf_task_beacon_get_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to get node beacon state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_beacon_get_destroy

`void btmesh_conf_task_beacon_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get Beacon BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_default_ttl_set_create

`btmesh_conf_task_t * btmesh_conf_task_default_ttl_set_create(uint8_t default_ttl)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|default_ttl|Default TTL value. Valid value range is from 2 to 127 for relayed PDUs, and 0 to indicate non-relayed PDUs.|

Create BT Mesh Configuration Task to set node default TTL state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_default_ttl_set_destroy

`void btmesh_conf_task_default_ttl_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Default TTL BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_default_ttl_get_create

`btmesh_conf_task_t * btmesh_conf_task_default_ttl_get_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to get node default TTL state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_default_ttl_get_destroy

`void btmesh_conf_task_default_ttl_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get Default TTL BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_gatt_proxy_set_create

`btmesh_conf_task_t * btmesh_conf_task_gatt_proxy_set_create(uint8_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|value|GATT proxy value to set. Valid values are:<br/><br/>- 0: Proxy feature is disabled<br/>- 1: Proxy feature is enabled|

Create BT Mesh Configuration Task to set node GATT proxy state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_gatt_proxy_set_destroy

`void btmesh_conf_task_gatt_proxy_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set GATT Proxy BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_gatt_proxy_get_create

`btmesh_conf_task_t * btmesh_conf_task_gatt_proxy_get_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to get node GATT proxy state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_gatt_proxy_get_destroy

`void btmesh_conf_task_gatt_proxy_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get GATT Proxy BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_relay_set_create

`btmesh_conf_task_t * btmesh_conf_task_relay_set_create(uint8_t value, uint8_t retransmit_count, uint16_t retransmit_interval_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|value|Relay value to set. Valid values are:<br/><br/>- 0: Relay feature is disabled<br/>- 1: Relay feature is enabled|
|uint8_t|[in]|retransmit_count|Relay retransmit count. Valid values range from 0 to 7; default value is 0 (no retransmissions).|
|uint16_t|[in]|retransmit_interval_ms|Relay retransmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value is ignored if the retransmission count is set to zero.|

Create BT Mesh Configuration Task to set node relay state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_relay_set_destroy

`void btmesh_conf_task_relay_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Relay BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_relay_get_create

`btmesh_conf_task_t * btmesh_conf_task_relay_get_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to get node relay state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_relay_get_destroy

`void btmesh_conf_task_relay_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get Relay BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_network_transmit_set_create

`btmesh_conf_task_t * btmesh_conf_task_network_transmit_set_create(uint8_t transmit_count, uint16_t transmit_interval_ms)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|transmit_count|Network transmit count. Valid values range from 1 to 8; default value is 1 (single transmission; no retransmissions).|
|uint16_t|[in]|transmit_interval_ms|Network transmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value is ignored if the transmission count is set to one.|

Create BT Mesh Configuration Task to set node network transmit state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_network_transmit_set_destroy

`void btmesh_conf_task_network_transmit_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Network Transmit BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_network_transmit_get_create

`btmesh_conf_task_t * btmesh_conf_task_network_transmit_get_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to get node network transmit state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_network_transmit_get_destroy

`void btmesh_conf_task_network_transmit_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get Network Transmit BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_friend_set_create

`btmesh_conf_task_t * btmesh_conf_task_friend_set_create(uint8_t value)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|value|Friend value to set. Valid values are:<br/><br/>- 0: Friend feature is not enabled<br/>- 1: Friend feature is enabled|

Create BT Mesh Configuration Task to set node friend state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_friend_set_destroy

`void btmesh_conf_task_friend_set_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Set Friend BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_friend_get_create

`btmesh_conf_task_t * btmesh_conf_task_friend_get_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to get node friend state.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_friend_get_destroy

`void btmesh_conf_task_friend_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get Friend BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_dcd_get_create

`btmesh_conf_task_t * btmesh_conf_task_dcd_get_create(uint8_t page)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|page|Composition data page to query|

Create BT Mesh Configuration Task to get composition data of a device.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_dcd_get_destroy

`void btmesh_conf_task_dcd_get_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Get DCD BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

###### btmesh_conf_task_reset_node_create

`btmesh_conf_task_t * btmesh_conf_task_reset_node_create(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Create BT Mesh Configuration Task to request a node to unprovision itself. Use this function when a node shall be removed from the network.

**Returns**

- Created configuration task.

**Return values**

- NULL: If the configuration task creation fails.

###### btmesh_conf_task_reset_node_destroy

`void btmesh_conf_task_reset_node_destroy(btmesh_conf_task_t *self)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_conf_task_t](btmesh-conf-task-t) *|[in]|self|Pointer to the configuration task instance|

Deallocation of Reset Node BT Mesh Configuration Task instance.

If [btmesh_conf_task_t::next_on_success](btmesh-conf-task-t#next-on-success) or [btmesh_conf_task_t::next_on_failure](btmesh-conf-task-t#next-on-failure) is set then those tasks are destroyed as well. 

##### Macros

`#define BTMESH_CONF_TASK_RESULT_UNKNOWN ((sl_status_t) 0xFFFFFFFF)`

**Description**: BT Mesh Configuration Task result is unknown because it is not finished yet.

Task specific data of add/remove application key data. 

###### Public Attributes

###### appkey_index (heading level 7)

```
uint16_t btmesh_conf_task_appkey_t::appkey_index
```

**Description:** Index of the application key.

###### netkey_index (heading level 7)

```
uint16_t btmesh_conf_task_appkey_t::netkey_index
```

**Description:** Index of the network key which the application key is bound to.

Task specific data of list application keys (all) 

###### Public Attributes

###### netkey_index (heading level 7)

```
uint16_t btmesh_conf_task_appkey_list_t::netkey_index
```

**Description:** Network key index for the key used as the query parameter.

###### appkey_indexes (heading level 7)

```
uint16_t* btmesh_conf_task_appkey_list_t::appkey_indexes
```

**Description:** List of application key indexes which are bound to the network key index.

###### appkey_count (heading level 7)

```
uint16_t btmesh_conf_task_appkey_list_t::appkey_count
```

**Description:** Number of application key indexes which are bound to the network key index.

Task specific data of bind/unbind application key to model. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t btmesh_conf_task_model_binding_t::elem_index
```

**Description:** Index of the element where the model resides on the node.

###### vendor_id (heading level 7)

```
uint16_t btmesh_conf_task_model_binding_t::vendor_id
```

**Description:** Vendor ID for the model (0xFFFF for Bluetooth SIG models)

###### model_id (heading level 7)

```
uint16_t btmesh_conf_task_model_binding_t::model_id
```

**Description:** Model ID for the model.

###### appkey_index (heading level 7)

```
uint16_t btmesh_conf_task_model_binding_t::appkey_index
```

**Description:** Index of the application key bound to the model.

Task specific data of list application keys bound to model. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t btmesh_conf_task_model_bindings_list_t::elem_index
```

**Description:** Index of the element where the model resides on the node.

###### vendor_id (heading level 7)

```
uint16_t btmesh_conf_task_model_bindings_list_t::vendor_id
```

**Description:** Vendor ID for the model (0xFFFF for Bluetooth SIG models)

###### model_id (heading level 7)

```
uint16_t btmesh_conf_task_model_bindings_list_t::model_id
```

**Description:** Model ID for the model.

###### appkey_indexes (heading level 7)

```
uint16_t* btmesh_conf_task_model_bindings_list_t::appkey_indexes
```

**Description:** List of key indexes for the application keys which are bound to a model.

###### appkey_count (heading level 7)

```
uint16_t btmesh_conf_task_model_bindings_list_t::appkey_count
```

**Description:** Number of key indexes for the application keys which are bound to a model.

Task specific data of set/get model publication data. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t btmesh_conf_task_model_pub_t::elem_index
```

**Description:** Index of the element where the model resides on the node.

###### vendor_id (heading level 7)

```
uint16_t btmesh_conf_task_model_pub_t::vendor_id
```

**Description:** Vendor ID for the model (0xFFFF for Bluetooth SIG models)

###### model_id (heading level 7)

```
uint16_t btmesh_conf_task_model_pub_t::model_id
```

**Description:** Model ID for the model.

###### address (heading level 7)

```
uint16_t btmesh_conf_task_model_pub_t::address
```

**Description:** The unicast or group address to publish to. It can also be the unassigned address to stop the model from publishing. Note: Task type determines whether `address` or `va_addres` is used.

###### va_address (heading level 7)

```
uuid_128 btmesh_conf_task_model_pub_t::va_address
```

**Description:** The virtual address to publish to. Note: Task type determines whether `address` or `va_addres` is used.

###### appkey_index (heading level 7)

```
uint16_t btmesh_conf_task_model_pub_t::appkey_index
```

**Description:** The application key index to use for the published messages.

###### credentials (heading level 7)

```
uint8_t btmesh_conf_task_model_pub_t::credentials
```

**Description:** Friendship credential flag. If zero, publication is done using normal credentials. If one, it is done with friendship credentials, meaning only the friend can decrypt the published message and relay it forward using the normal credentials. The default value is 0.

###### ttl (heading level 7)

```
uint8_t btmesh_conf_task_model_pub_t::ttl
```

**Description:** Publication time-to-live value.

###### period_ms (heading level 7)

```
uint32_t btmesh_conf_task_model_pub_t::period_ms
```

**Description:** Publication period in milliseconds. Note that the resolution of the publication period is limited by the specification to 100 ms up to a period of 6.3 s, 1 s up to a period of 63 s, 10 s up to a period of 630 s, and 10 minutes above that. Maximum period allowed is 630 minutes.

###### retransmit_count (heading level 7)

```
uint8_t btmesh_conf_task_model_pub_t::retransmit_count
```

**Description:** Publication retransmission count. Valid values range from 0 to 7.

###### retransmit_interval_ms (heading level 7)

```
uint16_t btmesh_conf_task_model_pub_t::retransmit_interval_ms
```

**Description:** Publication retransmission interval in millisecond units. The range of value is 50 to 1600 ms, and the resolution of the value is 50 milliseconds.

Task specific data of the following model subscription list operations. 

- Add address to model subscription list
- Set address to model subscription list (clear list & add group address)
- Remove address to model subscription list

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t btmesh_conf_task_model_sub_t::elem_index
```

**Description:** Index of the element where the model resides on the node.

###### vendor_id (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_t::vendor_id
```

**Description:** Vendor ID for the model (0xFFFF for Bluetooth SIG models)

###### model_id (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_t::model_id
```

**Description:** Model ID for the model.

###### sub_address (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_t::sub_address
```

**Description:** The group address in the subscription list. Note: Task type determines whether [sub_address](btmesh-conf-task-model-sub-t#sub-address) or [sub_address_va](btmesh-conf-task-model-sub-t#sub-address-va) is used.

###### sub_address_va (heading level 7)

```
uuid_128 btmesh_conf_task_model_sub_t::sub_address_va
```

**Description:** The full virtual address in the subscription list. Note: Task type determines whether [sub_address](btmesh-conf-task-model-sub-t#sub-address) or [sub_address_va](btmesh-conf-task-model-sub-t#sub-address-va) is used.

Task specific data of clear addresses from the subscription list of a model. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t btmesh_conf_task_model_sub_clear_t::elem_index
```

**Description:** Index of the element where the model resides on the node.

###### vendor_id (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_clear_t::vendor_id
```

**Description:** Vendor ID for the model (0xFFFF for Bluetooth SIG models)

###### model_id (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_clear_t::model_id
```

**Description:** Model ID for the model.

Task specific data of list addresses in the subscription list of a model. 

###### Public Attributes

###### elem_index (heading level 7)

```
uint8_t btmesh_conf_task_model_sub_list_t::elem_index
```

**Description:** Index of the element where the model resides on the node.

###### vendor_id (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_list_t::vendor_id
```

**Description:** Vendor ID for the model (0xFFFF for Bluetooth SIG models)

###### model_id (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_list_t::model_id
```

**Description:** Model ID for the model.

###### addresses (heading level 7)

```
uint16_t* btmesh_conf_task_model_sub_list_t::addresses
```

**Description:** List of subscription addresses <br />
 If the subscription address list entry is a Label UUID (full virtual address) then the corresponding virtual address hash is returned in this event.

###### address_count (heading level 7)

```
uint16_t btmesh_conf_task_model_sub_list_t::address_count
```

**Description:** Number of subscription addresses.

Task specific data of set/get Beacon. 

###### Public Attributes

###### value (heading level 7)

```
uint8_t btmesh_conf_task_beacon_t::value
```

**Description:** Secure network beacon value. Valid values are:

**Details:** - 0: Node is not broadcasting secure network beacons
- 1: Node is broadcasting secure network beacons

Task specific data of set/get default TTL. 

###### Public Attributes

###### ttl (heading level 7)

```
uint8_t btmesh_conf_task_default_ttl_t::ttl
```

**Description:** Default TTL value. Valid value range is from 2 to 127 for relayed PDUs, and 0 to indicate none - relayed PDUs.

Task specific data of set/get proxy feature. 

###### Public Attributes

###### value (heading level 7)

```
uint8_t btmesh_conf_task_gatt_proxy_t::value
```

**Description:** GATT proxy value. Valid values are:

**Details:** - 0: Proxy feature is disabled
- 1: Proxy feature is enabled

Task specific data of set/get relay feature. 

###### Public Attributes

###### value (heading level 7)

```
uint8_t btmesh_conf_task_relay_t::value
```

**Description:** Relay value. Valid values are:

**Details:** - 0: Relay feature is disabled
- 1: Relay feature is enabled

###### retransmit_count (heading level 7)

```
uint8_t btmesh_conf_task_relay_t::retransmit_count
```

**Description:** Relay retransmit count. Valid values range from 0 to 7; default value is 0 (no retransmissions).

###### retransmit_interval_ms (heading level 7)

```
uint16_t btmesh_conf_task_relay_t::retransmit_interval_ms
```

**Description:** Relay retransmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value is ignored if the retransmission count is set to zero.

Task specific data of set/get network transmit count and interval. 

###### Public Attributes

###### transmit_count (heading level 7)

```
uint8_t btmesh_conf_task_network_transmit_t::transmit_count
```

**Description:** Network transmit count. Valid values range from 1 to 8; default value is 1 (single transmission; no retransmissions).

###### transmit_interval_ms (heading level 7)

```
uint16_t btmesh_conf_task_network_transmit_t::transmit_interval_ms
```

**Description:** Network transmit interval in milliseconds. Valid values range from 10 ms to 320 ms, with a resolution of 10 ms. The value is ignored if the transmission count is set to one.

Task specific data of set/get friend feature. 

###### Public Attributes

###### value (heading level 7)

```
uint8_t btmesh_conf_task_friend_t::value
```

**Description:** Friend value. Valid values are:

**Details:** - 0: Friend feature is not enabled
- 1: Friend feature is enabled

Task specific data of get Device Composition Data (DCD) 

###### Public Attributes

###### page (heading level 7)

```
uint8_t btmesh_conf_task_dcd_get_t::page
```

**Description:** Composition data page containing data.

###### raw_dcd_data (heading level 7)

```
uint8_t* btmesh_conf_task_dcd_get_t::raw_dcd_data
```

**Description:** Raw DCD data of the remote node.

###### raw_dcd_data_size (heading level 7)

```
uint16_t btmesh_conf_task_dcd_get_t::raw_dcd_data_size
```

**Description:** Size of raw DCD data.

Union of BT Mesh Configuration Task specific data structures. 

###### Public Attributes

###### appkey (heading level 7)

```
btmesh_conf_task_appkey_t btmesh_conf_task_ext_t::appkey
```

**Description:** Task specific data of add/remove application key data.

###### appkey_list (heading level 7)

```
btmesh_conf_task_appkey_list_t btmesh_conf_task_ext_t::appkey_list
```

**Description:** Task specific data of list application keys (all)

###### model_binding (heading level 7)

```
btmesh_conf_task_model_binding_t btmesh_conf_task_ext_t::model_binding
```

**Description:** Task specific data of bind/unbind application key to model.

###### model_bindings_list (heading level 7)

```
btmesh_conf_task_model_bindings_list_t btmesh_conf_task_ext_t::model_bindings_list
```

**Description:** Task specific data of list application keys bound to model.

###### model_pub (heading level 7)

```
btmesh_conf_task_model_pub_t btmesh_conf_task_ext_t::model_pub
```

**Description:** Task specific data of set/get model publication data.

###### model_sub (heading level 7)

```
btmesh_conf_task_model_sub_t btmesh_conf_task_ext_t::model_sub
```

**Description:** Task specific data of add/set/remove model subscription list operations.

###### model_sub_clear (heading level 7)

```
btmesh_conf_task_model_sub_clear_t btmesh_conf_task_ext_t::model_sub_clear
```

**Description:** Task specific data of clear addresses from the subscription list of a model.

###### model_sub_list (heading level 7)

```
btmesh_conf_task_model_sub_list_t btmesh_conf_task_ext_t::model_sub_list
```

**Description:** Task specific data of list addresses in the subscription list of a model.

###### beacon (heading level 7)

```
btmesh_conf_task_beacon_t btmesh_conf_task_ext_t::beacon
```

**Description:** Task specific data of set/get beacon.

###### default_ttl (heading level 7)

```
btmesh_conf_task_default_ttl_t btmesh_conf_task_ext_t::default_ttl
```

**Description:** Task specific data of set/get default TTL.

###### gatt_proxy (heading level 7)

```
btmesh_conf_task_gatt_proxy_t btmesh_conf_task_ext_t::gatt_proxy
```

**Description:** Task specific data of set/get proxy feature.

###### relay (heading level 7)

```
btmesh_conf_task_relay_t btmesh_conf_task_ext_t::relay
```

**Description:** Task specific data of set/get relay feature.

###### network_transmit (heading level 7)

```
btmesh_conf_task_network_transmit_t btmesh_conf_task_ext_t::network_transmit
```

**Description:** Task specific data of set/get network transmit count and interval.

###### friend (heading level 7)

```
btmesh_conf_task_friend_t btmesh_conf_task_ext_t::friend
```

**Description:** Task specific data of set/get friend feature.

###### dcd (heading level 7)

```
btmesh_conf_task_dcd_get_t btmesh_conf_task_ext_t::dcd
```

**Description:** Task specific data of get Device Composition Data (DCD)

BT Mesh Configuration Task is abstraction of configuration procedures <br />
 The specific configuration tasks are instances of this structure with different task identifiers and function pointers (e.g. `conf_request`, `on_event` etc.) furthermore different members of the `btmesh_conf_task_ext_t` union is used based on the task type. 

###### Public Attributes

###### task_id (heading level 7)

```
btmesh_conf_task_id_t btmesh_conf_task_t::task_id
```

**Description:** Task identifier which determines the specific task type.

###### result (heading level 7)

```
sl_status_t btmesh_conf_task_t::result
```

**Description:** Task result. Initialized to [BTMESH_CONF_TASK_RESULT_UNKNOWN](btmesh-conf-task#btmesh-conf-task-result-unknown) and it set to the final value at the end of task. <br />
 If the configuration task was successful then it is set to SL_STATUS_OK. <br />
 If `conf_request` or `on_event` fails then it set to an error code returned by the BT Mesh Stack.

###### conf_request (heading level 7)

```
sl_status_t(* btmesh_conf_task_t::conf_request) (btmesh_conf_task_t *const self, uint16_t enc_netkey_index, uint16_t server_address, uint32_t *handle)
```

**Description:** Abstract configuration request which sends the task specific configuration request to the configuration server on a node.

**Details:** **Returns**

- Task request status

###### on_event (heading level 7)

```
sl_status_t(* btmesh_conf_task_t::on_event) (btmesh_conf_task_t *const self, uint16_t enc_netkey_index, uint16_t server_address, const sl_btmesh_msg_t *evt)
```

**Description:** Abstract configuration event handler which processes the BT Mesh Stack event. <br />
 Only those BT Mesh Configuration Client events shall be forwarded to this task event handler which matches the configuration handle of the last `conf_request` in order to make task implementation simpler.

**Details:** **Returns**

- Current status of the task.

###### to_string (heading level 7)

```
int32_t(* btmesh_conf_task_t::to_string) (btmesh_conf_task_t *const self, char *buffer, uint32_t size)
```

**Description:** Abstract function which provides the string representation of the configuration task. <br />
 The function always writes null terminated string into the `buffer`.

**Details:** **Returns**

- Return value of functions shall be interpreted as snprintf.

###### destroy (heading level 7)

```
void(* btmesh_conf_task_t::destroy) (btmesh_conf_task_t *const self)
```

**Description:** Deallocation of BT Mesh Configuration Task instance.

**Details:** 

###### next_on_success (heading level 7)

```
btmesh_conf_task_t* btmesh_conf_task_t::next_on_success
```

**Description:** Next task if this task is successful (`result` is SL_STATUS_OK)

###### next_on_failure (heading level 7)

```
btmesh_conf_task_t* btmesh_conf_task_t::next_on_failure
```

**Description:** Next task if this task fails (`result` is not SL_STATUS_OK)

###### ext (heading level 7)

```
btmesh_conf_task_ext_t btmesh_conf_task_t::ext
```

**Description:** Task specific data (parameters, runtime data, results) <br />
 Union of task specific data structures.

#### BT Mesh Configuration Types

BT Mesh Configuration Types provides common definitions and types. 

##### Modules

[btmesh_conf_varg_t](btmesh-conf-varg-t)

##### Macros

`#define BTMESH_CONF_NETKEY_INDEX_UNASSIGNED 0xFFFF`

**Description**: Unknown network key index value.

`#define BTMESH_CONF_PUB_ELEM_INDEX_UNKNOWN 0xFF`

**Description**: Unknown model publication element index value.

`#define BTMESH_CONF_PUB_VENDOR_ID_UNKNOWN 0xFFFF`

**Description**: Unknown model publication vendor ID value.

`#define BTMESH_CONF_PUB_MODEL_ID_UNKNOWN 0xFFFF`

**Description**: Unknown model publication model ID value.

`#define BTMESH_CONF_PUB_ADDRESS_UNKNOWN 0xFFFF`

**Description**: Unknown model publication address value.

`#define BTMESH_CONF_PUB_APPKEY_INDEX_UNKNOWN 0xFFFF`

**Description**: Unknown model publication application key value.

`#define BTMESH_CONF_PUB_CREDENTIALS_UNKNOWN 0xFF`

**Description**: Unknown model publication friendship credentials flag value.

`#define BTMESH_CONF_PUB_TTL_UNKNOWN 0xFF`

**Description**: Unknown model publication TTL value.

`#define BTMESH_CONF_PUB_PERIOD_MS_UNKNOWN 0xFFFFFFFF`

**Description**: Unknown model publication period value.

`#define BTMESH_CONF_PUB_RETRANSMIT_CNT_UNKNOWN 0xFF`

**Description**: Unknown model publication retransmit count value.

`#define BTMESH_CONF_PUB_RETRANSMIT_INT_MS_UNKNOWN 0xFFFF`

**Description**: Unknown model publication retransmit interval value.

`#define BTMESH_CONF_BEACON_UNKNOWN 0xFF`

**Description**: Unknown node beacon value.

`#define BTMESH_CONF_DEFAULT_TTL_UNKNOWN 0xFF`

**Description**: Unknown node default TTL value.

`#define BTMESH_CONF_PROXY_VALUE_UNKNOWN 0xFF`

**Description**: Unknown node proxy value.

`#define BTMESH_CONF_RELAY_VALUE_UNKNOWN 0xFF`

**Description**: Unknown node relay value.

`#define BTMESH_CONF_RELAY_RETRANSMIT_CNT_UNKNOWN 0xFF`

**Description**: Unknown node relay retransmit count.

`#define BTMESH_CONF_RELAY_RETRANSMIT_INT_MS_UNKNOWN 0xFFFF`

**Description**: Unknown node relay retransmit interval.

`#define BTMESH_CONF_NW_TRANSMIT_CNT_UNKNOWN 0xFF`

**Description**: Unknown node network transmit count.

`#define BTMESH_CONF_NW_TRANSMIT_INT_MS_UNKNOWN 0xFFFF`

**Description**: Unknown node network transmit interval.

`#define BTMESH_CONF_FRIEND_VALUE_UNKNOWN 0xFF`

**Description**: Unknown node friend value.

`#define BTMESH_CONF_MAX_APPKEY_COUNT (1 << 12)`

**Description**: Maximum theoretical number of application keys.

`#define BTMESH_CONF_MAX_NETKEY_COUNT (1 << 12)`

**Description**: Maximum theoretical number of network keys.

`#define BTMESH_CONF_MAX_SUB_ADDR_COUNT ((1 << 14) + (1 << 14) + 1)`

**Description**: Maximum theoretical number of subscription addresses BT Mesh model can subscribe to group addresses (14bit) and to virtual addresses (14bit) and to unicast address of the node element which the model resides on.

`#define BTMESH_CONF_VARG_U32 (u32)`

**Description**: Variable argument unsigned initializer macro.

`#define BTMESH_CONF_VARG_PTR (ptr)`

**Description**: Variable argument pointer initializer macro.

`#define BTMESH_CONF_VARG_NULL (btmesh_conf_varg_t){ .ptr = NULL }`

**Description**: Variable argument NULL pointer initializer macro.

Variable argument union type to provide application specific information. 

###### Public Attributes

###### u32 (heading level 7)

```
uint32_t btmesh_conf_varg_t::u32
```

**Description:** Unsigned 32bit variable.

###### ptr (heading level 7)

```
void* btmesh_conf_varg_t::ptr
```

**Description:** Pointer variable.

### BT Mesh Database

#### Modules

[btmesh_db_model_id_t](btmesh-db-model-id-t)

[btmesh_db_element_t](btmesh-db-element-t)

[btmesh_db_node_dcd_t](btmesh-db-node-dcd-t)

[btmesh_db_node_prov_t](btmesh-db-node-prov-t)

[btmesh_db_node_t](btmesh-db-node-t)

[btmesh_db_network_t](btmesh-db-network-t)

[btmesh_db_nodelist_elem_t](btmesh-db-nodelist-elem-t)

#### Typedefs

##### btmesh_db_network_t

`typedef struct btmesh_db_network_t btmesh_db_network_t`

##### btmesh_db_model_id_t

`typedef struct btmesh_db_model_id_t btmesh_db_model_id_t`

**Description:**

Common model identifier structure for Bluetooth SIG and Vendor models.

##### btmesh_db_element_t

`typedef struct btmesh_db_element_t btmesh_db_element_t`

**Description:**

Node element represention in the Device Composition Data (DCD)

##### btmesh_db_node_dcd_t

`typedef struct btmesh_db_node_dcd_t btmesh_db_node_dcd_t`

**Description:**

Representation of Device Composition Data (DCD)

##### btmesh_db_node_prov_t

`typedef struct btmesh_db_node_prov_t btmesh_db_node_prov_t`

**Description:**

The provisioning-related information of a node.

##### btmesh_db_node_t

`typedef struct btmesh_db_node_t btmesh_db_node_t`

**Description:**

Struct representing one single node.

##### btmesh_db_nodelist_elem_t

`typedef struct btmesh_db_nodelist_elem_t btmesh_db_nodelist_elem_t`

**Description:**

Helper struct to keep track of which nodes are part of a given network.

#### Functions

##### btmesh_db_init

`void btmesh_db_init(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize the database. 

##### btmesh_db_get_node_list

`sl_slist_node_t * btmesh_db_get_node_list(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get the node list.

**Returns**

- Pointer to the head of the node linked list

##### btmesh_db_get_network_list

`sl_slist_node_t * btmesh_db_get_network_list(void)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get the network list.

**Returns**

- Pointer to the head of the network linked list

##### btmesh_db_create_network

`sl_status_t btmesh_db_create_network(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|netkey_index of the network|

Create a new BT Mesh network in the database.

**Returns**

- Status of the network creation.

**Return values**

- SL_STATUS_OK: If network is correctly created.
- SL_STATUS_ALREADY_EXIST: If a network with the given netkey_index already exists.
- SL_STATUS_ALLOCATION_FAILED: If allocating memory for the network struct fails.

##### btmesh_db_remove_network

`void btmesh_db_remove_network(btmesh_db_network_t *network)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_db_network_t](btmesh-db-network-t) *|[in]|network|Pointer to the network to be deleted|

Remove network from the database. This also removes the reference to the network in all nodes that were part of it.

##### btmesh_db_create_node

`sl_status_t btmesh_db_create_node(uuid_128 uuid, bd_addr mac_address, uint16_t prim_address, uint8_t element_count, uint8_t bearer_type, uint16_t oob_capabilities)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the node|
|bd_addr|[in]|mac_address|Bluetooth address of the node|
|uint16_t|[in]|prim_address|Primary address of the node in a network|
|uint8_t|[in]|element_count|Element count of the node|
|uint8_t|[in]|bearer_type|Type of the provisioning bearer layer. Can be PB-ADV (0) or PB-GATT (1).|
|uint16_t|N/A|oob_capabilities||

Create a new node and add it to the node list.

**Returns**

- Status of the node creation.

**Return values**

- SL_STATUS_OK: If node is successfully created.
- SL_STATUS_ALREADY_EXIST: If a node with the given UUID already exists.
- SL_STATUS_ALLOCATION_FAILED: If allocating memory for the node struct fails.

##### btmesh_db_remove_node_by_uuid

`sl_status_t btmesh_db_remove_node_by_uuid(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the node to be removed|

Remove a node from the database by its UUID. This function removes the node from all networks it is present in.

**Returns**

- Status of the removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.

##### btmesh_db_remove_node_by_addr

`sl_status_t btmesh_db_remove_node_by_addr(uint16_t prim_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|prim_address|Primary element address of the node to be removed|

Remove a node from the database by its primary element address. This function removes the node from all networks it is present in.

**Returns**

- Status of the removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.

##### btmesh_db_remove_node_by_mac

`sl_status_t btmesh_db_remove_node_by_mac(bd_addr mac)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bd_addr|[in]|mac|Bluetooth address of the node to be removed|

Remove a node from the database by its Bluetooth address. This function removes the node from all networks it is present in.

**Returns**

- Status of the removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.

##### btmesh_db_add_node_to_network_by_uuid

`sl_status_t btmesh_db_add_node_to_network_by_uuid(uint16_t netkey_index, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|uuid_128|[in]|uuid|UUID of the node|

Add an already created node to a network by UUID

**Returns**

- Status of the addition.

**Return values**

- SL_STATUS_OK: If node is successfully added to the network.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If either the node or the network does not exist.
- SL_STATUS_ALREADY_EXISTS: If the node is already in the network.
- SL_STATUS_ALLOCATION_FAILED: If the node **pointer** can't be added to the network's list.

##### btmesh_db_node_dcd_set_available

`sl_status_t btmesh_db_node_dcd_set_available(uint16_t prim_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|prim_address|Primary element address of the node|

Makes the DCD information available for reading in the BT Mesh database

**Returns**

- Status of the set available operation

**Return values**

- SL_STATUS_OK: If DCD information is set available
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.

The DCD information of a node is built in several steps in btmesh database:

- [btmesh_db_node_dcd_set_header](btmesh-db#btmesh-db-node-dcd-set-header) (once)
- [btmesh_db_node_dcd_add_element](btmesh-db#btmesh-db-node-dcd-add-element) (element count times)
- [btmesh_db_node_dcd_add_model](btmesh-db#btmesh-db-node-dcd-add-model) (on each element model count times)

The DCD information is not valid until all necessary functions are called. This function marks when the DCD information is complete in the database. 

##### btmesh_db_node_dcd_set_header

`sl_status_t btmesh_db_node_dcd_set_header(uint16_t prim_address, uint16_t company_id, uint16_t product_id, uint16_t version_id, uint16_t min_replay_prot_list_len, bool feature_relay, bool feature_proxy, bool feature_friend, bool feature_low_power)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|prim_address|Primary element address of the node|
|uint16_t|[in]|company_id|Company identifier assigned by the Bluetooth SIG|
|uint16_t|[in]|product_id|Vendor-assigned product identifier|
|uint16_t|[in]|version_id|Vendor-assigned product version identifier|
|uint16_t|[in]|min_replay_prot_list_len|Min number of replay protection list entries|
|bool|[in]|feature_relay|Relay feature support|
|bool|[in]|feature_proxy|Proxy feature support|
|bool|[in]|feature_friend|Friend feature support|
|bool|[in]|feature_low_power|Low power feature support|

Sets the DCD header data (page 0) in the BT Mesh database

**Returns**

- Status of the set node DCD header operation

**Return values**

- SL_STATUS_OK: If DCD header data is set successfully.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.
- SL_STATUS_INVALID_STATE: If the DCD can't be modified because it was set available previously.

Sets DCD header data of the node chosen by prim_address in BT Mesh database. The DCD header data not vary with the number of elements or models.

If the DCD is set available then the DCD data can be modified only if it is cleared first by the [btmesh_db_node_dcd_clear](btmesh-db#btmesh-db-node-dcd-clear) function.

**Note**

- If the firmware is updated on the node then the DCD of the node might change (not necessarily). The BT Mesh specification guarantees that the DCD is constant between firmware updates.

##### btmesh_db_node_dcd_add_element

`sl_status_t btmesh_db_node_dcd_add_element(uint16_t prim_address, uint16_t location)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|prim_address|Primary element address of the node|
|uint16_t|[in]|location|Location description as defined in the GATT Bluetooth Namespace Descriptors section of the Bluetooth SIG Assigned Numbers|

Adds an empty element to the DCD of specified node in BT Mesh database

**Returns**

- Status of element addition

**Return values**

- SL_STATUS_OK: If the element is added successfully.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.
- SL_STATUS_INVALID_STATE: If the DCD can't be modified because it was set available previously.
- SL_STATUS_ALLOCATION_FAILED: If the memory allocation for the new element is failed.

The new empty element is added to end of element array of DCD in BT Mesh database. Therefore the elements shall be added in the increasing order of element indexes. 

##### btmesh_db_node_dcd_add_model

`sl_status_t btmesh_db_node_dcd_add_model(uint16_t prim_address, uint16_t element_index, btmesh_db_model_id_t model_id)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|prim_address|Primary element address of the node|
|uint16_t|[in]|element_index|Index of element where the model resides on the node|
|[btmesh_db_model_id_t](btmesh-db-model-id-t)|[in]|model_id|Model ID of the model|

Adds a model to the specified DCD element in BT Mesh database

**Returns**

- Status of the model addition

**Return values**

- SL_STATUS_OK: If the model is added successfully.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node or element does not exist.
- SL_STATUS_INVALID_STATE: If the DCD can't be modified because it was set available previously.
- SL_STATUS_ALREADY_EXISTS: If the model ID is already added to element. The model IDs shall be unique in the context of a node element.
- SL_STATUS_ALLOCATION_FAILED: If the memory allocation for the new model is failed.

##### btmesh_db_node_dcd_clear

`sl_status_t btmesh_db_node_dcd_clear(uint16_t prim_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|prim_address|Primary element address of the node|

Clears the DCD of the specified node in BT Mesh database

**Returns**

- Status of the DCD clear operation

**Return values**

- SL_STATUS_OK: If the DCD is cleared successfully.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the node does not exist.

The DCD clear operation deallocates all dynamically allocated resources belonging to the DCD of the specified node and sets the DCD unavailable. If the DCD was set available then it can be modified only if the current DCD of the node is cleared first by calling this function. 

##### btmesh_db_remove_node_from_network

`sl_status_t btmesh_db_remove_node_from_network(uint16_t netkey_index, btmesh_db_node_t *node)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|[btmesh_db_node_t](btmesh-db-node-t) *|[in]|node|Pointer to the node|

Remove a node from a given network.

**Returns**

- Status of the node removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If either the network does not exist or the node is not in the network.

##### btmesh_db_remove_node_from_network_by_addr

`sl_status_t btmesh_db_remove_node_from_network_by_addr(uint16_t netkey_index, uint16_t prim_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|uint16_t|[in]|prim_address|Primary address of the node|

Remove a node from a given network by the node's primary element address.

**Returns**

- Status of the node removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If either the network or node does not exist, or the node is not in the network.

##### btmesh_db_remove_node_from_network_by_uuid

`sl_status_t btmesh_db_remove_node_from_network_by_uuid(uint16_t netkey_index, uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|uuid_128|[in]|uuid|UUID of the network|

Remove a node from a given network by the node's UUID.

**Returns**

- Status of the node removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If either the network or node does not exist, or the node is not in the network.

##### btmesh_db_remove_node_from_network_by_mac

`sl_status_t btmesh_db_remove_node_from_network_by_mac(uint16_t netkey_index, bd_addr mac)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|bd_addr|[in]|mac|Bluetooth address of the node|

Remove a node from a given network by the node's Bluetooth address.

**Returns**

- Status of the node removal.

**Return values**

- SL_STATUS_OK: If node is successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If either the network or node does not exist, or the node is not in the network.

##### btmesh_db_remove_all_nodes_from_network

`sl_status_t btmesh_db_remove_all_nodes_from_network(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|

Remove all nodes from a give network

**Returns**

- Status of the node removal.

**Return values**

- SL_STATUS_OK: If nodes are successfully removed.
- SL_STATUS_BT_MESH_DOES_NOT_EXIST: If the network does not exist.

##### btmesh_db_node_get_by_addr

`btmesh_db_node_t * btmesh_db_node_get_by_addr(uint16_t address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|address|Primary element address of the node|

Get a node by its primary element address

**Returns**

- Pointer to the node, NULL if it does not exist.

##### btmesh_db_node_get_by_uuid

`btmesh_db_node_t * btmesh_db_node_get_by_uuid(uuid_128 uuid)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uuid_128|[in]|uuid|UUID of the node|

Get a node by its UUID

**Returns**

- Pointer to the node, NULL if it does not exist.

##### btmesh_db_node_get_by_mac

`btmesh_db_node_t * btmesh_db_node_get_by_mac(bd_addr mac)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bd_addr|[in]|mac|Bluetooth address of the node|

Get a node by its Bluetooth address

**Returns**

- Pointer to the node, NULL if it does not exist.

##### btmesh_db_node_set_availability

`sl_status_t btmesh_db_node_set_availability(btmesh_db_node_t *node, bool availability)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_db_node_t](btmesh-db-node-t) *|[in]|node|Pointer to the node|
|bool|[in]|availability|The requested status of the availability flag|

Set the availability parameter of a given node

**Returns**

- Status of the command.

**Return values**

- SL_STATUS_OK: If availability flag is set.
- SL_STATUS_NULL_POINTER: If the node does not exist.

##### btmesh_db_node_set_primary_address

`sl_status_t btmesh_db_node_set_primary_address(btmesh_db_node_t *node, uint16_t primary_address)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_db_node_t](btmesh-db-node-t) *|[in]|node|Pointer to the node|
|uint16_t|[in]|primary_address|The requested primary element address|

Set the Primary element address of a given node

**Returns**

- Status of the command.

**Return values**

- SL_STATUS_OK: If primary element address is set.
- SL_STATUS_NULL_POINTER: If the node does not exist.

##### btmesh_db_network_get_network

`btmesh_db_network_t * btmesh_db_network_get_network(uint16_t netkey_index)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the requested network|

Get a network by its netkey index

**Returns**

- pointer to the network. NULL if network does not exist.

##### btmesh_db_is_node_in_network

`bool btmesh_db_is_node_in_network(uint16_t netkey_index, btmesh_db_node_t *node)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|netkey_index|Netkey index of the network|
|[btmesh_db_node_t](btmesh-db-node-t) *|[in]|node|Pointer to the node|

Check if a given node is part of a network

##### btmesh_db_is_node_in_any_network

`bool btmesh_db_is_node_in_any_network(btmesh_db_node_t *node)`

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[btmesh_db_node_t](btmesh-db-node-t) *|[in]|node|Pointer to the node|

Check if a given node is part of any network

Common model identifier structure for Bluetooth SIG and Vendor models. 

##### Public Attributes

###### vendor

```
uint16_t btmesh_db_model_id_t::vendor
```

**Description:** Vendor ID of the model (`MESH_SPEC_VENDOR_ID` for Bluetooth SIG models)

###### model

```
uint16_t btmesh_db_model_id_t::model
```

**Description:** Model ID of the Vendor or Bluetooth SIG model.

Node element represention in the Device Composition Data (DCD) 

##### Public Attributes

###### address

```
uint16_t btmesh_db_element_t::address
```

**Description:** Network address of the element (each element has its own address)

###### location

```
uint16_t btmesh_db_element_t::location
```

**Description:** Location description as defined in the GATT Bluetooth Namespace Descriptors section of the Bluetooth SIG Assigned Numbers.

###### model_count

```
uint16_t btmesh_db_element_t::model_count
```

**Description:** Total number of models in this element (Bluetooth SIG plus Vendor models)

###### models

```
btmesh_db_model_id_t* btmesh_db_element_t::models
```

**Description:** Array of models in this element (Bluetooth SIG plus Vendor models)

Representation of Device Composition Data (DCD) 

##### Public Attributes

###### company_id

```
uint16_t btmesh_db_node_dcd_t::company_id
```

**Description:** Company identifier assigned by the Bluetooth SIG.

###### product_id

```
uint16_t btmesh_db_node_dcd_t::product_id
```

**Description:** Vendor-assigned product identifier.

###### version_id

```
uint16_t btmesh_db_node_dcd_t::version_id
```

**Description:** Vendor-assigned product version identifier.

###### min_replay_prot_list_len

```
uint16_t btmesh_db_node_dcd_t::min_replay_prot_list_len
```

**Description:** Value representing the minimum number of replay protection list entries in a device.

###### feature_relay

```
bool btmesh_db_node_dcd_t::feature_relay
```

**Description:** Relay feature support.

###### feature_proxy

```
bool btmesh_db_node_dcd_t::feature_proxy
```

**Description:** Proxy feature support.

###### feature_friend

```
bool btmesh_db_node_dcd_t::feature_friend
```

**Description:** Friend feature support.

###### feature_low_power

```
bool btmesh_db_node_dcd_t::feature_low_power
```

**Description:** Low power feature support.

###### element_count

```
uint16_t btmesh_db_node_dcd_t::element_count
```

**Description:** Number of elements.

###### elements

```
btmesh_db_element_t* btmesh_db_node_dcd_t::elements
```

**Description:** Array of elements.

The provisioning-related information of a node. 

##### Public Attributes

###### uuid

```
uuid_128 btmesh_db_node_prov_t::uuid
```

**Description:** UUID of the node.

###### mac_address

```
bd_addr btmesh_db_node_prov_t::mac_address
```

**Details:** Bluetooth address of the node. This is only known if the node is unprovisioned beaconing.

###### bearer_type

```
uint8_t btmesh_db_node_prov_t::bearer_type
```

**Description:** Type of the provisioning bearer. One of PB-ADV(0) or PB-GATT(1).

###### prim_address

```
uint16_t btmesh_db_node_prov_t::prim_address
```

**Details:** Primary element address of the node. This is only known if the node is part of a network.

###### element_count

```
uint16_t btmesh_db_node_prov_t::element_count
```

**Description:** Element count of the node.

###### oob_capabilities

```
uint16_t btmesh_db_node_prov_t::oob_capabilities
```

**Description:** Out of band capability mask.

Struct representing one single node. 

##### Public Attributes

###### list_elem

```
sl_slist_node_t btmesh_db_node_t::list_elem
```

**Description:** Linked list of nodes.

###### prov

```
btmesh_db_node_prov_t btmesh_db_node_t::prov
```

**Description:** Provisioning information.

###### dcd_available

```
bool btmesh_db_node_t::dcd_available
```

**Description:** DCD data available.

###### dcd_modified

```
bool btmesh_db_node_t::dcd_modified
```

**Description:** DCD data modified.

###### dcd

```
btmesh_db_node_dcd_t btmesh_db_node_t::dcd
```

**Description:** DCD information.

###### node_available

```
bool btmesh_db_node_t::node_available
```

**Description:** Node is part of a network.

###### primary_subnet

```
btmesh_db_network_t* btmesh_db_node_t::primary_subnet
```

**Description:** The node's primary subnet's address.

Struct representing one single network. 

##### Public Attributes

###### list_elem

```
sl_slist_node_t btmesh_db_network_t::list_elem
```

**Description:** Linked list of networks.

###### netkey_index

```
uint16_t btmesh_db_network_t::netkey_index
```

**Description:** Netkey index of the network.

###### node_count

```
uint16_t btmesh_db_network_t::node_count
```

**Description:** Number of nodes in the network.

###### node_list

```
sl_slist_node_t* btmesh_db_network_t::node_list
```

**Description:** Linked list of nodes in the network.

Helper struct to keep track of which nodes are part of a given network. 

##### Public Attributes

###### list_elem

```
sl_slist_node_t btmesh_db_nodelist_elem_t::list_elem
```

**Description:** Linked list of nodes.

###### node

```
btmesh_db_node_t* btmesh_db_nodelist_elem_t::node
```

**Description:** Pointer to the node.