Compare commits

..
201 Commits
Author SHA1 Message Date
Raoul Rubien 37cd2e2b48 fix esp_https_ota_begin(): implements handling of HttpStatus_PartialContent-code 206 2025-12-03 13:33:05 +01:00
feedc0de c6d093b1a1 Implement i2c_master_multi_buffer_transmit_receive() 2025-12-01 12:45:07 +01:00
feedc0de 688c818c2f Avoid cmake error when variable is not defined 2025-11-27 11:11:21 +01:00
Ferdi265andfeedc0de c9281dc1e3 fix(cmake): Allow disabling component validation
Allow disabling component validation by setting
ESP_IDF_DISABLE_COMPONENT_VALIDATION=1 in the environment.
2025-11-27 11:11:21 +01:00
feedc0de a4f4040ef0 fix(esp_phy): Make config argument const for esp_phy_set_ant_gpio() 2025-11-27 11:11:21 +01:00
feedc0de fdb3a300b3 Allow the https server to request client certs only with OPTIONAL 2025-11-27 11:11:21 +01:00
feedc0de d0cba05798 Update esp-mqtt submodule to my fork with async stop api 2025-11-27 11:11:21 +01:00
feedc0de f34b2966d9 Show stacktrace of task which failed timeout in task watchdog 2025-11-27 11:11:21 +01:00
feedc0de 11769a9eb7 Add uart_read_some_bytes() to allow reading into a buffer without waiting until that buffer is full 2025-11-27 11:11:21 +01:00
feedc0de c9dcfbace5 Add filename and line number back to esp log 2025-11-27 11:11:21 +01:00
Peter Pötziandfeedc0de 2d0af32c8f add function to start spi transaction from isr 2025-11-27 11:11:21 +01:00
feedc0de 1c715e372a set_server_config() set ssl authmode to OPTIONAL 2025-11-27 11:11:21 +01:00
feedc0de b76c9b20de Show websocket network errors 2025-11-27 11:11:21 +01:00
Tobias Schrammandfeedc0de 888952efaa bootloader_support: burn security efuses if flash encryption is enabled
Previously security eFuses were only burnt if the flash was not encrypted
yet.
To enhance robustness of the security eFuse settings their correct setup
should be verified on each bootup. Else it would be possible for an
already encrypted ESP to be reflashed with firmware containing updated,
more restrictive eFuse settings without them ever being applied.
Additionally this change enables easy, secure use of ESPs with host sidee
flash preencryption. Flash preencryption by the host computer performing
the programming procedure can speed up the programming process by a great
deal since the flash no longer needs to be read, erased and written again
by the bootloader self-encryption routines. Additionally it avoids
bricking of ESPs through interruption of the self-ecnryption procedure.
Without this change the host would have to set up all fuses in the ESP
correctly by itself, duplicating the fuse configuration code already
present in the bootloader and creating additional maintenance burden for
the host software if anything about the fuse setup logic changes.
This commit changes the security eFuse configuration logic to always burn
any configured security eFuses on bootup, regardless of current flash
encryption status.
2025-11-27 11:11:21 +01:00
feedc0de 86e4391bde Show remote ip address when somebody requests and invalid path to ease debugging 2025-11-27 11:11:21 +01:00
feedc0de 6846f9846c Return ESP_ERR_HTTP_EAGAIN in http client perform 2025-11-27 11:11:21 +01:00
feedc0de 55092b1409 Less tcp packet fragmentation 2025-11-27 11:11:21 +01:00
feedc0de 0e63b97662 Add missing header include to netif ppp 2025-11-27 11:11:20 +01:00
feedc0de cc60dc1410 Return EAGAIN in http client perform 2025-11-27 11:11:20 +01:00
feedc0de 74cf5f130a Add support for X-WWW-Authenticate header 2025-11-27 11:11:20 +01:00
feedc0de c740d3179b Fix compilation under C++ again 2025-11-27 11:11:20 +01:00
Wei Yuhan d9ad0ad50b change(version): Update version to 6.0.0 2025-11-05 16:25:23 +08:00
Jiang Jiang Jian 8e1ebcad18 Merge branch 'feat/support_nan_usd' into 'master'
Add support for Unsynchronized Service Discovery (USD)

See merge request espressif/esp-idf!30990
2025-10-22 14:00:49 +08:00
Island 883eca3119 Merge branch 'feat/ble_mesh_ble_50_micellaneous_fix' into 'master'
fix(ble_mesh): resolve issues in long packet mode

Closes BLERP-2324, BLERP-2323, BLERP-2322, BLERP-2321, BLERP-2320, and BLERP-2319

See merge request espressif/esp-idf!42745
2025-10-22 10:46:54 +08:00
Island d5086b36ac Merge branch 'feature/ble_mesh_dfu_support' into 'master'
Feature/ble mesh dfu support

Closes BLERP-808

See merge request espressif/esp-idf!31579
2025-10-22 10:42:39 +08:00
Chen Chen 23b76aaf92 Merge branch 'refactor/i2c_op_array_type' into 'master'
refactor(i2c_master): Change member type of i2c_operation_job_t

Closes IDFGH-16453

See merge request espressif/esp-idf!42036
2025-10-22 10:29:05 +08:00
David Čermák 3d5c2efb82 Merge branch 'netif_return_error' into 'master'
Makes netif receive to return error

Closes IDF-7194

See merge request espressif/esp-idf!40325
2025-10-22 03:06:18 +08:00
Jiang Jiang Jian 93f0ecfe2e Merge branch 'fix/eth_init' into 'master'
fix(examples): fixed examples ethernet_init dependency

Closes IDFCI-4847

See merge request espressif/esp-idf!42770
2025-10-22 02:37:12 +08:00
morris 0566fb4260 Merge branch 'pr/17754' into 'master'
build(deps-dev): bump vite

Closes IDFGH-16656

See merge request espressif/esp-idf!42734
2025-10-21 22:31:07 +08:00
Shu Chen 25d269dab6 Merge branch 'feat/ot_ci_log_output' into 'master'
feat(openthread): output logs of host for debugging CI issues

See merge request espressif/esp-idf!42587
2025-10-21 12:02:26 +00:00
Ondrej Kosta 6e160e2e47 fix(examples): fixed examples ethernet_init dependency 2025-10-21 13:06:04 +02:00
Island 160df75e64 Merge branch 'feat/support_get_ble_local_irk' into 'master'
feat(ble/bluedroid): add API to get local BLE IRK

Closes BLERP-2278

See merge request espressif/esp-idf!42214
2025-10-21 18:03:09 +08:00
Roland Dobai c4cabac522 Merge branch 'fix/root_build_error' into 'master'
Fixed unsuccessful build for the IDF root directory attempts in Windows

See merge request espressif/esp-idf!42000
2025-10-21 11:30:14 +02:00
David Čermák 76966b3d8d Merge branch 'fix/docs_dhcp_acd' into 'master'
[lwip]: Clarify and test DHCP conflict detection

Closes IDF-7271

See merge request espressif/esp-idf!42020
2025-10-21 17:28:14 +08:00
luoxu 9f62db74d3 fix(bt): Fixed the issue of duplicate MAX macro definitions 2025-10-21 17:22:22 +08:00
luoxu 1b1a646891 feat(ble_mesh): Adapt DFU/MBT to esp-idf 2025-10-21 17:22:22 +08:00
luoxu 9fd27046c5 feat(ble_mesh): Device Firmware Update (Zephyr v4.0.0) 2025-10-21 17:22:22 +08:00
dependabot[bot]andmorris f3aa1e81a9 build(deps-dev): bump vite version
Merges https://github.com/espressif/esp-idf/pull/17754
2025-10-21 16:38:27 +08:00
luoxu 0772e12f58 fix(ble_mesh): resolve issues in long packet mode
- Fix ignored extended advertising parameters from application
- Fix incorrect filtering of extended advertising reports
- Fix segmentation logic errors in long packet mode
2025-10-21 16:00:48 +08:00
C.S.M 06e5eeb494 Merge branch 'refactor/jpeg_fourcc' into 'master'
refactor(jpeg): Use fourcc for jpeg format

Closes IDF-14231

See merge request espressif/esp-idf!42581
2025-10-21 15:57:20 +08:00
Roland Dobai ca6cfada99 Merge branch 'feat/add_idf_py_mcp' into 'master'
tools: add idf.py mcp-server support

Closes DOC-12659

See merge request espressif/esp-idf!40833
2025-10-21 09:43:13 +02:00
luoxu b01490fc95 fix(ble_mesh): fixed the uninitialized relay advertisement queue on provisioner 2025-10-21 15:42:02 +08:00
luoxu 950b000be6 fix(ble_mesh): Fixed an issue where BLE advertisement packets failed to be sent 2025-10-21 15:41:56 +08:00
luoxu 67539296dd fix(ble_mesh): fixed ble50 advertising on bluedroid 2025-10-21 15:41:48 +08:00
Chen Chen 3d73884ae8 refactor(i2c_master): Change member type of i2c_operation_job_t
Closes https://github.com/espressif/esp-idf/issues/17585
2025-10-21 14:52:57 +08:00
Jakub Kocka 138ef35683 Merge branch 'fix/env_locale' into 'master'
Updated setting of locale to prevent Windows issues with building tools

Closes IDFGH-16402

See merge request espressif/esp-idf!42110
2025-10-21 14:48:34 +08:00
Wang Meng Yang f207bec03c Merge branch 'bugfix/ci_c3eco7_pwr_save_fail' into 'master'
fix(ble): fix ci power save test connection failure

Closes IDFCI-3036

See merge request espressif/esp-idf!42636
2025-10-21 14:40:56 +08:00
Chen Chen bb80291429 Merge branch 'refactor/pre_i2c_removal' into 'master'
refactor(i2c): Add disclaimer for legacy driver

Closes IDF-14262

See merge request espressif/esp-idf!42607
2025-10-21 14:39:09 +08:00
Kevin (Lao Kaiyao) 311158878f Merge branch 'bugfix/fixed_i2s_write_invalid_offset_issue' into 'master'
fix(i2s): fixed invalid offset in the big gap writing scenario

See merge request espressif/esp-idf!42735
2025-10-21 14:33:25 +08:00
Kevin (Lao Kaiyao) dc2415aedf Merge branch 'contrib/github_pr_17742' into 'master'
fix(i2s_hal): fix typo in PDM2PCM check (GitHub PR)

Closes IDFGH-16642

See merge request espressif/esp-idf!42712
2025-10-21 14:29:28 +08:00
laokaiyao 9b69fa150f fix(i2s): fixed invalid offset in the big gap writing scenario 2025-10-21 11:17:49 +08:00
Lv Xin Yue 73115c34c9 Merge branch 'docs/improve_cam_ctrl_header_files' into 'master'
improve cam driver header files

See merge request espressif/esp-idf!42431
2025-10-21 09:15:02 +08:00
Zhang ShuxianandMarek Fiala 512a1d8028 docs: Update CN translation 2025-10-20 16:22:54 +02:00
Marek Fiala c4347a682d feat: Install mcp with initialization scripts 2025-10-20 16:22:54 +02:00
Mahavir JainandMarek Fiala 7c517deb35 tools: add idf.py mcp-server support 2025-10-20 16:22:54 +02:00
Island 7a20f71935 Merge branch 'bugfix/fix_ble_deinit_memory_leak' into 'master'
fix(ble/bluedroid): fix memory leak during deinit when service table is created but not started

Closes BCI-565

See merge request espressif/esp-idf!42456
2025-10-20 22:03:27 +08:00
Lv Xin Yue 31700298ed improve cam driver header files 2025-10-20 18:26:46 +08:00
David Cermak 11921c10b9 fix(esp_netif): Fix return value of PPP input function 2025-10-20 12:22:38 +02:00
David Cermak ee97356448 fix(esp_netif): Add Backward compat option for external components to adjust 2025-10-20 12:22:38 +02:00
David Cermak fd9de0c19e fix(openthread): Update OT netif layers to return error 2025-10-20 12:22:38 +02:00
Euripedes RochaandDavid Cermak afd7d930ee change(esp_netif): Makes netif receive to return error
Makes esp_netif_recv to return errors unconditionally
2025-10-20 12:22:38 +02:00
Zhang Shu Xian e8ce6566d5 Merge branch 'docs/update_reference_to_esp32_errata' into 'master'
docs: Update reference to the specific section in ESP32 Errata

Closes DOC-10080

See merge request espressif/esp-idf!42514
2025-10-20 17:54:19 +08:00
Armando (Dou Yiwen) a02b44deef Merge branch 'fix/fix_xip_power_reset_stuck_issue_p4_rev3' into 'master'
psram: fixed p4 rev3 xip stuck after board reset issue

See merge request espressif/esp-idf!42146
2025-10-20 09:05:58 +00:00
Agócs Dánielandlaokaiyao 041130244c fix(i2s_hal): fix typo in PDM2PCM check
Merges https://github.com/espressif/esp-idf/pull/17742
2025-10-20 16:42:33 +08:00
C.S.M 8a41bb02b4 refactor(jpeg): Use fourcc for jpeg format 2025-10-20 16:18:09 +08:00
Roland Dobai d4900702d5 Merge branch 'ci/github-docker-build' into 'master'
GitHUB CI fix: Add GH hosted large runner for Docker builds

Closes ITOPS-196

See merge request espressif/esp-idf!42684
2025-10-20 10:15:05 +02:00
Erhan Kurubas 8ee473d06e Merge branch 'change/apptrace_public_interface' into 'master'
Apptrace API changes and allow runtime destination selection

Closes DOC-12445, IDF-4738, and IDF-3357

See merge request espressif/esp-idf!41597
2025-10-20 10:10:01 +02:00
morris 2fb0c3cdfe Merge branch 'fix/i2c_disable_od_in_delete' into 'master'
fix(i2c): disable open drain mode on deinit

Closes IDFGH-16635

See merge request espressif/esp-idf!42644
2025-10-20 15:27:06 +08:00
Sarvesh Bodakhe 4c3d6c1292 fix(wifi): Add refactoring and migration guide for USD, Offchan_tx, ROC
1. fix(wifi): Rename old NAN configuration to NAN-Sync
  - Rename CONFIG_ESP_WIFI_NAN_ENABLE to CONFIG_ESP_WIFI_NAN_SYNC_ENABLE to indicate
    the support for Synchronized NAN (Wi-Fi Aware).
  - Because the original flag really controls the synchronized feature set, rename it
    to CONFIG_ESP_WIFI_NAN_SYNC_ENABLE so the NAN-Sync and NAN-USD paths can be
    selected independently without confusion.
2. Document esp_wifi_start requirement and fix USD examples
3. Rename nan_callbacks to nan_sync_callbacks
4. Remove the discovery_flag, clarify docs for sync vs USD flows, and add USD start/stop APIs
5. Require esp_wifi_start() before USD start
6. docs(nan): add NAN-USD application examples
7. add migration guide and hints for NAN-USD proto field
8. Improve allow_broadcast documentation
9. Add attention to the API esp_wifi_remain_on_channel
10. fix(wifi): align NAN API renames and docs for v6.0
  - keep shared APIs under esp_wifi_nan_* while reserving
    sync/usd names for mode-specific entry points
  - clarify synchronized-cluster scope in headers, docs, and migration notes (EN/zh-CN)
  - update examples for renamed helpers and WIFI_NAN_SYNC_CONFIG_DEFAULT()
  - rename `wifi_nan_config_t` to `wifi_nan_sync_config_t`
11. Mark NAN-USD as esp-idf experimental feature
2025-10-20 12:46:55 +05:30
Sarvesh Bodakhe a5f6bc639b feat(wifi): Add support to set BSSID (A3) in esp_wifi_action_tx_req 2025-10-20 12:46:44 +05:30
Sarvesh BodakheandShyamal Khachane 93347494b3 feat(wifi): Add support for Wi-Fi Aware: Unsynchronized Service Discover (USD)
1.  Remove redundant fixes in upstream wpa_supplicant for USD
    - Upstream supplicant has mostly fixed the issues regarding the
      unnecessary resetting pauseStateTimeout.
    - Upstream supplicant still needs one fix to avoid resetting the
      pauseStateTimeout when subscribe message is received from the peer
      which had triggered the pauseStateTimeout previously.

2.  Replace array-based channel list with bitmap for NaN-USD

    Use `wifi_scan_channel_bitmap_t` to represent the channel list for NaN-USD
    publisher and subscriber configurations. This replaces the previous approach
    that used a large array to store allowed channels.

    Also aligns with internal scan bitmap conventions across Wi-Fi stack.

3.  call esp_wifi_nan_stop() after USD exchange or STA stop

    Ensure esp_wifi_nan_stop() is called after publish/subscribe activity
    completes or when WIFI_EVENT_STA_STOP is received. This prevents NAN stop
    errors due to inactive interface. NaN-USD currently uses STA interface
    for Tx/Rx.

4.  Fix task watchdog timer triggered in active USD subscriber:

    As both USD supplicant and offchan TX component gets executed
    in the wifi task, it created a deadlock like scenario where offchan TX
    done callback was never getting executed and supplicant 'nan_de_timer'
    keeps running but failing to send any subscribe frame.

5.  Make sure that device is able to recieve action management frames
    of size more than 1400 bytes.

6.  Update proto field in SSI to match Wi-Fi Aware (NaN) spec format

    The 'proto' field in the 'wifi_nan_wfa_ssi_t' structure previously used an
    enum (wifi_nan_svc_proto_t), resulting in a 32-bit field. According to
    the Wi-Fi NAN Specification (Table 5.7), this field must be a single
    octet (8 bits). This commit updates the type to uint8_t to ensure
    compliance with the specification.

    This mismatch previously triggered warnings but did not cause functional
    errors.

7.  Set `allow_broadcast` to true in USD Remain on channel

    This enables the peer discovery as USD uses NAN-Network Multicast BSSID
    as A3 address in publish frames.

8.  Implement custom channel<->frequency conversion for NAN-USD

    NaN-USD only permits 20 MHz bandwidth channels in the 2.4 GHz and 5 GHz bands
    (as per section 4.5.3 of the Wi-Fi Aware Specification v4.0). To avoid linking
    a large portion of upstream supplicant code for frequency-to-channel and
    channel-to-frequency conversion, implement minimal custom helper functions.

9.  Limit NAN_DE_MAX_SERVICE to 2 for ESP_SUPPLICANT

10. Note: Upstream clamps negative `os_reltime` deltas to zero in `nan_de_srv_time_to_next()`,
    but our ESP_SUPPLICANT port keeps `os_time_t` unsigned, so that guard just provokes a
    compiler warning. We skip it for now because the scheduling loop validates past timestamps
    before computing the diff.

Co-authored-by: Shyamal Khachane <shyamal.khachane@espressif.com>
2025-10-20 12:18:28 +05:30
Sarvesh Bodakhe 6255a67654 fix(wifi): Add support to receive broadcast frames in ROC (Remain on Channel)
This commit adds the support to receive broadcast frames in ROC Rx
callback. Some use cases may need to receive broadcast packets for
discovery of other peers.

- This can be enabled/disabled through 'allow__broadcast' flag in
  'wifi_roc_req_t' structure.
- In default configration, broadcast packets will always be filtered out and
  will not be passed to the Rx callback to save CPU consumption.
2025-10-20 12:18:19 +05:30
Sarvesh Bodakhe b1d1897547 fix(wifi): Make sure that USD APIs do not alter the SSI information
1.  Make sure that wpa_supplicant does not encapsulate user-given SSI info
    with WFA OUI.

2.  USD component shall transfer the SSI given by user as it is, without
    any modification or encapsulation.

3.  Note that this will break the compatibility of ESP USD implementation
    with a device running upstream wpa_supplicant as wpa_supplicant
    encapsulates the SSI information with WfA oui.
    For compatibility with wpa_supplicant, user needs to handle the
    SSI encapsulation/decapsulation.
2025-10-20 12:18:19 +05:30
Andrei OtcheretianskiandSarvesh Bodakhe 0ad3af78a6 NAN: Remove excessive debug print about the next timer
As it polutes the log too much.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2025-10-20 12:18:19 +05:30
Andrei OtcheretianskiandSarvesh Bodakhe a83d66cb88 NAN: Fix A3 for unicast P2P2 USD
According to the Wi-Fi Direct spec draft, address 3 in unicast USD
frames shall be set to the P2P Device Address of the sender (i.e., this
differs from the Wi-Fi Aware specification). Fix it.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2025-10-20 12:18:19 +05:30
Andrei OtcheretianskiandSarvesh Bodakhe 706b211dbf NAN: Fix A3 for multicast P2P2 USD
According to the Wi-Fi Direct spec draft, address 3 in multicast USD
frames shall be set to wildcard BSSID (i.e., this differs from the Wi-Fi
Aware specification). Fix it.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2025-10-20 12:18:19 +05:30
Shivani BaranwalandSarvesh Bodakhe 105225be91 NAN USD: Use different group address for P2P2
P2P2 uses USD with a different group address than the NAN Network ID
defined in the Wi-Fi Aware specification. Select the group address based
on whether USD is used with P2P2 or something else. This changes
behavior only for the P2P2 cases.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 8489c48dda NAN: Do not expire USD services based on last TX/RX message
This behavior is not described in the Wi-Fi Aware specification, so
remove it and instead, expect services to terminate USD explicitly when
no further Follow-up messages are needed.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 63445ae0f7 NAN: Wait on the channel with publisher is in pauseState
Remain waiting for additional Follow-up messages on a publisher that is
in pauseState for a service that requires further service discovery.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 62e7fa86ab NAN: Limit pauseState to be within service lifetime
If a publish service is configured with an explicit lifetime (ttl), do
not allow pauseState duration to exceed that.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 7ba048a8c5 NAN: Print a debug entry on TX wait time expiration
This can be helpful for understanding NAN DE behavior.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 1c18f52de0 NAN: Make DE aware of maximum driver supported listen time
This can be used to optimize listen operations to be as long as the
driver supports instead of having to use a small enough value to work
with all drivers.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe fd7b14af83 NAN: Do not unpause publisher on fixed Follow-up message timeout
Do not unpause publisher if more than one second has passed from the
last Follow-up message TX or RX. There is no such behavior described in
the Wi-Fi Aware specification and it is possible for a service to need
more time to generate Follow-up messages. Leave it to the service itself
to force timeout, if desired, or terminate pauseState after the 60
second overall timeout.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe aa433f46c9 NAN: Handle A3 copying internally to simplify control interface
There is no need to copy the A3 value for follow-up frames through the
control interface events and commands since it can be handled internally
in the service with sufficient accuracy. More parallel operations with
multiple peers might need per-peer information, but that can be extended
in the future, if that level of complexity is really needed in practice.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 6fe979cad1 NAN: Update A3 for USD to use NAN Network ID or NAN Cluster ID in A3
Wi-Fi Aware spec v4.0 was not clear on all cases and used a bit unclear
definition of A3 use in Table 5 (Address field definiton for NAN SDF
frames in USD). That resulted in the initial implementation using
Wildcard BSSID to comply with the IEEE 802.11 rules on Public Action
frame addressing.

For USD to have chances of working with synchronized NNA devices, A3
needs to be set to the NAN Cluster ID when replying to a frame received
from a synchronized NAN device. While there is no cluster ID for USD,
this can be done by copying the A3 from the received frame. For the
cases where sending out an unsolicited multicast frame, the NAN Network
ID should be used instead of the Wildcard BSSID.

While this behavior is not strictly speaking compliant with the IEEE
802.11 standard, this is the expected behavior for NAN devices, so
update the USD implementation to match.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe cbb2ee7ba7 NAN: Process received NAN SDFs with NAN Network ID in A3 on AP
hostapd did not accept NAN SDFs that used NAN Network ID instead of
Wildcard BSSID in A3. Extend this to process NAN Network ID just like
Wildcard BSSID for these frames to allow the specific group address to
be used.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Shivani BaranwalandSarvesh Bodakhe bbeb70d81b NAN USD: Add publishChannelList option for Subscriber
Add frequency list to active NAN USD Subscriber to search for a
Publisher on multiple channels. This is the publish channel list used by
the Subscriber to periodically search for a service on these channels.
publishChannelList was already supported in the Publisher and this
commit extends that to the Subscriber.

This is needed for a P2P2 seeker that is an active subscriber looking
for an advertiser on a list of publish channels.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2025-10-20 12:18:19 +05:30
Shivani BaranwalandSarvesh Bodakhe 59dfc2ec32 P2P2: Allow P2P IE to be added into NAN SDFs
Extend the NAN Subscribe and Publish methods to allow p2p=1 to be
specified to include P2P attributes in a P2P IE to be added into the NAN
Element Container attribute. In addition, use the P2P Device Address for
the NAN SDFs for the P2P cases.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2025-10-20 12:18:19 +05:30
Shivani BaranwalandSarvesh Bodakhe 8173b5cc87 NAN: Option to offload NAN DE for USD into the driver
Support implementation architecture where the NAN discovery engine is
located in the driver/firmware instead of wpa_supplicant.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2025-10-20 12:18:19 +05:30
Chien WongandSarvesh Bodakhe 35e508258d NAN: Reject undefined publish type
The Wi-Fi Aware Specification v4.0 only defines unsolicited
transmissions only, solicited transmissions only and both unsolicited
and solicited transmissions publish. The other possibility is undefined
so we should reject it.

Signed-off-by: Chien Wong <m@xv97.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe 6a1c9a5f26 NAN: Unsynchronized service discovery (USD)
Add NAN discovery engine and wpa_supplicant interface to use it for the
subset of NAN functionality that is needed for USD.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:19 +05:30
Jouni MalinenandSarvesh Bodakhe e1791e769c NAN: Protocol definitions
Add NAN protocol definitions that are needed for USD based on Wi-Fi
Aware specification v4.0.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2025-10-20 12:18:18 +05:30
Jiang Jiang Jian 6566973398 Merge branch 'bugfix/fix_ptk_key_memory_leak_issue' into 'master'
fix(wifi): fix pkt key memory leak issue

Closes WIFI-7065

See merge request espressif/esp-idf!42417
2025-10-20 14:04:56 +08:00
Chen Chen 4ac9954101 refactor(i2c): Add disclaimer for legacy driver 2025-10-20 11:38:26 +08:00
armando 9fadbf2588 fix(psram): fixed p4 rev3 xip stuck after board reset issue 2025-10-20 03:09:47 +00:00
Shen Meng Jing c8bbe90e26 Merge branch 'docs/update_cn_storage' into 'master'
docs: Update CN translation for storage.rst

Closes DOC-12508

See merge request espressif/esp-idf!42533
2025-10-20 10:42:12 +08:00
Shen Meng Jing 76dc7098a0 Merge branch 'docs/update_cn_translation' into 'master'
docs: Update CN translation

Closes DOC-12501

See merge request espressif/esp-idf!42467
2025-10-20 10:37:44 +08:00
morris 8f87fe4770 Merge branch 'feat/esp_hal_dma' into 'master'
feat(dma): graduate the dma driver into a single component: esp_hal_dma

Closes IDF-14080, IDF-13675, and IDF-13673

See merge request espressif/esp-idf!42250
2025-10-20 00:16:47 +08:00
morris 2de3be7300 feat(dma): graduate the dma driver into a single component 2025-10-19 22:06:46 +08:00
Erhan KurubasandBOT 2ef718fc29 change(app_trace): breaking changes related to destination selection
- Destination selection is unified for SystemView and app_trace
- Destination param is removed from app_trace APIs
- Destinaiton and related configuration now can be override from users
  with a callback from system_init_fn
2025-10-18 02:28:31 +08:00
Erhan KurubasandBOT 68764bf80f refactor(app_trace): remove redundant init call from startup 2025-10-18 02:28:31 +08:00
Erhan KurubasandBOT 006ab972c7 docs(app_trace_to_plot): fixed OpenOCD command in README 2025-10-18 02:28:31 +08:00
Erhan KurubasandBOT 72b45ab2a6 change(examples): disable gcov build and tests because of apptrace breaking changes 2025-10-18 02:28:31 +08:00
Marius Vikhammer ca626ae04f Merge branch 'fix/missing_requirement_in_test_app' into 'master'
fix(esp_hw_support): add the missing dependency of esp_hal_wdt component in test app

See merge request espressif/esp-idf!42681
2025-10-18 00:00:40 +08:00
Mahavir Jain e351376dcf Merge branch 'fix/esp_tee_int_wdt' into 'master'
fix(esp_tee): Sync M-U interrupt thresholds during service calls from critical sections

See merge request espressif/esp-idf!42365
2025-10-17 17:40:53 +05:30
Mahavir Jain 1b8994c739 Merge branch 'feat/esp32p4_eco5_support_km_memprot' into 'master'
Support newer Key Manager key sources for ESP32-P4 V3

Closes IDF-13524, IDF-13527, IDF-13528, and IDF-12233

See merge request espressif/esp-idf!42360
2025-10-17 17:33:02 +05:30
Island 4cd13a9317 Merge branch 'fix/update_pawr_example_docs' into 'master'
Fix/update pawr example docs

See merge request espressif/esp-idf!42161
2025-10-17 18:03:00 +08:00
Shen Mengjing d67a677331 docs: Update CN translation for storage.rst 2025-10-17 17:57:28 +08:00
zhanghaipeng 9df828835c fix(ble/bluedroid): fix memory leak during deinit when service table is created but not started 2025-10-17 17:45:35 +08:00
zhanghaipeng 3c68650d7e feat(ble/bluedroid): add API to get local BLE IRK 2025-10-17 17:36:45 +08:00
Shen Mengjing 5d57ad769d docs: Update CN translation 2025-10-17 17:21:56 +08:00
Wu Zheng Hui 6d2487082e Merge branch 'fix/fix_coverity_issues' into 'master'
fix(esp_hw_support): fix coverity issues in esp_hw_support

Closes IDF-13819, IDF-13892, and IDF-13894

See merge request espressif/esp-idf!42566
2025-10-17 16:53:49 +08:00
muhaidong f5db0eafbe fix(wifi): fix pkt key memory leak issue 2025-10-17 16:22:09 +08:00
Marius Vikhammer 19e0997436 Merge branch 'feature/esp_stdio' into 'master'
feat(stdio): added new esp_stdio component

Closes IDF-13799

See merge request espressif/esp-idf!41625
2025-10-17 16:11:16 +08:00
Jakub Kocka 7e09b471ab fix: Updated locale handling to prevent issues with build tools
Closes https://github.com/espressif/esp-idf/issues/17542
2025-10-17 09:58:44 +02:00
Jakub Kocka 21c2ad8c23 fix: Added check to prevent IDF root directory build failed attempts in Win
Closes https://github.com/espressif/esp-idf/issues/17516
2025-10-17 09:37:04 +02:00
Armando (Dou Yiwen) 57bc0fe12c Merge branch 'feat/mspi_axi_arb' into 'master'
mspi: axi arb priority

Closes IDF-14125

See merge request espressif/esp-idf!42602
2025-10-17 06:07:51 +00:00
Jiang Jiang Jian 4563f8ee5f Merge branch 'change/remove_rtc_attrs' into 'master'
fix(esp_hw_support): fix rtc_clk test case time stamp lost

Closes IDF-14228

See merge request espressif/esp-idf!42632
2025-10-17 14:00:09 +08:00
Marius Vikhammer 4dd3fe78f7 Merge branch 'ci/update_mr_template' into 'master'
ci(gitlab): remove refs to release notes in MR templates

See merge request espressif/esp-idf!42601
2025-10-17 13:36:40 +08:00
morris ee8e47ffa1 fix(esp_hw_support): add the missing dependency of esp_hal_wdt component in test app 2025-10-17 13:10:57 +08:00
morris f4ba6279f1 fix(i2c): remove notfix(i2c): disable open drian mode on deinit
Closes https://github.com/espressif/esp-idf/issues/17737
2025-10-17 13:08:25 +08:00
morris e5da8951b3 fix(uart): always add NOP workaround for UART FIFO read on esp32 2025-10-17 13:08:25 +08:00
Tomas Sebestik e337f85adc ci(github-docker-build): add GH hosted large runner for docker builds 2025-10-17 07:02:46 +02:00
Laukik Hase 66c16561f5 Merge branch 'fix/c5_tee_sram_prot' into 'master'
fix(esp_tee): Split TEE SRAM as I/DRAM for ESP32-C5 with PMA

See merge request espressif/esp-idf!42347
2025-10-17 10:21:09 +05:30
Mahavir Jain ac6aeda1ec Merge branch 'feat/enable_pseudo_round_support_for_aes' into 'master'
feat: enable pesudo round functionality for AES in ESP32P4 ECO5

Closes IDF-13526 and IDF-13437

See merge request espressif/esp-idf!42204
2025-10-17 08:26:32 +05:30
Mahavir Jain fcc01f872b Merge branch 'fix/allign_hal_crypto_ecdsa_test_parameters_with_mbedtls_tests' into 'master'
feat(hal/test_apps): Align hal/crypto ECDSA test parameters to mbedtls test_apps

See merge request espressif/esp-idf!42226
2025-10-17 08:25:49 +05:30
Wang Meng Yang 171fc377ce Merge branch 'bugfix/fix_bt_coverity' into 'master'
fix(esp_coex): fix explicit null dereferenced reported by coverity

Closes IDF-14126

See merge request espressif/esp-idf!42062
2025-10-16 18:58:40 +08:00
Nilesh Kale 92d4e3afd1 Merge branch 'feature/partial_download_over_single_connection' into 'master'
feat(esp_https_ota): Support partial downloading of OTA over single connection

Closes IDF-13400

See merge request espressif/esp-idf!41911
2025-10-16 18:32:15 +08:00
Konstantin Kondrashov 610971835b Merge branch 'feature/support_efuses_esp32p4_eco5' into 'master'
feat(efuse): Support efuses for ESP32-P4 ECO5

Closes IDF-13512 and IDF-13562

See merge request espressif/esp-idf!41607
2025-10-16 17:31:59 +08:00
Rahul Tank 7ae7dcd1da Merge branch 'fix/ble_gap_conn_handle_overflow' into 'master'
fix(nimble) Fix array overflow caused by invalid connection handle indexing

Closes BLERP-2297 and BLERP-2298

See merge request espressif/esp-idf!42124
2025-10-16 14:32:16 +05:30
Konstantin Kondrashov fb91ddd813 Merge branch 'fix/test_time_ut' into 'master'
fix(esp_libc): Fix test_time UTs for newlib nano format

Closes IDFCI-3389

See merge request espressif/esp-idf!42399
2025-10-16 16:24:56 +08:00
He Binglin f840c0bd32 Merge branch 'feat/esp_idf_c61_doc' into 'master'
docs(pm): update power management related docs for esp32c61

Closes IDF-10116

See merge request espressif/esp-idf!42515
2025-10-16 16:09:43 +08:00
xiongweichao 7920885608 fix(ble): fix ci power save test connection failure 2025-10-16 15:59:19 +08:00
Kevin (Lao Kaiyao) 30d0ededbe Merge branch 'refactor/remove_legacy_touch_dependency_in_ulp' into 'master'
refactor(touch): remove legacy touch driver dependency in ulp

Closes IDF-14263

See merge request espressif/esp-idf!42404
2025-10-16 15:26:02 +08:00
Meet Patel 6491647fcb Merge branch 'feature/rtc_wdt_test_app' into 'master'
feat(rtc_wdt): Added unity app to test rtc watchdog timer functions

Closes IDF-12273

See merge request espressif/esp-idf!42568
2025-10-16 12:55:13 +05:30
Wu Zheng Hui e1b6006761 Merge branch 'fix/fix_esp32c5_xtal32k_clock_lost_in_sleep' into 'master'
fix(esp_system): manage slow clock sleep pd in select_rtc_slow_clk

See merge request espressif/esp-idf!41591
2025-10-16 15:24:50 +08:00
wuzhenghui c396fd5ec3 fix(esp_hw_support): fix rtc_clk test case time stamp lost 2025-10-16 14:51:52 +08:00
Chen Chen 260443fe73 Merge branch 'fix/i2c_lp_test' into 'master'
fix(i2c/gpio): Add error checks to the i2c driver & Fix errors in gpio

Closes IDF-13942

See merge request espressif/esp-idf!41527
2025-10-16 13:51:18 +08:00
morris d5ff73e928 Merge branch 'feature/esp32p4_eco5_support' into 'master'
feat(gpio/ledc/uart/2ddma/ppa): ESP32P4 ECO5 related updates

Closes IDF-13419, IDF-13425, IDF-13427, IDF-13436, IDF-13740, IDF-13741, IDF-13675, IDF-12225, IDF-13823, IDF-13514, IDF-13539, and IDF-13533

See merge request espressif/esp-idf!41980
2025-10-16 11:16:34 +08:00
Gao Xu 5d8af45b21 Merge branch 'refactor/rng_ll_c3' into 'master'
refactor(rng): refactor to use hal/ll apis for C3

Closes IDF-12535

See merge request espressif/esp-idf!42249
2025-10-16 11:16:08 +08:00
Island 1f085d5c0e Merge branch 'fix/change_api_to_enable_rc32k' into 'master'
fix: change the api to enable rc32k

Closes BLERP-2283

See merge request espressif/esp-idf!42284
2025-10-16 11:11:13 +08:00
Armando (Dou Yiwen) ba7d244762 Merge branch 'change/remove_rtc_attrs' into 'master'
rtc: removed rtc related memory attrs on no-rtc-support chips

Closes IDF-7680 and IDF-14228

See merge request espressif/esp-idf!42101
2025-10-16 03:04:25 +00:00
Zhang Shuxian 52aa593617 docs: Update reference to the specific section in ESP32 Errata 2025-10-16 10:08:16 +08:00
Marius Vikhammer a257812e14 feat(stdio): added esp_stdio component
esp_stdio contains everything the old esp_vfs_console contained (the vfs stdio glue layer)
as well as other functionality related to stdio (previously referred to as console)
2025-10-16 10:01:59 +08:00
Laukik Hase 9de1d631b4 feat(esp_tee): Reclaim unused TEE IRAM memory as heap
- Changed the default TEE code placement to use the flash
  text section instead of IRAM text, making it consistent
  with the default data placement.
2025-10-15 18:22:44 +05:30
Laukik Hase 20344640e3 fix(esp_tee): Split TEE SRAM as I/DRAM for ESP32-C5 with PMA 2025-10-15 18:22:43 +05:30
Konstantin Kondrashov 6f9e137336 feat(efuse): Adds calibration efuses for ESP32-P4 ECO5 2025-10-15 15:36:56 +03:00
Konstantin Kondrashov 969d017c56 feat(efuse): Support efuses for ESP32-P4 ECO5 2025-10-15 15:36:55 +03:00
Island 7ce5732049 Merge branch 'feat/esp32c2_add_get_used_heap_size' into 'master'
Feat/esp32c2 add get used heap size

Closes BLERP-2245, BLERP-2276, and BLERP-2277

See merge request espressif/esp-idf!42168
2025-10-15 20:14:30 +08:00
Wu Zheng Hui dfeae969a4 Merge branch 'feat/support_esp32p4_eco5_pmu' into 'master'
feat(esp_hw_support): Update esp32p4 eco5 lowpower features support

See merge request espressif/esp-idf!41162
2025-10-15 19:47:43 +08:00
Tomas Rohlinek 7d7c5f1412 Merge branch 'fix/vfs_new_api_docs' into 'master'
fix(storage/vfs): Fix typo in code snippet in docs

Closes IDF-14285

See merge request espressif/esp-idf!42609
2025-10-15 13:34:15 +02:00
Chen Ji Chang a480689459 Merge branch 'feat/re_support_i80_on_p4_eco5' into 'master'
feat(i80_lcd): re-support i80 lcd on p4eco5

Closes IDF-13821

See merge request espressif/esp-idf!42117
2025-10-15 19:14:31 +08:00
ShreeyashandRahul Tank dd2cdf18cc fix(nimble): fix array overflow caused by invalid connection handle indexing 2025-10-15 15:58:08 +05:30
harshal.patil 609d52c6bf feat(esp32p4): Support newer Key Manager key sources for ESP32-P4 V3 2025-10-15 15:49:20 +05:30
Song Ruo Jing 6776f65fc9 feat(ppa): ESP32P4 ECO5 PPA related updates
PPA SRM engine added YUV422 and GRAY8 color mode support
PPA SRM engine macro block size increased to 32x32
PPA Blending engine added YUV420, YUV422 and GRAY8 color mode support
2025-10-15 16:49:22 +08:00
Song Ruo Jing dd5d4bd8d7 feat(2ddma): ESP32P4 ECO5 2DDMA related updates
Added one more pair of 2DDMA channels
Priority bit width increased corespondingly
Added three new CSC modes for RX channel 0
Also cleaned up DMA2D capability definitions in soc_caps.h
2025-10-15 16:49:22 +08:00
Song Ruo Jing 4b0524258d feat(interrupts): ESP32P4 ECO5 interrupt sources update 2025-10-15 16:49:22 +08:00
Song Ruo Jing 08bc91ecc5 fix(clk): allow P4 CPU clk freq can auto switch between 360/400MHz according to revision 2025-10-15 16:49:21 +08:00
Song Ruo Jing ccca5a19ca feat(uart): ESP32P4 ECO5 UART related updates 2025-10-15 16:49:21 +08:00
Song Ruo Jing 22dfacc18d feat(ledc): ESP32P4 ECO5 LEDC related updates 2025-10-15 16:49:21 +08:00
Tomáš Rohlínek 4568f6c776 fix(storage/vfs): Fix typo in code snippet in docs 2025-10-15 10:08:52 +02:00
Xu Si Yu 13df28d5c9 feat(openthread): output logs of host for debugging CI issues 2025-10-15 15:28:39 +08:00
zwl e87ace3a33 feat(ble): change free api on ESP32-C5 2025-10-15 15:11:06 +08:00
zwl 034172154a feat(ble): change free api on ESP32-C6 2025-10-15 15:11:06 +08:00
zwl e18972e94e feat(ble): change free api on ESP32-C2 2025-10-15 15:11:06 +08:00
zwl 149f6c56b3 feat(ble): add get used mem api 2025-10-15 15:11:02 +08:00
Laukik Hase 8770ae9db4 fix(esp_tee): Sync TEE-REE intr thresholds during service calls from critical sections
- Previously, only the U-mode interrupt threshold was raised in REE critical sections,
  leaving M-mode at the lowest level.
- As a result, when a service call transitioned to M-mode, all interrupts were still
  allowed to fire, including those that should have been masked.
2025-10-15 12:33:31 +05:30
Meet Patel 9b86dc25ab feat(rtc_wdt): Added unity app to test rtc watchdog timer functions
Unity based test app configures RTC WDT to verify following features:
1. Verify all 4 stages of RTC WDT are able to trigger timeout and
   invoke the pre-configured interrupt service routine
2. Verify RTC WDT can reset the main SYSTEM or main SYSTEM + RTC
2025-10-15 12:14:19 +05:30
Chen Chen 29f8fcf7b7 fix(i2c/gpio): Add error checks to the i2c driver
Add more checks to i2c driver, as well as fixed some GPIO issues
together with it.
2025-10-15 10:38:59 +08:00
armando abfad4d255 feat(mspi): axi arb priority 2025-10-15 09:59:16 +08:00
laokaiyao 14cf724f64 refactor(touch): remove legacy touch driver dependency in ulp 2025-10-15 09:44:43 +08:00
Marius Vikhammer 8a10c7ae6a ci(gitlab): remove refs to release notes in MR templates 2025-10-15 09:39:10 +08:00
wuzhenghuiandArmando (Dou Yiwen) 5bdcc8f5b0 change(esp_hw_support): update RTC mem attr in sleep_modes.c 2025-10-15 01:19:02 +00:00
armando 0f6adbebed change(memory): removed rtc related memory attrs on no-rtc-support chips 2025-10-15 01:19:02 +00:00
David Cermak 0586066d1b fix(lwip): Clarify and test DHCP conflict detection 2025-10-14 12:48:58 +02:00
wuzhenghui 065dd70056 change(esp_hw_support): move ESP_SLEEP_POWER_DOWN_CPU to Kconfig 2025-10-14 16:33:30 +08:00
wuzhenghui 69553da81a fix(esp_hw_support): fix P4 v3.0 USB leakage on PU_CNNT lightsleep 2025-10-14 16:33:30 +08:00
wuzhenghui f68896ca53 fix(esp_hw_support): add the TOP domain's power-off dependency on the CNNT domain 2025-10-14 16:33:30 +08:00
wuzhenghui e1e649ab89 fix(esp_hw_support): disable HP regulator if DCDC keeps powering during sleep 2025-10-14 16:33:29 +08:00
wuzhenghui bedcf4ad88 change(esp_hw_support): allocate memory with MALLOC_CAP_RETENTION for regdma link 2025-10-14 16:33:29 +08:00
wuzhenghui 3b950401d8 change(soc): reset L2 Cache sync after config restore 2025-10-14 16:33:29 +08:00
wuzhenghui af1c8a568d feat(esp_hw_support): update cpu_pd support for esp32p4 v3.0 2025-10-14 16:33:28 +08:00
wuzhenghui 0eab2428c3 feat(esp_hw_support): update pmu support for esp32p4 v3.0 2025-10-14 16:33:28 +08:00
wuzhenghui ff6d219775 feat(soc): support esp32p4 rev3.0 soc 2025-10-14 16:33:28 +08:00
wuzhenghui 55bab4c4b2 fix(esp_hw_support): fix Coverity static analysis issue in regdma_link_update_next 2025-10-13 20:47:50 +08:00
wuzhenghui e71265839e change(esp_hw_support): fix dead code in esp_sleep_pd_config and add detailed comments 2025-10-13 20:35:10 +08:00
yangfengandBOT d9ce1e6bc9 fix(esp_coex): fix explicit null dereferenced reported by coverity 2025-10-13 19:39:51 +08:00
hebinglin f8a5ae28a7 docs(pm): update power management related docs for esp32c61 2025-10-11 16:14:19 +08:00
Chen Jichang 5868098168 feat(lcd): re-support i80 lcd and support underrun inerrupt on p4 rev 3.0 2025-10-11 14:32:09 +08:00
nilesh.kale 709b869a34 feat(esp_https_ota): Support partial downloading of OTA over single connection
This commit added support to download OTA with partial download feature
over single HTTP connection if server supports persistent connection.
2025-10-10 15:42:47 +05:30
wuzhenghui aab33f3219 fix(esp_system): manage slow clock sleep pd in select_rtc_slow_clk 2025-10-09 20:03:49 +08:00
nilesh.kale 28e332b7fa feat: enable pesudo round functionality for AES in ESP32P4 ECO5 2025-10-08 15:40:25 +05:30
Konstantin Kondrashov caf15b8f66 fix(esp_libc): Fix test_time UTs for newlib nano format
Optimized UTs for newlib nano format (where no support 64 bits print).
(C2 chip with CONFIG_LIBC_NEWLIB_NANO_FORMAT=y)
2025-10-08 12:00:34 +03:00
cjin 9c3bcab65c fix: change the api to enable rc32k on ESP32-H2 2025-09-30 14:18:30 +08:00
gaoxu 85144da53e refactor(rng): refactor to use hal/ll apis for C3 2025-09-28 14:34:30 +08:00
cjin abfc2d766e feat(ble): allow a larger sca limit on ESP32-H2 2025-09-26 18:04:27 +08:00
cjin b3c608f2cf feat(ble): allow a larger sca limit on ESP32-C6 2025-09-26 18:04:27 +08:00
cjin f012fafe51 feat(ble): allow a larger sca limit on ESP32-C5 2025-09-26 18:04:27 +08:00
cjin 9ecf67b230 feat(ble): allow a larger sca limit on ESP32-C2 2025-09-26 18:04:19 +08:00
nilesh.kale 5bad8496dc feat(hal/test_apps): Aligh hal/crypto ECDSA test parameters to mbedtls test_apps
Updated the hal/crypto ECDSA test parameters to match the configuration used
mbedtls/ test applications for consistency and easier maintenance.
2025-09-26 15:09:22 +05:30
cjin 164fec9e74 fix(ble): update the example docs for pawr 2025-09-25 14:37:04 +08:00
658 changed files with 34529 additions and 30930 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
# Disable the job in forks
if: ${{ github.repository_owner == 'espressif' }}
runs-on: ubuntu-latest
runs-on: ubuntu-24.04-X64-large
steps:
# Depending on the branch/tag, set CLONE_BRANCH_OR_TAG variable (used in the Dockerfile
# as a build arg) and TAG_NAME (used when tagging the image).
+1 -2
View File
@@ -117,13 +117,12 @@
/components/esp_ringbuf/ @esp-idf-codeowners/system
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
/components/esp_security/ @esp-idf-codeowners/security
/components/esp_stdio/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
/components/esp_system/ @esp-idf-codeowners/system
/components/esp_tee/ @esp-idf-codeowners/security
/components/esp_timer/ @esp-idf-codeowners/system
/components/esp-tls/ @esp-idf-codeowners/app-utilities
/components/esp_usb_cdc_rom_console/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals/usb
/components/esp_vfs_*/ @esp-idf-codeowners/storage
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
/components/esp_wifi/ @esp-idf-codeowners/wifi
/components/espcoredump/ @esp-idf-codeowners/debugging
/components/esptool_py/ @esp-idf-codeowners/tools
+1 -1
View File
@@ -37,7 +37,7 @@ variables:
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
# we're using .cache folder for caches
GIT_CLEAN_FLAGS: -ffdx -e .cache/
LATEST_GIT_TAG: v6.0-dev
LATEST_GIT_TAG: v6.0-beta1
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
# by default we will fetch all submodules
@@ -9,11 +9,6 @@
## Related <!-- Optional -->
<!-- Related Jira issues and Github issues or write "No related issues"-->
## Release notes <!-- Mandatory -->
<!-- Either state release notes or write "No release notes" -->
<!-- ## Breaking change notes --><!-- Optional -->
<!-- ## Dynamic Pipeline Configuration
```yaml
Test Case Filters:
@@ -39,27 +39,5 @@ _For other small/non-public changes, which are not expected to be in the release
* Mention submodule MR, if there is
* Mention backport(ed) MR, if there is
_Don't touch the subsection titles below, they will be parsed by scripts._
## Release notes <!-- Mandatory -->
_Changes made in this MR that should go into the **Release Notes** should be listed here. Please use **past tense** and *specify the area (see maintainers page of IDF internal wiki)*. If there is a subscope, include it and separate with slash (`/`). Minor changes can go to the descriptions above without a release notes entry._
_Write all the changes in a **list** (Start at the beginning of the line with `-` or `*`). If multiple changes are made, each of them should take a single line. If there is only one change to list, it should still be the only line of a list. If this MR does not need any release notes, write "No release notes" here without the `-` or `*`. e.g._
* [WiFi] Changed/fixed/updated xxx
* [WiFi] Added support of xxx
* [Peripheral Drivers/I2S] Fixed xxx (https://github.com/espressif/esp-idf/issues/xxxx)
## Breaking change notes
_Remove this subsection if not used._
_If there are any breaking changes, please mention it here. Talking about (1) what is not accepted any more, (2) the alternative solution and (3) the benefits/reason. e.g._
_Please strictly follow the breaking change restriction, which means, if there is a breaking change but you are merging to non-major versions, you have to separate the breaking part out to another MR for a major version. The breaking change subsection is only accepted in MRs merging to major versions._
* [VFS/UART] Now vfs_uart_set_rts_cts accept one more instance argument, to support configuration to different ports.
<!-- Don't remove the next line - assigns the MR author as the assignee -->
/assign me
+2 -1
View File
@@ -56,7 +56,8 @@
[submodule "components/mqtt/esp-mqtt"]
path = components/mqtt/esp-mqtt
url = ../../espressif/esp-mqtt.git
# url = ../../espressif/esp-mqtt.git
url = ../../0xFEEDC0DE64/esp-mqtt.git
[submodule "components/protobuf-c/protobuf-c"]
path = components/protobuf-c/protobuf-c
+7 -4
View File
@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.22)
project(esp-idf C CXX ASM)
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Current directory '${CMAKE_CURRENT_LIST_DIR}' is not buildable. "
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try "
"again.")
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try again.")
endif()
project(esp-idf C CXX ASM)
# Variables compile_options, c_compile_options, cxx_compile_options, compile_definitions, link_options shall
# not be unset as they may already contain flags, set by toolchain-TARGET.cmake files.
@@ -333,7 +333,10 @@ endforeach()
# Only run validation for the main project, not subprojects like bootloader
idf_build_get_property(bootloader_build BOOTLOADER_BUILD)
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
if(NOT bootloader_build AND NOT esp_tee_build)
if((NOT DEFINED ENV{ESP_IDF_DISABLE_COMPONENT_VALIDATION}
OR "$ENV{ESP_IDF_DISABLE_COMPONENT_VALIDATION}" STREQUAL ""
OR "$ENV{ESP_IDF_DISABLE_COMPONENT_VALIDATION}" STREQUAL "0")
AND NOT bootloader_build AND NOT esp_tee_build)
include("${CMAKE_CURRENT_LIST_DIR}/tools/cmake/component_validation.cmake")
__component_validation_run_checks()
endif()
+22 -23
View File
@@ -4,10 +4,26 @@ if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs
"app_trace.c"
"app_trace_util.c"
"host_file_io.c")
if(CONFIG_APPTRACE_ENABLE)
set(srcs
"app_trace.c"
"app_trace_util.c"
"host_file_io.c"
)
if(NOT CONFIG_APPTRACE_DEST_UART) # JTAG or ALL
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND srcs "port/xtensa/port_jtag.c")
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
list(APPEND srcs "port/riscv/port_jtag.c")
endif()
list(APPEND srcs "app_trace_membufs_proto.c")
endif()
if(NOT CONFIG_APPTRACE_DEST_JTAG) # UART or ALL
list(APPEND srcs "port/port_uart.c")
endif()
endif()
if(CONFIG_ESP_DEBUG_STUBS_ENABLE)
list(APPEND srcs "debug_stubs.c")
@@ -17,23 +33,6 @@ set(include_dirs "include")
set(priv_include_dirs "private_include" "port/include")
if(CONFIG_APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE)
list(APPEND srcs "app_trace_membufs_proto.c")
endif()
if(CONFIG_APPTRACE_DEST_JTAG)
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND srcs "port/xtensa/port_jtag.c")
endif()
if(CONFIG_IDF_TARGET_ARCH_RISCV)
list(APPEND srcs "port/riscv/port_jtag.c")
endif()
endif()
if(CONFIG_APPTRACE_DEST_UART)
list(APPEND srcs "port/port_uart.c")
endif()
if(CONFIG_APPTRACE_SV_ENABLE)
list(APPEND include_dirs
sys_view/Config
@@ -59,6 +58,6 @@ endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
PRIV_REQUIRES esp_driver_gptimer esp_driver_gpio esp_driver_uart
REQUIRES esp_timer
PRIV_REQUIRES esp_driver_gptimer
REQUIRES esp_timer esp_driver_uart
LDFRAGMENTS linker.lf)
+40 -64
View File
@@ -1,36 +1,50 @@
menu "Application Level Tracing"
choice APPTRACE_DESTINATION1
prompt "Data Destination 1"
default APPTRACE_DEST_NONE
config APPTRACE_ENABLE
bool "Enable Application Level Tracing"
default n
help
Select destination for application trace: JTAG or none (to disable).
Enables/disable application tracing module.
This must be enabled to use any tracing library.
choice APPTRACE_DESTINATION
prompt "Data Destination"
default APPTRACE_DEST_JTAG if !PM_ENABLE
default APPTRACE_DEST_UART if PM_ENABLE
depends on APPTRACE_ENABLE
help
Select destination for application trace: JTAG or UART.
When SystemView is enabled, this also controls the SystemView destination.
config APPTRACE_DEST_JTAG
bool "JTAG"
select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA
select APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
select APPTRACE_ENABLE
config APPTRACE_DEST_NONE
bool "None"
endchoice
choice APPTRACE_DESTINATION2
prompt "Data Destination 2"
default APPTRACE_DEST_UART_NONE
help
Select destination for application trace: UART or none (to disable).
depends on !PM_ENABLE
config APPTRACE_DEST_UART
bool "UART"
select APPTRACE_ENABLE
config APPTRACE_DEST_UART_NONE
bool "None"
config APPTRACE_DEST_NONE
bool "None (runtime selection)"
help
Compile both JTAG and UART interfaces. Increases IRAM usage.
Allows runtime selection via esp_apptrace_get_user_params().
With this option, destination and configuration must be provided
at runtime. Default JTAG and UART settings are defined in
components/app_trace/include/esp_app_trace_config.h.
Override these by implementing esp_apptrace_get_user_params()
in your application.
endchoice
config APPTRACE_BUF_SIZE
int "Size of the apptrace buffer"
depends on APPTRACE_DEST_JTAG && !APPTRACE_TRAX_ENABLE
default 16384
help
Size of the memory buffer for trace data in bytes.
config APPTRACE_DEST_UART_NUM
int "UART port number"
depends on APPTRACE_DEST_UART
@@ -107,6 +121,7 @@ menu "Application Level Tracing"
config APPTRACE_UART_TASK_PRIO
int
prompt "UART Task Priority" if APPTRACE_DEST_UART
depends on APPTRACE_DEST_UART
default 1
range 1 32
help
@@ -126,23 +141,13 @@ menu "Application Level Tracing"
help
Enables/disable TRAX tracing HW.
config APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
bool
default n
help
Enables/disable swapping memory buffers tracing protocol.
config APPTRACE_ENABLE
bool
default n
help
Enables/disable application tracing module.
config APPTRACE_LOCK_ENABLE
bool
default !APPTRACE_SV_ENABLE
bool "Internal Sync Lock Enable"
depends on APPTRACE_ENABLE
default n
help
Enables/disable application tracing module internal sync lock.
Keep in mind this will slow down the trace data transfer to the host.
config APPTRACE_ONPANIC_HOST_FLUSH_TMO
int "Timeout for flushing last trace data to host on panic"
@@ -162,13 +167,6 @@ menu "Application Level Tracing"
Threshold for flushing last trace data to host on panic in post-mortem mode.
This is minimal amount of data needed to perform flush. In bytes.
config APPTRACE_BUF_SIZE
int "Size of the apptrace buffer"
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE && !APPTRACE_TRAX_ENABLE
default 16384
help
Size of the memory buffer for trace data in bytes.
menu "FreeRTOS SystemView Tracing"
depends on APPTRACE_ENABLE
config APPTRACE_SV_ENABLE
@@ -178,30 +176,9 @@ menu "Application Level Tracing"
help
Enables support for SEGGER SystemView tracing functionality.
choice APPTRACE_SV_DEST
prompt "SystemView destination"
depends on APPTRACE_SV_ENABLE
default APPTRACE_SV_DEST_JTAG
help
SystemView will transfer data through the defined interface.
config APPTRACE_SV_DEST_JTAG
bool "Data destination JTAG"
depends on !PM_ENABLE && !APPTRACE_DEST_NONE
help
Send SEGGER SystemView events through JTAG interface.
config APPTRACE_SV_DEST_UART
bool "Data destination UART"
depends on APPTRACE_DEST_UART
help
Send SEGGER SystemView events through UART interface.
endchoice
choice APPTRACE_SV_CPU
prompt "CPU to trace"
depends on APPTRACE_SV_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE
depends on APPTRACE_SV_ENABLE && APPTRACE_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE
default APPTRACE_SV_DEST_CPU_0
help
Define the CPU to trace by SystemView.
@@ -218,7 +195,6 @@ menu "Application Level Tracing"
endchoice
choice APPTRACE_SV_TS_SOURCE
prompt "Timer to use as timestamp source"
depends on APPTRACE_SV_ENABLE
+153 -207
View File
@@ -7,8 +7,10 @@
#include <string.h>
#include "esp_cpu.h"
#include "esp_log.h"
#include "esp_rom_sys.h"
#include "esp_app_trace.h"
#include "esp_app_trace_port.h"
#include "esp_app_trace_types.h"
#include "esp_private/startup_internal.h"
#if CONFIG_ESP_CONSOLE_UART && CONFIG_APPTRACE_DEST_UART && (CONFIG_APPTRACE_DEST_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM)
@@ -24,257 +26,205 @@ const static char *TAG = "esp_apptrace";
typedef struct {
esp_apptrace_hw_t *hw;
void *hw_data;
esp_apptrace_dest_t dest;
} esp_apptrace_channel_t;
static esp_apptrace_channel_t s_trace_channels[ESP_APPTRACE_DEST_MAX];
static bool s_inited;
static esp_apptrace_channel_t s_trace_ch;
static volatile int s_trace_ch_hw_initialized = 0;
esp_err_t esp_apptrace_init(void)
static esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config)
{
__attribute__((unused)) void *hw_data = NULL;
// 'esp_apptrace_init()' is called on every core, so ensure to do main initialization only once
if (esp_cpu_get_core_id() == 0) {
memset(&s_trace_channels, 0, sizeof(s_trace_channels));
#if CONFIG_APPTRACE_DEST_JTAG
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = esp_apptrace_jtag_hw_get(&hw_data);
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
s_trace_ch.hw = esp_apptrace_jtag_hw_get(&hw_data);
s_trace_ch.hw_data = hw_data;
#elif CONFIG_APPTRACE_DEST_UART
const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart;
s_trace_ch.hw = esp_apptrace_uart_hw_get(uart_config->uart_num, &hw_data);
s_trace_ch.hw_data = hw_data;
#else // CONFIG_APPTRACE_DEST_NONE allows runtime selection
if (config->dest == ESP_APPTRACE_DEST_JTAG) {
s_trace_ch.hw = esp_apptrace_jtag_hw_get(&hw_data);
s_trace_ch.hw_data = hw_data;
} else if (config->dest == ESP_APPTRACE_DEST_UART) {
const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart;
s_trace_ch.hw = esp_apptrace_uart_hw_get(uart_config->uart_num, &hw_data);
s_trace_ch.hw_data = hw_data;
} else {
s_trace_ch.hw = NULL;
s_trace_ch.hw_data = NULL;
ESP_APPTRACE_LOGE("Invalid destination type (%d)!", config->dest);
return ESP_ERR_INVALID_ARG;
}
#endif
#if CONFIG_APPTRACE_DEST_UART
s_trace_channels[ESP_APPTRACE_DEST_UART].hw = esp_apptrace_uart_hw_get(CONFIG_APPTRACE_DEST_UART_NUM, &hw_data);
s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
#endif
s_inited = true;
s_trace_ch.dest = config->dest;
s_trace_ch_hw_initialized = 1;
} else {
// There is NO guarantee that system init functions will execute on core 0 first
// So we need to wait for core 0 to set up the hardware interface
while (!s_trace_ch_hw_initialized) {
esp_rom_delay_us(10);
}
}
// esp_apptrace_init() is called on every core, so initialize trace channel on every core
for (int i = 0; i < sizeof(s_trace_channels) / sizeof(s_trace_channels[0]); i++) {
esp_apptrace_channel_t *ch = &s_trace_channels[i];
if (ch->hw) {
int res = ch->hw->init(ch->hw_data);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
return res;
}
if (s_trace_ch.hw) {
int res = s_trace_ch.hw->init(s_trace_ch.hw_data, config);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
return res;
}
}
return ESP_OK;
}
ESP_SYSTEM_INIT_FN(esp_apptrace_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115)
esp_err_t esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size)
{
return esp_apptrace_init();
}
esp_err_t esp_apptrace_down_buffer_config(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t size)
{
esp_apptrace_channel_t *ch;
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!buf || size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (buf == NULL || size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_FAIL;
}
if (ch->hw->down_buffer_config != NULL) {
ch->hw->down_buffer_config(ch->hw_data, buf, size);
if (s_trace_ch.hw->down_buffer_config) {
s_trace_ch.hw->down_buffer_config(s_trace_ch.hw_data, buf, size);
}
return ESP_OK;
}
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t user_tmo)
uint8_t *esp_apptrace_down_buffer_get(uint32_t *size, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!size || *size == 0) {
return NULL;
}
if (size == NULL || *size == 0) {
if (!s_trace_ch.hw) {
return NULL;
}
if (!s_inited) {
return NULL;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return NULL;
}
if (ch->hw->get_down_buffer == NULL) {
if (!s_trace_ch.hw->get_down_buffer) {
return NULL;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
return ch->hw->get_down_buffer(ch->hw_data, size, &tmo);
return s_trace_ch.hw->get_down_buffer(s_trace_ch.hw_data, size, &tmo);
}
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
esp_err_t esp_apptrace_down_buffer_put(uint8_t *ptr, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!ptr) {
return ESP_ERR_INVALID_ARG;
}
if (ptr == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_ERR_NOT_SUPPORTED;
}
if (ch->hw->get_down_buffer == NULL) {
if (!s_trace_ch.hw->get_down_buffer) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
return ch->hw->put_down_buffer(ch->hw_data, ptr, &tmo);
return s_trace_ch.hw->put_down_buffer(s_trace_ch.hw_data, ptr, &tmo);
}
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size, uint32_t user_tmo)
esp_err_t esp_apptrace_read(void *buf, uint32_t *size, uint32_t user_tmo)
{
int res = ESP_OK;
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!buf || !size || *size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (buf == NULL || size == NULL || *size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_ERR_NOT_SUPPORTED;
}
if (ch->hw->get_down_buffer == NULL || ch->hw->put_down_buffer == NULL) {
if (!s_trace_ch.hw->get_down_buffer || !s_trace_ch.hw->put_down_buffer) {
return ESP_ERR_NOT_SUPPORTED;
}
//TODO: callback system
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
uint32_t act_sz = *size;
*size = 0;
uint8_t *ptr = ch->hw->get_down_buffer(ch->hw_data, &act_sz, &tmo);
uint8_t *ptr = s_trace_ch.hw->get_down_buffer(s_trace_ch.hw_data, &act_sz, &tmo);
if (ptr && act_sz > 0) {
ESP_APPTRACE_LOGD("Read %" PRIu32 " bytes from host", act_sz);
memcpy(buf, ptr, act_sz);
res = ch->hw->put_down_buffer(ch->hw_data, ptr, &tmo);
*size = act_sz;
} else {
res = ESP_ERR_TIMEOUT;
return s_trace_ch.hw->put_down_buffer(s_trace_ch.hw_data, ptr, &tmo);
}
return res;
return ESP_ERR_TIMEOUT;
}
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t user_tmo)
uint8_t *esp_apptrace_buffer_get(uint32_t size, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
return NULL;
}
if (size == 0) {
return NULL;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return NULL;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return NULL;
}
if (ch->hw->get_up_buffer == NULL) {
if (!s_trace_ch.hw->get_up_buffer) {
return NULL;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
return ch->hw->get_up_buffer(ch->hw_data, size, &tmo);
return s_trace_ch.hw->get_up_buffer(s_trace_ch.hw_data, size, &tmo);
}
esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
esp_err_t esp_apptrace_buffer_put(uint8_t *ptr, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!ptr) {
return ESP_ERR_INVALID_ARG;
}
if (ptr == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_ERR_NOT_SUPPORTED;
}
if (ch->hw->put_up_buffer == NULL) {
if (!s_trace_ch.hw->put_up_buffer) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
return ch->hw->put_up_buffer(ch->hw_data, ptr, &tmo);
return s_trace_ch.hw->put_up_buffer(s_trace_ch.hw_data, ptr, &tmo);
}
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t user_tmo)
esp_err_t esp_apptrace_write(const void *data, uint32_t size, uint32_t user_tmo)
{
uint8_t *ptr = NULL;
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!data || size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (data == NULL || size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_ERR_NOT_SUPPORTED;
}
if (ch->hw->get_up_buffer == NULL || ch->hw->put_up_buffer == NULL) {
if (!s_trace_ch.hw->get_up_buffer || !s_trace_ch.hw->put_up_buffer) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
ptr = ch->hw->get_up_buffer(ch->hw_data, size, &tmo);
if (ptr == NULL) {
uint8_t *ptr = s_trace_ch.hw->get_up_buffer(s_trace_ch.hw_data, size, &tmo);
if (!ptr) {
return ESP_ERR_NO_MEM;
}
@@ -283,36 +233,29 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_
memcpy(ptr, data, size);
// now indicate that this buffer is ready to be sent off to host
return ch->hw->put_up_buffer(ch->hw_data, ptr, &tmo);
return s_trace_ch.hw->put_up_buffer(s_trace_ch.hw_data, ptr, &tmo);
}
int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const char *fmt, va_list ap)
int esp_apptrace_vprintf_to(uint32_t user_tmo, const char *fmt, va_list ap)
{
uint16_t nargs = 0;
uint8_t *pout, *p = (uint8_t *)fmt;
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!fmt) {
return -1;
}
if (fmt == NULL) {
if (!s_trace_ch.hw) {
return -1;
}
if (!s_inited) {
return -1;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return -1;
}
if (ch->hw->get_up_buffer == NULL || ch->hw->put_up_buffer == NULL) {
if (!s_trace_ch.hw->get_up_buffer || !s_trace_ch.hw->put_up_buffer) {
return -1;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, user_tmo);
ESP_APPTRACE_LOGD("fmt %p", fmt);
while ((p = (uint8_t *)strchr((char *)p, '%')) && nargs < ESP_APPTRACE_MAX_VPRINTF_ARGS) {
p++;
@@ -325,8 +268,8 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
ESP_APPTRACE_LOGE("Failed to store all printf args!");
}
pout = ch->hw->get_up_buffer(ch->hw_data, 1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
if (pout == NULL) {
pout = s_trace_ch.hw->get_up_buffer(s_trace_ch.hw_data, 1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
if (!pout) {
ESP_APPTRACE_LOGE("Failed to get buffer!");
return -1;
}
@@ -342,7 +285,7 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
ESP_APPTRACE_LOGD("arg %" PRIx32, arg);
}
int ret = ch->hw->put_up_buffer(ch->hw_data, p, &tmo);
int ret = s_trace_ch.hw->put_up_buffer(s_trace_ch.hw_data, p, &tmo);
if (ret != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to put printf buf (%d)!", ret);
return -1;
@@ -353,78 +296,81 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
int esp_apptrace_vprintf(const char *fmt, va_list ap)
{
return esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_JTAG, 0, fmt, ap);
return esp_apptrace_vprintf_to(0, fmt, ap);
}
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t usr_tmo)
esp_err_t esp_apptrace_flush_nolock(uint32_t min_sz, uint32_t usr_tmo)
{
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_ERR_NOT_SUPPORTED;
}
if (ch->hw->flush_up_buffer_nolock == NULL) {
if (!s_trace_ch.hw->flush_up_buffer_nolock) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, usr_tmo);
return ch->hw->flush_up_buffer_nolock(ch->hw_data, min_sz, &tmo);
return s_trace_ch.hw->flush_up_buffer_nolock(s_trace_ch.hw_data, min_sz, &tmo);
}
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t usr_tmo)
esp_err_t esp_apptrace_flush(uint32_t usr_tmo)
{
esp_apptrace_tmo_t tmo;
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_ERR_NOT_SUPPORTED;
}
if (ch->hw->flush_up_buffer == NULL) {
if (!s_trace_ch.hw->flush_up_buffer) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, usr_tmo);
return ch->hw->flush_up_buffer(ch->hw_data, &tmo);
return s_trace_ch.hw->flush_up_buffer(s_trace_ch.hw_data, &tmo);
}
bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
bool esp_apptrace_host_is_connected(void)
{
esp_apptrace_channel_t *ch;
ESP_APPTRACE_LOGV("%s(): enter", __func__);
if (dest >= ESP_APPTRACE_DEST_MAX) {
if (!s_trace_ch.hw) {
return false;
}
if (!s_inited) {
return false;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return false;
}
if (ch->hw->host_is_connected == NULL) {
if (!s_trace_ch.hw->host_is_connected) {
return false;
}
return ch->hw->host_is_connected(ch->hw_data);
return s_trace_ch.hw->host_is_connected(s_trace_ch.hw_data);
}
esp_apptrace_dest_t esp_apptrace_get_destination(void)
{
return s_trace_ch.dest;
}
esp_err_t esp_apptrace_set_header_size(esp_apptrace_header_size_t header_size)
{
if (!s_trace_ch.hw) {
return ESP_ERR_INVALID_STATE;
}
if (s_trace_ch.hw->set_header_size) {
s_trace_ch.hw->set_header_size(s_trace_ch.hw_data, header_size);
}
return ESP_OK;
}
esp_apptrace_config_t __attribute__((weak)) esp_apptrace_get_user_params(void)
{
esp_apptrace_config_t default_config = APPTRACE_CONFIG_DEFAULT();
return default_config;
}
ESP_SYSTEM_INIT_FN(apptrace_early_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115)
{
esp_apptrace_config_t config = esp_apptrace_get_user_params();
return esp_apptrace_init(&config);
}
+58 -49
View File
@@ -18,13 +18,16 @@
* In this case host SW will see that wr_sz < block_sz and will report error.
*/
typedef struct {
#if CONFIG_APPTRACE_SV_ENABLE
uint8_t block_sz; // size of allocated block for user data
uint8_t wr_sz; // size of actually written data
#else
uint16_t block_sz; // size of allocated block for user data
uint16_t wr_sz; // size of actually written data
#endif
union {
struct {
uint8_t block_sz_8;
uint8_t wr_sz_8;
};
struct {
uint16_t block_sz_16;
uint16_t wr_sz_16;
};
};
} esp_tracedata_hdr_t;
/** TODO: docs
@@ -33,31 +36,24 @@ typedef struct {
uint16_t block_sz; // size of allocated block for user data
} esp_hostdata_hdr_t;
#if CONFIG_APPTRACE_SV_ENABLE
#define ESP_APPTRACE_USR_BLOCK_CORE(_cid_) (0)
#define ESP_APPTRACE_USR_BLOCK_LEN(_v_) (_v_)
#define ESP_APPTRACE_USR_DATA_LEN_MAX(_hw_data_) 255UL
#else
#define ESP_APPTRACE_USR_BLOCK_CORE(_cid_) ((_cid_) << 15)
#define ESP_APPTRACE_USR_BLOCK_LEN(_v_) (~(1 << 15) & (_v_))
#define ESP_APPTRACE_USR_DATA_LEN_MAX(_hw_data_) (ESP_APPTRACE_INBLOCK(_hw_data_)->sz - sizeof(esp_tracedata_hdr_t))
#endif
#define ESP_APPTRACE_USR_BLOCK_RAW_SZ(_s_) ((_s_) + sizeof(esp_tracedata_hdr_t))
#define ESP_APPTRACE_INBLOCK_MARKER(_hw_data_) \
((_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2])
#define ESP_APPTRACE_INBLOCK_MARKER(_hw_data_) ((_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2])
#define ESP_APPTRACE_INBLOCK_MARKER_UPD(_hw_data_, _v_) do {(_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2] += (_v_);}while(0)
#define ESP_APPTRACE_INBLOCK(_hw_data_) (&(_hw_data_)->blocks[(_hw_data_)->state.in_block % 2])
#define ESP_APPTRACE_INBLOCK(_hw_data_) \
(&(_hw_data_)->blocks[(_hw_data_)->state.in_block % 2])
const static char *TAG = "esp_apptrace";
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size);
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto,
uint8_t *data, uint32_t size);
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, const esp_apptrace_mem_block_t blocks_cfg[2])
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto,
const esp_apptrace_mem_block_t blocks_cfg[2])
{
// disabled by default
esp_apptrace_rb_init(&proto->rb_down, NULL, 0);
// membufs proto init
for (unsigned i = 0; i < 2; i++) {
for (unsigned int i = 0; i < 2; i++) {
proto->blocks[i].start = blocks_cfg[i].start;
proto->blocks[i].sz = blocks_cfg[i].sz;
proto->state.markers[i] = 0;
@@ -104,7 +100,8 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
*(p - 8), *(p - 7), *(p - 6), *(p - 5), *(p - 4), *(p - 3), *(p - 2), *(p - 1));
uint32_t sz = esp_apptrace_membufs_down_buffer_write_nolock(proto, (uint8_t *)(hdr + 1), hdr->block_sz);
if (sz != hdr->block_sz) {
ESP_APPTRACE_LOGE("Failed to write %" PRIu32 " bytes to down buffer (%" PRIu16 " %" PRIu32 ")!", hdr->block_sz - sz, hdr->block_sz, sz);
ESP_APPTRACE_LOGE("Failed to write %" PRIu32 " bytes to down buffer (%" PRIu16 " %" PRIu32 ")!",
hdr->block_sz - sz, hdr->block_sz, sz);
}
hdr->block_sz = 0;
}
@@ -137,7 +134,8 @@ static esp_err_t esp_apptrace_membufs_swap_waitus(esp_apptrace_membufs_proto_dat
return res;
}
uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t *size, esp_apptrace_tmo_t *tmo)
uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t *proto,
uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr = NULL;
@@ -170,13 +168,15 @@ uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t
return ptr;
}
esp_err_t esp_apptrace_membufs_down_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
esp_err_t esp_apptrace_membufs_down_buffer_put(esp_apptrace_membufs_proto_data_t *proto,
uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
/* nothing todo */
return ESP_OK;
}
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size)
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto,
uint8_t *data, uint32_t size)
{
uint32_t total_sz = 0;
@@ -204,29 +204,21 @@ static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membu
return total_sz;
}
static inline uint8_t *esp_apptrace_membufs_pkt_start(uint8_t *ptr, uint16_t size)
static inline uint32_t esp_apptrace_membufs_usr_data_len_max(esp_apptrace_membufs_proto_data_t *proto)
{
// it is safe to use esp_cpu_get_core_id() in macro call because arg is used only once inside it
((esp_tracedata_hdr_t *)ptr)->block_sz = ESP_APPTRACE_USR_BLOCK_CORE(esp_cpu_get_core_id()) | size;
((esp_tracedata_hdr_t *)ptr)->wr_sz = 0;
return ptr + sizeof(esp_tracedata_hdr_t);
return proto->header_size == ESP_APPTRACE_HEADER_SIZE_32 ?
ESP_APPTRACE_INBLOCK(proto)->sz - ESP_APPTRACE_HEADER_SIZE_32 : 255;
}
static inline void esp_apptrace_membufs_pkt_end(uint8_t *ptr)
uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto,
uint32_t size, esp_apptrace_tmo_t *tmo)
{
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - sizeof(esp_tracedata_hdr_t));
// update written size
hdr->wr_sz = hdr->block_sz;
}
uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t size, esp_apptrace_tmo_t *tmo)
{
if (size > ESP_APPTRACE_USR_DATA_LEN_MAX(proto)) {
if (size > esp_apptrace_membufs_usr_data_len_max(proto)) {
ESP_APPTRACE_LOGE("Too large user data size %" PRIu32 "!", size);
return NULL;
}
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) {
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + size + proto->header_size > ESP_APPTRACE_INBLOCK(proto)->sz) {
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
if (res != ESP_OK) {
return NULL;
@@ -235,16 +227,32 @@ uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *p
uint8_t *buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
// update cur block marker
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size);
proto->state.markers[proto->state.in_block % 2] += size + proto->header_size;
// update header
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)buf_ptr;
if (proto->header_size == ESP_APPTRACE_HEADER_SIZE_32) {
hdr->block_sz_16 = (esp_cpu_get_core_id() << 15) | size;
hdr->wr_sz_16 = 0;
} else {
hdr->block_sz_8 = size;
hdr->wr_sz_8 = 0;
}
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
return buf_ptr;
return buf_ptr + proto->header_size;
}
esp_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
esp_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *proto,
uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
esp_apptrace_membufs_pkt_end(ptr);
// update header
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - proto->header_size);
if (proto->header_size == ESP_APPTRACE_HEADER_SIZE_32) {
hdr->wr_sz_16 = hdr->block_sz_16;
} else {
hdr->wr_sz_8 = hdr->block_sz_8;
}
// TODO: mark block as busy in order not to reuse it for other tracing calls until it is completely written
// TODO: avoid potential situation when all memory is consumed by low prio tasks which can not complete writing due to
// higher prio tasks and the latter can not allocate buffers at all
@@ -253,7 +261,8 @@ esp_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *
return ESP_OK;
}
esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *proto, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *proto,
uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
int res = ESP_OK;
@@ -267,7 +276,7 @@ esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *p
res = esp_apptrace_membufs_swap_waitus(proto, tmo);
if (res != ESP_OK) {
if (res == ESP_ERR_TIMEOUT) {
ESP_APPTRACE_LOGW("Failed to switch to another block in %" PRIi32 " us!", (int32_t)tmo->elapsed);
ESP_APPTRACE_LOGW("Failed to switch to another block in %" PRId32 " us!", (int32_t)tmo->elapsed);
} else {
ESP_APPTRACE_LOGE("Failed to switch to another block, res: %d", res);
}
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -57,6 +57,12 @@ esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
///////////////////////////////// LOCK ////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
{
portMUX_INITIALIZE(&lock->mux);
lock->int_state = 0;
}
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo)
{
esp_err_t ret;
+1 -1
View File
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "esp_heap_trace.h"
#include "esp_heap_caps.h"
#if CONFIG_APPTRACE_SV_ENABLE
+30 -34
View File
@@ -17,8 +17,6 @@
#include <string.h>
#include "esp_app_trace.h"
#if CONFIG_APPTRACE_ENABLE
#include "esp_log.h"
const static char *TAG = "esp_host_file_io";
@@ -79,13 +77,13 @@ typedef struct {
void *file;
} esp_apptrace_ftell_args_t;
static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
static esp_err_t esp_apptrace_file_cmd_send(uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
{
esp_err_t ret;
esp_apptrace_fcmd_hdr_t *hdr;
ESP_EARLY_LOGV(TAG, "%s %d", __func__, cmd);
uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
uint8_t *ptr = esp_apptrace_buffer_get(sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
if (ptr == NULL) {
return ESP_ERR_NO_MEM;
}
@@ -97,13 +95,13 @@ static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cm
}
// now indicate that this buffer is ready to be sent off to host
ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
ret = esp_apptrace_buffer_put(ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret);
return ret;
}
ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
ret = esp_apptrace_flush(ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret);
return ret;
@@ -112,12 +110,12 @@ static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cm
return ESP_OK;
}
static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t buf_len)
static esp_err_t esp_apptrace_file_rsp_recv(uint8_t *buf, uint32_t buf_len)
{
uint32_t tot_rd = 0;
while (tot_rd < buf_len) {
uint32_t rd_size = buf_len - tot_rd;
esp_err_t ret = esp_apptrace_read(dest, buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
esp_err_t ret = esp_apptrace_read(buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read (%d)!", ret);
return ret;
@@ -137,7 +135,7 @@ static void esp_apptrace_fopen_args_prepare(uint8_t *buf, void *priv)
memcpy(buf + args->path_len, args->mode, args->mode_len);
}
void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
void *esp_apptrace_fopen(const char *path, const char *mode)
{
esp_apptrace_fopen_args_t cmd_args;
@@ -151,7 +149,7 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char
cmd_args.mode = mode;
cmd_args.mode_len = strlen(mode) + 1;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
&cmd_args, cmd_args.path_len + cmd_args.mode_len);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -160,7 +158,7 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char
// now read the answer
void *resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return NULL;
@@ -176,12 +174,12 @@ static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
memcpy(buf, &args->file, sizeof(args->file));
}
int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
int esp_apptrace_fclose(void *stream)
{
esp_apptrace_fclose_args_t cmd_args;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -190,7 +188,7 @@ int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
// now read the answer
int resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return EOF;
@@ -207,7 +205,7 @@ static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
memcpy(buf + sizeof(args->file), args->buf, args->size);
}
size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
size_t esp_apptrace_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream)
{
esp_apptrace_fwrite_args_t cmd_args;
@@ -220,7 +218,7 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
cmd_args.buf = (void *)ptr;
cmd_args.size = size * nmemb;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
&cmd_args, sizeof(cmd_args.file) + cmd_args.size);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -229,7 +227,7 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
// now read the answer
size_t resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return 0;
@@ -249,7 +247,7 @@ static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
}
size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream)
{
esp_apptrace_fread_args_t cmd_args;
@@ -261,7 +259,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
cmd_args.size = size * nmemb;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -270,7 +268,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
// now read the answer
size_t resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return 0;
@@ -279,7 +277,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
return 0;
}
ret = esp_apptrace_file_rsp_recv(dest, ptr, resp);
ret = esp_apptrace_file_rsp_recv(ptr, resp);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read file data (%d)!", ret);
return 0;
@@ -300,7 +298,7 @@ static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
memcpy(buf + sizeof(args->file) + sizeof(args->offset), &args->whence, sizeof(args->whence));
}
int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
int esp_apptrace_fseek(void *stream, long offset, int whence)
{
esp_apptrace_fseek_args_t cmd_args;
@@ -309,7 +307,7 @@ int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int
cmd_args.file = stream;
cmd_args.offset = offset;
cmd_args.whence = whence;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -318,7 +316,7 @@ int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int
// now read the answer
int resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return -1;
@@ -334,12 +332,12 @@ static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
memcpy(buf, &args->file, sizeof(args->file));
}
int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
int esp_apptrace_ftell(void *stream)
{
esp_apptrace_ftell_args_t cmd_args;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -348,7 +346,7 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
// now read the answer
int resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return -1;
@@ -357,10 +355,10 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
return resp;
}
int esp_apptrace_fstop(esp_apptrace_dest_t dest)
int esp_apptrace_fstop(void)
{
ESP_EARLY_LOGV(TAG, "%s", __func__);
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
}
@@ -374,12 +372,12 @@ static void esp_apptrace_feof_args_prepare(uint8_t *buf, void *priv)
memcpy(buf, &args->file, sizeof(args->file));
}
int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream)
int esp_apptrace_feof(void *stream)
{
esp_apptrace_feof_args_t cmd_args;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FEOF, esp_apptrace_feof_args_prepare,
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FEOF, esp_apptrace_feof_args_prepare,
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
@@ -388,7 +386,7 @@ int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream)
// now read the answer
int resp;
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
return EOF;
@@ -396,5 +394,3 @@ int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream)
return resp;
}
#endif
+78 -53
View File
@@ -8,6 +8,7 @@
#include <stdarg.h>
#include "esp_err.h"
#include "esp_app_trace_config.h"
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
#ifdef __cplusplus
@@ -15,83 +16,73 @@ extern "C" {
#endif
/**
* Application trace data destinations bits.
*/
typedef enum {
ESP_APPTRACE_DEST_JTAG, ///< JTAG destination
ESP_APPTRACE_DEST_UART, ///< UART destination
ESP_APPTRACE_DEST_MAX,
} esp_apptrace_dest_t;
/**
* @brief Initializes application tracing module.
* @brief Get custom trace initialization parameters (optional callback)
*
* @note Should be called before any esp_apptrace_xxx call.
* This is an optional callback function that user applications can implement to provide
* custom trace configuration. A weak default implementation exists in the app_trace component
* that returns menuconfig defaults (APPTRACE_CONFIG_DEFAULT()). User applications can override
* this by providing their own implementation.
*
* This function is called during early system initialization (before app_main) on all cores.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_init(void);
esp_apptrace_config_t esp_apptrace_get_user_params(void);
/**
* @brief Configures down buffer.
* @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and esp_apptrace_read.
* This function does not protect internal data by lock.
*
* @param dest Indicates HW interface to configure.
* @param buf Address of buffer to use for down channel (host to target) data.
* @param size Size of the buffer.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_down_buffer_config(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t size);
esp_err_t esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
/**
* @brief Allocates buffer for trace data.
* Once the data in the buffer is ready to be sent, esp_apptrace_buffer_put must be called to indicate it.
*
* @param dest Indicates HW interface to send data.
* @param size Size of data to write to trace buffer.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return non-NULL on success, otherwise NULL.
*/
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t tmo);
uint8_t *esp_apptrace_buffer_get(uint32_t size, uint32_t tmo);
/**
* @brief Indicates that the data in the buffer is ready to be sent.
* This function is a counterpart of and must be preceded by esp_apptrace_buffer_get.
*
* @param dest Indicates HW interface to send data. Should be identical to the same parameter in call to esp_apptrace_buffer_get.
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_buffer_get.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo);
esp_err_t esp_apptrace_buffer_put(uint8_t *ptr, uint32_t tmo);
/**
* @brief Writes data to trace buffer.
*
* @param dest Indicates HW interface to send data.
* @param data Address of data to write to trace buffer.
* @param size Size of data to write to trace buffer.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t tmo);
esp_err_t esp_apptrace_write(const void *data, uint32_t size, uint32_t tmo);
/**
* @brief vprintf-like function to send log messages to host via specified HW interface.
*
* @param dest Indicates HW interface to send data.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
* @param fmt Address of format string.
* @param ap List of arguments.
*
* @return Number of bytes written.
*/
int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t tmo, const char *fmt, va_list ap);
int esp_apptrace_vprintf_to(uint32_t tmo, const char *fmt, va_list ap);
/**
* @brief vprintf-like function to send log messages to host.
@@ -106,98 +97,104 @@ int esp_apptrace_vprintf(const char *fmt, va_list ap);
/**
* @brief Flushes remaining data in trace buffer to host.
*
* @param dest Indicates HW interface to flush data on.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo);
esp_err_t esp_apptrace_flush(uint32_t tmo);
/**
* @brief Flushes remaining data in trace buffer to host without locking internal data.
* This is a special version of esp_apptrace_flush which should be called from panic handler.
*
* @param dest Indicates HW interface to flush data on.
* @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t tmo);
esp_err_t esp_apptrace_flush_nolock(uint32_t min_sz, uint32_t tmo);
/**
* @brief Reads host data from trace buffer.
*
* @param dest Indicates HW interface to read the data on.
* @param data Address of buffer to put data from trace buffer.
* @param size Pointer to store size of read data. Before call to this function pointed memory must hold requested size of data
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *data, uint32_t *size, uint32_t tmo);
esp_err_t esp_apptrace_read(void *data, uint32_t *size, uint32_t tmo);
/**
* @brief Retrieves incoming data buffer if any.
* Once data in the buffer is processed, esp_apptrace_down_buffer_put must be called to indicate it.
*
* @param dest Indicates HW interface to receive data.
* @param size Address to store size of available data in down buffer. Must be initialized with requested value.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return non-NULL on success, otherwise NULL.
*/
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t tmo);
uint8_t *esp_apptrace_down_buffer_get(uint32_t *size, uint32_t tmo);
/**
* @brief Indicates that the data in the down buffer is processed.
* This function is a counterpart of and must be preceded by esp_apptrace_down_buffer_get.
*
* @param dest Indicates HW interface to receive data. Should be identical to the same parameter in call to esp_apptrace_down_buffer_get.
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_down_buffer_get.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo);
esp_err_t esp_apptrace_down_buffer_put(uint8_t *ptr, uint32_t tmo);
/**
* @brief Checks whether host is connected.
*
* @param dest Indicates HW interface to use.
*
* @return true if host is connected, otherwise false
*/
bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest);
bool esp_apptrace_host_is_connected(void);
/**
* @brief Gets the destination of the application trace.
*
* @return The destination of the application trace.
*/
esp_apptrace_dest_t esp_apptrace_get_destination(void);
/**
* @brief Sets the header size of the application trace packet.
*
* @param header_size The header size to set.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_set_header_size(esp_apptrace_header_size_t header_size);
/**
* @brief Opens file on host.
* This function has the same semantic as 'fopen' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param path Path to file.
* @param mode Mode string. See fopen for details.
*
* @return non zero file handle on success, otherwise 0
*/
void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode);
void *esp_apptrace_fopen(const char *path, const char *mode);
/**
* @brief Closes file on host.
* This function has the same semantic as 'fclose' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
*
* @return Zero on success, otherwise non-zero. See fclose for details.
*/
int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream);
int esp_apptrace_fclose(void *stream);
/**
* @brief Writes to file on host.
* This function has the same semantic as 'fwrite' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param ptr Address of data to write.
* @param size Size of an item.
* @param nmemb Number of items to write.
@@ -205,13 +202,12 @@ int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream);
*
* @return Number of written items. See fwrite for details.
*/
size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream);
size_t esp_apptrace_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream);
/**
* @brief Read file on host.
* This function has the same semantic as 'fread' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param ptr Address to store read data.
* @param size Size of an item.
* @param nmemb Number of items to read.
@@ -219,53 +215,82 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
*
* @return Number of read items. See fread for details.
*/
size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream);
size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream);
/**
* @brief Set position indicator in file on host.
* This function has the same semantic as 'fseek' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
* @param offset Offset. See fseek for details.
* @param whence Position in file. See fseek for details.
*
* @return Zero on success, otherwise non-zero. See fseek for details.
*/
int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence);
int esp_apptrace_fseek(void *stream, long offset, int whence);
/**
* @brief Get current position indicator for file on host.
* This function has the same semantic as 'ftell' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
*
* @return Current position in file. See ftell for details.
*/
int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream);
int esp_apptrace_ftell(void *stream);
/**
* @brief Indicates to the host that all file operations are complete.
* This function should be called after all file operations are finished and
* indicate to the host that it can perform cleanup operations (close open files etc.).
*
* @param dest Indicates HW interface to use.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
int esp_apptrace_fstop(esp_apptrace_dest_t dest);
int esp_apptrace_fstop(void);
/**
* @brief Test end-of-file indicator on a stream.
* This function has the same semantic as 'feof' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
*
* @return Non-Zero if end-of-file indicator is set for stream. See feof for details.
*/
int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream);
int esp_apptrace_feof(void *stream);
#if !CONFIG_APPTRACE_DEST_UART // JTAG or NONE
#define APPTRACE_JTAG_CONFIG_DEFAULT() { \
.dest = ESP_APPTRACE_DEST_JTAG, \
.dest_cfg.jtag = {0}, \
.panic_flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \
.panic_flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \
}
#endif
#if !CONFIG_APPTRACE_DEST_JTAG // UART or NONE
#define APPTRACE_UART_CONFIG_DEFAULT() { \
.dest = ESP_APPTRACE_DEST_UART, \
.dest_cfg.uart = { \
.uart_num = CONFIG_APPTRACE_DEST_UART_NUM, \
.tx_pin_num = CONFIG_APPTRACE_UART_TX_GPIO, \
.rx_pin_num = CONFIG_APPTRACE_UART_RX_GPIO, \
.baud_rate = CONFIG_APPTRACE_UART_BAUDRATE, \
.rx_buff_size = CONFIG_APPTRACE_UART_RX_BUFF_SIZE, \
.tx_buff_size = CONFIG_APPTRACE_UART_TX_BUFF_SIZE, \
.tx_msg_size = CONFIG_APPTRACE_UART_TX_MSG_SIZE, \
.task_prio = CONFIG_APPTRACE_UART_TASK_PRIO, \
}, \
.panic_flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \
.panic_flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \
}
#endif
// Default picks JTAG if available, otherwise UART
#if !CONFIG_APPTRACE_DEST_UART
#define APPTRACE_CONFIG_DEFAULT() APPTRACE_JTAG_CONFIG_DEFAULT()
#else
#define APPTRACE_CONFIG_DEFAULT() APPTRACE_UART_CONFIG_DEFAULT()
#endif
#ifdef __cplusplus
}
@@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_APP_TRACE_CONFIG_H_
#define ESP_APP_TRACE_CONFIG_H_
#include "sdkconfig.h"
/* Default configurations for runtime selection (CONFIG_APPTRACE_DEST_NONE)
* These values are used when CONFIG_APPTRACE_DEST_NONE is selected in menuconfig.
* To customize at runtime, implement esp_apptrace_get_user_params()
* in your application. See esp_app_trace.h for details.
*/
#if !defined(CONFIG_APPTRACE_UART_TX_GPIO) || !defined(CONFIG_APPTRACE_UART_RX_GPIO)
#include "soc/uart_pins.h"
#endif
#ifndef CONFIG_APPTRACE_BUF_SIZE
#define CONFIG_APPTRACE_BUF_SIZE 16384
#endif
#ifndef CONFIG_APPTRACE_UART_RX_BUFF_SIZE
#define CONFIG_APPTRACE_UART_RX_BUFF_SIZE 128
#endif
#ifndef CONFIG_APPTRACE_UART_TX_BUFF_SIZE
#define CONFIG_APPTRACE_UART_TX_BUFF_SIZE 4096
#endif
#ifndef CONFIG_APPTRACE_UART_TX_MSG_SIZE
#define CONFIG_APPTRACE_UART_TX_MSG_SIZE 128
#endif
#ifndef CONFIG_APPTRACE_UART_BAUDRATE
#define CONFIG_APPTRACE_UART_BAUDRATE 1000000
#endif
#ifndef CONFIG_APPTRACE_UART_TASK_PRIO
#define CONFIG_APPTRACE_UART_TASK_PRIO 1
#endif
#ifndef CONFIG_APPTRACE_UART_TX_GPIO
#define CONFIG_APPTRACE_UART_TX_GPIO U1TXD_GPIO_NUM
#endif
#ifndef CONFIG_APPTRACE_UART_RX_GPIO
#define CONFIG_APPTRACE_UART_RX_GPIO U1RXD_GPIO_NUM
#endif
#ifndef CONFIG_APPTRACE_DEST_UART_NUM
#define CONFIG_APPTRACE_DEST_UART_NUM 1
#endif
#ifndef CONFIG_APPTRACE_SV_DEST_CPU_0
#define CONFIG_APPTRACE_SV_DEST_CPU_0 1
#endif
#endif /* ESP_APP_TRACE_CONFIG_H_ */
@@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_APP_TRACE_TYPES_H_
#define ESP_APP_TRACE_TYPES_H_
#include <stdint.h>
#include "spinlock.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Structure which holds data necessary for measuring time intervals.
*
* After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
* periodically to check timeout for expiration.
*/
typedef struct {
int64_t start; ///< time interval start (in us)
int64_t tmo; ///< timeout value (in us)
int64_t elapsed; ///< elapsed time (in us)
} esp_apptrace_tmo_t;
/** Tracing module synchronization lock */
typedef struct {
spinlock_t mux;
unsigned int_state;
} esp_apptrace_lock_t;
/** Ring buffer control structure.
*
* @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
* current ring buffer size can be temporarily shrunk in order to provide buffer with requested size.
*/
typedef struct {
uint8_t *data; ///< pointer to data storage
volatile uint32_t size; ///< size of data storage
volatile uint32_t cur_size; ///< current size of data storage
volatile uint32_t rd; ///< read pointer
volatile uint32_t wr; ///< write pointer
} esp_apptrace_rb_t;
/**
* Application trace data destinations
*/
typedef enum {
ESP_APPTRACE_DEST_JTAG,
ESP_APPTRACE_DEST_UART,
} esp_apptrace_dest_t;
/**
* Application trace configuration for UART destination
*/
typedef struct {
int uart_num; ///< Port number
int tx_pin_num; ///< TX pin number
int rx_pin_num; ///< RX pin number
int baud_rate; ///< Baud rate
uint32_t rx_buff_size; ///< RX ring buffer size
uint32_t tx_buff_size; ///< TX ring buffer size
uint32_t tx_msg_size; ///< Maximum size of the single message to transfer.
int task_prio; ///< Task priority
} esp_apptrace_uart_config_t;
/**
* Application trace trace header size in bytes. It is 2 bytes for SEGGER SystemView
*/
typedef enum {
ESP_APPTRACE_HEADER_SIZE_16 = 2,
ESP_APPTRACE_HEADER_SIZE_32 = 4,
} esp_apptrace_header_size_t;
/**
* Application trace configuration
*/
typedef struct {
esp_apptrace_dest_t dest; ///< Destination type (JTAG or UART)
union {
esp_apptrace_uart_config_t uart; ///< UART configuration (when dest is ESP_APPTRACE_DEST_UART)
struct { ///< Reserved for JTAG (when dest is ESP_APPTRACE_DEST_JTAG)
uint8_t _unused;
} jtag;
} dest_cfg; ///< Destination-specific configuration
uint32_t panic_flush_tmo; ///< Panic flush timeout in milliseconds
uint32_t panic_flush_thresh; ///< Panic flush threshold in bytes
} esp_apptrace_config_t;
#ifdef __cplusplus
}
#endif
#endif /* ESP_APP_TRACE_TYPES_H_ */
@@ -10,24 +10,13 @@
extern "C" {
#endif
#include "freertos/FreeRTOS.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "esp_app_trace_types.h"
/** Infinite waiting timeout */
#define ESP_APPTRACE_TMO_INFINITE ((uint32_t)-1)
/** Structure which holds data necessary for measuring time intervals.
*
* After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
* periodically to check timeout for expiration.
*/
typedef struct {
int64_t start; ///< time interval start (in us)
int64_t tmo; ///< timeout value (in us)
int64_t elapsed; ///< elapsed time (in us)
} esp_apptrace_tmo_t;
/**
* @brief Initializes timeout structure.
*
@@ -55,22 +44,12 @@ static inline uint32_t esp_apptrace_tmo_remaining_us(esp_apptrace_tmo_t *tmo)
return tmo->tmo != (int64_t) -1 ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
}
/** Tracing module synchronization lock */
typedef struct {
spinlock_t mux;
unsigned int_state;
} esp_apptrace_lock_t;
/**
* @brief Initializes lock structure.
*
* @param lock Pointer to lock structure to be initialized.
*/
static inline void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
{
portMUX_INITIALIZE(&lock->mux);
lock->int_state = 0;
}
void esp_apptrace_lock_init(esp_apptrace_lock_t *lock);
/**
* @brief Tries to acquire lock in specified time period.
@@ -91,19 +70,6 @@ esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *
*/
esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock);
/** Ring buffer control structure.
*
* @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
* current ring buffer size can be temporarily shrunk in order to provide buffer with requested size.
*/
typedef struct {
uint8_t *data; ///< pointer to data storage
volatile uint32_t size; ///< size of data storage
volatile uint32_t cur_size; ///< current size of data storage
volatile uint32_t rd; ///< read pointer
volatile uint32_t wr; ///< write pointer
} esp_apptrace_rb_t;
/**
* @brief Initializes ring buffer control structure.
*
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,7 +18,7 @@ extern "C" {
/**
* @brief Flushes remaining data in SystemView trace buffer to host.
*
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK.
*/
+10 -10
View File
@@ -1,14 +1,14 @@
[mapping:app_trace]
archive: libapp_trace.a
entries:
app_trace (noflash)
app_trace_util (noflash)
if APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE:
app_trace_membufs_proto (noflash)
if APPTRACE_DEST_JTAG = y:
port_jtag (noflash)
if APPTRACE_DEST_UART = y:
port_uart (noflash)
if APPTRACE_ENABLE = y:
app_trace (noflash)
app_trace_util (noflash)
if APPTRACE_DEST_JTAG = y || APPTRACE_DEST_NONE = y:
port_jtag (noflash)
app_trace_membufs_proto (noflash)
if APPTRACE_DEST_UART = y || APPTRACE_DEST_NONE = y:
port_uart (noflash)
if APPTRACE_SV_ENABLE = y:
SEGGER_SYSVIEW (noflash)
SEGGER_RTT_esp (noflash)
@@ -19,6 +19,6 @@ entries:
archive: libesp_driver_gptimer.a
entries:
if APPTRACE_SV_TS_SOURCE_GPTIMER = y:
gptimer: gptimer_get_raw_count (noflash)
gptimer: gptimer_get_raw_count (noflash)
else:
* (default)
* (default)
@@ -15,7 +15,7 @@ extern "C" {
/** Apptrace HW interface. */
typedef struct {
esp_err_t (*init)(void *hw_data);
esp_err_t (*init)(void *hw_data, const esp_apptrace_config_t *config);
uint8_t *(*get_up_buffer)(void *hw_data, uint32_t, esp_apptrace_tmo_t *);
esp_err_t (*put_up_buffer)(void *hw_data, uint8_t *, esp_apptrace_tmo_t *);
esp_err_t (*flush_up_buffer_nolock)(void *hw_data, uint32_t, esp_apptrace_tmo_t *);
@@ -24,6 +24,7 @@ typedef struct {
uint8_t *(*get_down_buffer)(void *hw_data, uint32_t *, esp_apptrace_tmo_t *);
esp_err_t (*put_down_buffer)(void *hw_data, uint8_t *, esp_apptrace_tmo_t *);
bool (*host_is_connected)(void *hw_data);
void (*set_header_size)(void *hw_data, esp_apptrace_header_size_t header_size);
} esp_apptrace_hw_t;
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data);
+146 -106
View File
@@ -3,19 +3,16 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "soc/soc.h"
#include "esp_log.h"
#include "esp_cpu.h"
#include "esp_app_trace_config.h"
#include "esp_app_trace_port.h"
#include "driver/uart.h"
#include "hal/uart_ll.h"
#define APP_TRACE_MAX_TX_BUFF_UART CONFIG_APPTRACE_UART_TX_BUFF_SIZE
#define APP_TRACE_MAX_TX_MSG_UART CONFIG_APPTRACE_UART_TX_MSG_SIZE
/** UART HW transport data */
typedef struct {
uint8_t inited;
@@ -23,28 +20,34 @@ typedef struct {
esp_apptrace_lock_t lock; // sync lock
#endif
uart_port_t port_num;
// TX data ring buffer
/* TX data ring buffer */
uint8_t *tx_data_buff;
uint32_t tx_data_buff_size;
int32_t tx_data_buff_in;
int32_t tx_data_buff_out;
// TX message buffer
/* TX message buffer */
uint8_t *tx_msg_buff;
uint32_t tx_msg_buff_size;
uint32_t tx_pending_msg_size;
// RX message buffer
/* RX message buffer */
uint8_t *down_buffer;
uint32_t down_buffer_size;
// Buffer overflow flags
/* Buffer overflow flags */
bool message_buff_overflow;
bool circular_buff_overflow;
} esp_apptrace_uart_data_t;
const static char *TAG = "esp_apptrace_uart";
static esp_err_t esp_apptrace_uart_lock(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_uart_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
esp_apptrace_uart_data_t *uart_data = hw_data;
esp_err_t ret = esp_apptrace_lock_take(&uart_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
@@ -52,11 +55,12 @@ static esp_err_t esp_apptrace_uart_lock(esp_apptrace_uart_data_t *hw_data, esp_a
return ESP_OK;
}
static esp_err_t esp_apptrace_uart_unlock(esp_apptrace_uart_data_t *hw_data)
static esp_err_t esp_apptrace_uart_unlock(void *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
esp_apptrace_uart_data_t *uart_data = hw_data;
ret = esp_apptrace_lock_give(&uart_data->lock);
#endif
return ret;
}
@@ -70,58 +74,69 @@ static inline void esp_apptrace_uart_hw_init(void)
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_send_uart_data(esp_apptrace_uart_data_t *hw_data, const char *data, uint32_t size, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_send_uart_data(void *hw_data, const char *data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
esp_apptrace_uart_data_t *uart_data = hw_data;
esp_err_t res = esp_apptrace_uart_lock(uart_data, tmo);
if (res != ESP_OK) {
return res;
}
// We store current out position to handle it without lock
volatile int32_t out_position = hw_data->tx_data_buff_out;
volatile int32_t out_position = uart_data->tx_data_buff_out;
int len_free = APP_TRACE_MAX_TX_BUFF_UART - (hw_data->tx_data_buff_in - out_position);
if (out_position > hw_data->tx_data_buff_in) {
len_free = out_position - hw_data->tx_data_buff_in;
int len_free = uart_data->tx_data_buff_size - (uart_data->tx_data_buff_in - out_position);
if (out_position > uart_data->tx_data_buff_in) {
len_free = out_position - uart_data->tx_data_buff_in;
}
int check_len = APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in;
int check_len = uart_data->tx_data_buff_size - uart_data->tx_data_buff_in;
if (size <= len_free) {
if (check_len >= size) {
memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, size);
hw_data->tx_data_buff_in += size;
memcpy(&uart_data->tx_data_buff[uart_data->tx_data_buff_in], data, size);
uart_data->tx_data_buff_in += size;
} else {
memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in);
memcpy(&hw_data->tx_data_buff[0], &data[APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in], size - (APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in));
hw_data->tx_data_buff_in = size - (APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in);
memcpy(&uart_data->tx_data_buff[uart_data->tx_data_buff_in],
data,
uart_data->tx_data_buff_size - uart_data->tx_data_buff_in);
memcpy(&uart_data->tx_data_buff[0],
&data[uart_data->tx_data_buff_size - uart_data->tx_data_buff_in],
size - (uart_data->tx_data_buff_size - uart_data->tx_data_buff_in));
uart_data->tx_data_buff_in = size - (uart_data->tx_data_buff_size - uart_data->tx_data_buff_in);
}
if (hw_data->tx_data_buff_in >= APP_TRACE_MAX_TX_BUFF_UART) {
hw_data->tx_data_buff_in = 0;
if (uart_data->tx_data_buff_in >= uart_data->tx_data_buff_size) {
uart_data->tx_data_buff_in = 0;
}
} else {
hw_data->circular_buff_overflow = true;
uart_data->circular_buff_overflow = true;
}
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_uart_unlock(uart_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ESP_OK;
}
static void send_buff_data(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static void send_buff_data(void *hw_data, esp_apptrace_tmo_t *tmo)
{
if (hw_data->tx_data_buff_in == hw_data->tx_data_buff_out) {
esp_apptrace_uart_data_t *uart_data = hw_data;
if (uart_data->tx_data_buff_in == uart_data->tx_data_buff_out) {
return;
}
// We store current in position to handle it without lock
volatile int32_t in_position = hw_data->tx_data_buff_in;
if (in_position > hw_data->tx_data_buff_out) {
int bytes_sent = uart_write_bytes(hw_data->port_num, &hw_data->tx_data_buff[hw_data->tx_data_buff_out], in_position - hw_data->tx_data_buff_out);
hw_data->tx_data_buff_out += bytes_sent;
volatile int32_t in_position = uart_data->tx_data_buff_in;
if (in_position > uart_data->tx_data_buff_out) {
int bytes_sent = uart_write_bytes(uart_data->port_num,
&uart_data->tx_data_buff[uart_data->tx_data_buff_out],
in_position - uart_data->tx_data_buff_out);
uart_data->tx_data_buff_out += bytes_sent;
} else {
int bytes_sent = uart_write_bytes(hw_data->port_num, &hw_data->tx_data_buff[hw_data->tx_data_buff_out], APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_out);
hw_data->tx_data_buff_out += bytes_sent;
if (hw_data->tx_data_buff_out >= APP_TRACE_MAX_TX_BUFF_UART) {
hw_data->tx_data_buff_out = 0;
int bytes_sent = uart_write_bytes(uart_data->port_num,
&uart_data->tx_data_buff[uart_data->tx_data_buff_out],
uart_data->tx_data_buff_size - uart_data->tx_data_buff_out);
uart_data->tx_data_buff_out += bytes_sent;
if (uart_data->tx_data_buff_out >= uart_data->tx_data_buff_size) {
uart_data->tx_data_buff_out = 0;
}
}
}
@@ -130,20 +145,21 @@ static void send_buff_data(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t
static void esp_apptrace_send_uart_tx_task(void *arg)
{
esp_apptrace_uart_data_t *hw_data = (esp_apptrace_uart_data_t *)arg;
esp_apptrace_uart_data_t *uart_data = arg;
esp_apptrace_tmo_t tmo;
esp_apptrace_tmo_init(&tmo, APP_TRACE_UART_STOP_WAIT_TMO);
vTaskDelay(10);
while (1) {
send_buff_data(hw_data, &tmo);
send_buff_data(uart_data, &tmo);
vTaskDelay(10);
if (hw_data->circular_buff_overflow == true) {
hw_data->circular_buff_overflow = false;
if (uart_data->circular_buff_overflow == true) {
uart_data->circular_buff_overflow = false;
ESP_LOGE(TAG, "Buffer overflow. Please increase UART baudrate, or increase UART TX ring buffer size in menuconfig.");
}
if (hw_data->message_buff_overflow == true) {
hw_data->message_buff_overflow = false;
if (uart_data->message_buff_overflow == true) {
uart_data->message_buff_overflow = false;
ESP_LOGE(TAG, "Message size more then message buffer!");
}
}
@@ -151,157 +167,181 @@ static void esp_apptrace_send_uart_tx_task(void *arg)
static const int APP_TRACE_UART_RX_BUF_SIZE = 4024;
static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
static esp_err_t esp_apptrace_uart_init(void *hw_data, const esp_apptrace_config_t *config)
{
esp_apptrace_uart_data_t *uart_data = hw_data;
const esp_apptrace_uart_config_t *apptrace_uart_config = &config->dest_cfg.uart;
/* esp_apptrace_uart_init() is called on every core, so ensure to do main initialization only once */
int core_id = esp_cpu_get_core_id();
if (core_id == 0) {
hw_data->tx_data_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_BUFF_UART, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (hw_data->tx_data_buff == NULL) {
uart_data->tx_data_buff_size = apptrace_uart_config->tx_buff_size;
uart_data->tx_data_buff = heap_caps_malloc(uart_data->tx_data_buff_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (uart_data->tx_data_buff == NULL) {
return ESP_ERR_NO_MEM;
}
hw_data->tx_data_buff_in = 0;
hw_data->tx_data_buff_out = 0;
hw_data->tx_msg_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_MSG_UART, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (hw_data->tx_msg_buff == NULL) {
uart_data->tx_data_buff_in = 0;
uart_data->tx_data_buff_out = 0;
uart_data->tx_msg_buff_size = apptrace_uart_config->tx_msg_size;
uart_data->tx_msg_buff = heap_caps_malloc(uart_data->tx_msg_buff_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (uart_data->tx_msg_buff == NULL) {
return ESP_ERR_NO_MEM;
}
hw_data->tx_msg_buff_size = 0;
hw_data->down_buffer_size = 0;
hw_data->message_buff_overflow = false;
hw_data->circular_buff_overflow = false;
uart_data->tx_pending_msg_size = 0;
uart_data->down_buffer_size = 0;
uart_data->message_buff_overflow = false;
uart_data->circular_buff_overflow = false;
assert((hw_data->port_num <= SOC_UART_NUM) && "Not possible to configure UART. Please check selected UART port");
assert((uart_data->port_num <= SOC_UART_NUM) && "Not possible to configure UART. Please check selected UART port");
int source_clk = UART_SCLK_DEFAULT;
#if SOC_UART_LP_NUM > 0
if (hw_data->port_num >= SOC_UART_HP_NUM) {
if (uart_data->port_num >= SOC_UART_HP_NUM) {
source_clk = LP_UART_SCLK_DEFAULT;
}
#endif
const uart_config_t uart_config = {
.baud_rate = CONFIG_APPTRACE_UART_BAUDRATE,
.baud_rate = apptrace_uart_config->baud_rate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = source_clk,
};
ESP_LOGI(TAG, "UART baud rate: %i", CONFIG_APPTRACE_UART_BAUDRATE);
ESP_LOGI(TAG, "UART baud rate: %i", apptrace_uart_config->baud_rate);
// We won't use a buffer for sending data.
esp_err_t err = uart_driver_install(hw_data->port_num, APP_TRACE_UART_RX_BUF_SIZE, APP_TRACE_UART_RX_BUF_SIZE, 0, NULL, 0);
assert((err == ESP_OK) && "Not possible to install UART. Please check and change menuconfig parameters!");
err = uart_param_config(hw_data->port_num, &uart_config);
assert((err == ESP_OK) && "Not possible to configure UART. Please check and change menuconfig parameters!");
err = uart_set_pin(hw_data->port_num, CONFIG_APPTRACE_UART_TX_GPIO, CONFIG_APPTRACE_UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
assert((err == ESP_OK) && "Not possible to configure UART RX/TX pins. Please check and change menuconfig parameters!");
esp_err_t __attribute__((unused)) err = uart_driver_install(uart_data->port_num,
APP_TRACE_UART_RX_BUF_SIZE,
APP_TRACE_UART_RX_BUF_SIZE,
0,
NULL,
0);
assert((err == ESP_OK) && "Not possible to install UART. Please check and change uart parameters!");
err = uart_param_config(uart_data->port_num, &uart_config);
assert((err == ESP_OK) && "Not possible to configure UART. Please check and change uart parameters!");
err = uart_set_pin(uart_data->port_num,
apptrace_uart_config->tx_pin_num,
apptrace_uart_config->rx_pin_num,
UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE);
assert((err == ESP_OK) && "Not possible to configure UART RX/TX pins. Please check and change the uart pins!");
int uart_prio = CONFIG_APPTRACE_UART_TASK_PRIO;
int uart_prio = apptrace_uart_config->task_prio;
if (uart_prio >= (configMAX_PRIORITIES - 1)) {
uart_prio = configMAX_PRIORITIES - 1;
}
err = xTaskCreate(esp_apptrace_send_uart_tx_task, "app_trace_uart_tx_task", 2500, hw_data, uart_prio, NULL);
err = xTaskCreate(esp_apptrace_send_uart_tx_task, "app_trace_uart_tx_task", 2500, uart_data, uart_prio, NULL);
assert((err == pdPASS) && "Not possible to configure UART. Not possible to create task!");
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
esp_apptrace_lock_init(&uart_data->lock);
#endif
}
// init UART on this CPU
esp_apptrace_uart_hw_init();
hw_data->inited |= 1 << core_id;
uart_data->inited |= 1 << core_id;
return ESP_OK;
}
static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
static uint8_t *esp_apptrace_uart_up_buffer_get(void *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (size > APP_TRACE_MAX_TX_MSG_UART) {
hw_data->message_buff_overflow = true;
esp_apptrace_uart_data_t *uart_data = hw_data;
if (size > uart_data->tx_msg_buff_size) {
uart_data->message_buff_overflow = true;
return NULL;
}
if (hw_data->tx_msg_buff_size != 0) {
if (uart_data->tx_pending_msg_size != 0) {
// A previous message was not sent.
return NULL;
}
esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_uart_lock(uart_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = hw_data->tx_msg_buff;
hw_data->tx_msg_buff_size = size;
uint8_t *ptr = uart_data->tx_msg_buff;
// Set the amount of data to send
uart_data->tx_pending_msg_size = size;
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_uart_unlock(uart_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_uart_up_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
esp_err_t res = esp_apptrace_send_uart_data(hw_data, (const char *)ptr, hw_data->tx_msg_buff_size, tmo);
esp_apptrace_uart_data_t *uart_data = hw_data;
esp_err_t res = esp_apptrace_send_uart_data(uart_data, (const char *)ptr, uart_data->tx_pending_msg_size, tmo);
// Clear size to indicate that we've sent data
hw_data->tx_msg_buff_size = 0;
uart_data->tx_pending_msg_size = 0;
return res;
}
static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size)
static void esp_apptrace_uart_down_buffer_config(void *hw_data, uint8_t *buf, uint32_t size)
{
hw_data->down_buffer = (uint8_t *)malloc(size);
if (hw_data->down_buffer == NULL) {
esp_apptrace_uart_data_t *uart_data = hw_data;
uart_data->down_buffer = (uint8_t *)malloc(size);
if (uart_data->down_buffer == NULL) {
assert(false && "Failed to allocate apptrace uart down buffer!");
}
hw_data->down_buffer_size = size;
uart_data->down_buffer_size = size;
}
static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
static uint8_t *esp_apptrace_uart_down_buffer_get(void *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
esp_apptrace_uart_data_t *uart_data = hw_data;
uint8_t *ptr = NULL;
if (*size > hw_data->down_buffer_size) {
if (*size > uart_data->down_buffer_size) {
return NULL;
}
esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_uart_lock(uart_data, tmo);
if (res != ESP_OK) {
return NULL;
}
size_t uart_fifolen = 0;
uart_get_buffered_data_len(hw_data->port_num, &uart_fifolen);
uart_get_buffered_data_len(uart_data->port_num, &uart_fifolen);
if (uart_fifolen > 0) {
if (*size < uart_fifolen) {
uart_fifolen = *size;
}
*size = uart_fifolen;
ptr = hw_data->down_buffer;
*size = uart_read_bytes(hw_data->port_num, ptr, uart_fifolen, 0);
ptr = uart_data->down_buffer;
*size = uart_read_bytes(uart_data->port_num, ptr, uart_fifolen, 0);
}
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_uart_unlock(uart_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_uart_down_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
return ESP_OK;
}
static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data)
static bool esp_apptrace_uart_host_is_connected(void *hw_data)
{
return hw_data->inited & 1;
esp_apptrace_uart_data_t *uart_data = hw_data;
return uart_data->inited & 1;
}
static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_uart_flush_nolock(void *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
return ESP_OK;
}
static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_uart_flush(void *hw_data, esp_apptrace_tmo_t *tmo)
{
return ESP_OK;
}
@@ -312,15 +352,15 @@ esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
static esp_apptrace_uart_data_t s_uart_hw_data;
static esp_apptrace_hw_t s_uart_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_uart_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
.init = esp_apptrace_uart_init,
.get_up_buffer = esp_apptrace_uart_up_buffer_get,
.put_up_buffer = esp_apptrace_uart_up_buffer_put,
.flush_up_buffer_nolock = esp_apptrace_uart_flush_nolock,
.flush_up_buffer = esp_apptrace_uart_flush,
.down_buffer_config = esp_apptrace_uart_down_buffer_config,
.get_down_buffer = esp_apptrace_uart_down_buffer_get,
.put_down_buffer = esp_apptrace_uart_down_buffer_put,
.host_is_connected = esp_apptrace_uart_host_is_connected,
};
s_uart_hw_data.port_num = num;
*data = &s_uart_hw_data;
+76 -51
View File
@@ -7,6 +7,7 @@
#include "sdkconfig.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "esp_app_trace_config.h"
#include "esp_app_trace_membufs_proto.h"
#include "esp_app_trace_port.h"
#include "riscv/semihosting.h"
@@ -74,10 +75,11 @@ __attribute__((weak)) void esp_apptrace_get_up_buffers(esp_apptrace_mem_block_t
mem_blocks_cfg[1].sz = CONFIG_APPTRACE_BUF_SIZE;
}
static esp_err_t esp_apptrace_riscv_lock(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_riscv_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
esp_apptrace_riscv_data_t *riscv_data = hw_data;
esp_err_t ret = esp_apptrace_lock_take(&riscv_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
@@ -85,11 +87,12 @@ static esp_err_t esp_apptrace_riscv_lock(esp_apptrace_riscv_data_t *hw_data, esp
return ESP_OK;
}
static esp_err_t esp_apptrace_riscv_unlock(esp_apptrace_riscv_data_t *hw_data)
static esp_err_t esp_apptrace_riscv_unlock(void *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
esp_apptrace_riscv_data_t *riscv_data = hw_data;
ret = esp_apptrace_lock_give(&riscv_data->lock);
#endif
return ret;
}
@@ -98,89 +101,96 @@ static esp_err_t esp_apptrace_riscv_unlock(esp_apptrace_riscv_data_t *hw_data)
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data)
static esp_err_t esp_apptrace_riscv_init(void *hw_data, const esp_apptrace_config_t *config)
{
int core_id = esp_cpu_get_core_id();
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (hw_data->inited == 0) {
/* esp_apptrace_riscv_init() is called on every core, so ensure to do main initialization only once */
int core_id = esp_cpu_get_core_id();
if (core_id == 0) {
esp_apptrace_mem_block_t mem_blocks_cfg[2];
esp_apptrace_get_up_buffers(mem_blocks_cfg);
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
riscv_data->membufs.header_size = ESP_APPTRACE_HEADER_SIZE_32;
esp_err_t res = esp_apptrace_membufs_init(&riscv_data->membufs, mem_blocks_cfg);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
return res;
}
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
esp_apptrace_lock_init(&riscv_data->lock);
#endif
}
hw_data->inited |= 1 << core_id;
riscv_data->inited |= 1 << core_id;
ESP_APPTRACE_LOGI("Apptrace initialized on CPU%d. Tracing control block @ %p.", core_id, &s_tracing_ctrl[core_id]);
s_tracing_ctrl[core_id].mem_blocks = hw_data->membufs.blocks;
s_tracing_ctrl[core_id].mem_blocks = riscv_data->membufs.blocks;
for (int i = 0; i < 2; i++) {
ESP_APPTRACE_LOGD("Mem buf[%d] %" PRIu32 " bytes @ %p (%p/%p)", i,
s_tracing_ctrl[core_id].mem_blocks[i].sz, s_tracing_ctrl[core_id].mem_blocks[i].start,
&(s_tracing_ctrl[core_id].mem_blocks[i].start), &(s_tracing_ctrl[core_id].mem_blocks[i].sz));
}
// notify host about control block address
int res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]);
int __attribute__((unused)) res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]);
assert(res == 0 && "Failed to send config to host!");
return ESP_OK;
}
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
static uint8_t *esp_apptrace_riscv_up_buffer_get(void *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_riscv_lock(riscv_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
uint8_t *ptr = esp_apptrace_membufs_up_buffer_get(&riscv_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_riscv_unlock(riscv_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_riscv_up_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&riscv_data->membufs, ptr, tmo);
return res;
}
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size)
static void esp_apptrace_riscv_down_buffer_config(void *hw_data, uint8_t *buf, uint32_t size)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return;
}
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
esp_apptrace_membufs_down_buffer_config(&riscv_data->membufs, buf, size);
}
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
static uint8_t *esp_apptrace_riscv_down_buffer_get(void *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_riscv_lock(riscv_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
uint8_t *ptr = esp_apptrace_membufs_down_buffer_get(&riscv_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
@@ -189,9 +199,11 @@ static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw
return ptr;
}
static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_riscv_down_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
@@ -200,7 +212,7 @@ static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *h
return res;
}*/
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&riscv_data->membufs, ptr, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
/*if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
@@ -209,36 +221,42 @@ static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *h
return res;
}
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data)
static bool esp_apptrace_riscv_host_is_connected(void *hw_data)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return false;
}
return s_tracing_ctrl[esp_cpu_get_core_id()].ctrl & ESP_APPTRACE_RISCV_HOST_CONNECT ? true : false;
}
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_riscv_flush_nolock(void *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return ESP_ERR_INVALID_STATE;
}
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
return esp_apptrace_membufs_flush_nolock(&riscv_data->membufs, min_sz, tmo);
}
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_riscv_flush(void *hw_data, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
esp_apptrace_riscv_data_t *riscv_data = hw_data;
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_riscv_lock(riscv_data, tmo);
if (res != ESP_OK) {
return res;
}
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
res = esp_apptrace_membufs_flush_nolock(&riscv_data->membufs, 0, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_riscv_unlock(riscv_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return res;
@@ -319,6 +337,12 @@ static bool esp_apptrace_riscv_host_data_pending(void)
return (ctrl_reg & ESP_APPTRACE_RISCV_HOST_DATA) ? true : false;
}
static void esp_apptrace_riscv_set_header_size(void *hw_data, esp_apptrace_header_size_t header_size)
{
esp_apptrace_riscv_data_t *riscv_data = hw_data;
riscv_data->membufs.header_size = header_size;
}
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
@@ -333,15 +357,16 @@ esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
},
};
static esp_apptrace_hw_t s_trace_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_riscv_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_riscv_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_riscv_host_is_connected,
.init = esp_apptrace_riscv_init,
.get_up_buffer = esp_apptrace_riscv_up_buffer_get,
.put_up_buffer = esp_apptrace_riscv_up_buffer_put,
.flush_up_buffer_nolock = esp_apptrace_riscv_flush_nolock,
.flush_up_buffer = esp_apptrace_riscv_flush,
.down_buffer_config = esp_apptrace_riscv_down_buffer_config,
.get_down_buffer = esp_apptrace_riscv_down_buffer_get,
.put_down_buffer = esp_apptrace_riscv_down_buffer_put,
.host_is_connected = esp_apptrace_riscv_host_is_connected,
.set_header_size = esp_apptrace_riscv_set_header_size,
};
*data = &s_trace_hw_data;
return &s_trace_hw;
+72 -49
View File
@@ -195,10 +195,11 @@ static uint8_t * const s_trax_blocks[] = {
(uint8_t *)TRACEMEM_BLK1_ADDR
};
static esp_err_t esp_apptrace_trax_lock(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_trax_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
esp_apptrace_trax_data_t *trax_data = hw_data;
esp_err_t ret = esp_apptrace_lock_take(&trax_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
@@ -206,11 +207,12 @@ static esp_err_t esp_apptrace_trax_lock(esp_apptrace_trax_data_t *hw_data, esp_a
return ESP_OK;
}
static esp_err_t esp_apptrace_trax_unlock(esp_apptrace_trax_data_t *hw_data)
static esp_err_t esp_apptrace_trax_unlock(void *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
esp_apptrace_trax_data_t *trax_data = hw_data;
ret = esp_apptrace_lock_give(&trax_data->lock);
#endif
return ret;
}
@@ -262,11 +264,12 @@ static inline void esp_apptrace_trax_memory_enable(void)
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data)
static esp_err_t esp_apptrace_trax_init(void *hw_data, const esp_apptrace_config_t *config)
{
int core_id = esp_cpu_get_core_id();
esp_apptrace_trax_data_t *trax_data = hw_data;
// 'esp_apptrace_trax_init()' is called on every core, so ensure to do main initialization only once
int core_id = esp_cpu_get_core_id();
if (core_id == 0) {
esp_apptrace_mem_block_t mem_blocks_cfg[2] = {
{
@@ -278,87 +281,94 @@ static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data)
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
},
};
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
trax_data->membufs.header_size = ESP_APPTRACE_HEADER_SIZE_32;
esp_err_t res = esp_apptrace_membufs_init(&trax_data->membufs, mem_blocks_cfg);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
return res;
}
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
esp_apptrace_lock_init(&trax_data->lock);
#endif
esp_apptrace_trax_memory_enable();
esp_apptrace_trax_select_memory_block(0);
}
// init TRAX on this CPU
esp_apptrace_trax_hw_init();
hw_data->inited |= 1 << core_id;
trax_data->inited |= 1 << core_id;
return ESP_OK;
}
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
static uint8_t *esp_apptrace_trax_up_buffer_get(void *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_trax_lock(trax_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
uint8_t *ptr = esp_apptrace_membufs_up_buffer_get(&trax_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_trax_unlock(trax_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_trax_up_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&trax_data->membufs, ptr, tmo);
return res;
}
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size)
static void esp_apptrace_trax_down_buffer_config(void *hw_data, uint8_t *buf, uint32_t size)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return;
}
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
esp_apptrace_membufs_down_buffer_config(&trax_data->membufs, buf, size);
}
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
static uint8_t *esp_apptrace_trax_down_buffer_get(void *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_trax_lock(trax_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
uint8_t *ptr = esp_apptrace_membufs_down_buffer_get(&trax_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_trax_unlock(trax_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_trax_down_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
@@ -367,7 +377,7 @@ static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_
return res;
}*/
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&trax_data->membufs, ptr, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
/*if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
@@ -376,36 +386,42 @@ static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_
return res;
}
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data)
static bool esp_apptrace_trax_host_is_connected(void *hw_data)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return false;
}
return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false;
}
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_trax_flush_nolock(void *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return ESP_ERR_INVALID_STATE;
}
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
return esp_apptrace_membufs_flush_nolock(&trax_data->membufs, min_sz, tmo);
}
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
static esp_err_t esp_apptrace_trax_flush(void *hw_data, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
esp_apptrace_trax_data_t *trax_data = hw_data;
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
esp_err_t res = esp_apptrace_trax_lock(trax_data, tmo);
if (res != ESP_OK) {
return res;
}
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
res = esp_apptrace_membufs_flush_nolock(&trax_data->membufs, 0, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
if (esp_apptrace_trax_unlock(trax_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return res;
@@ -494,6 +510,12 @@ static bool esp_apptrace_trax_host_data_pending(void)
return (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) ? true : false;
}
static void esp_apptrace_trax_set_header_size(void *hw_data, esp_apptrace_header_size_t header_size)
{
esp_apptrace_trax_data_t *trax_data = hw_data;
trax_data->membufs.header_size = header_size;
}
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
@@ -508,15 +530,16 @@ esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
},
};
static esp_apptrace_hw_t s_trax_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_trax_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_trax_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_trax_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_trax_host_is_connected,
.init = esp_apptrace_trax_init,
.get_up_buffer = esp_apptrace_trax_up_buffer_get,
.put_up_buffer = esp_apptrace_trax_up_buffer_put,
.flush_up_buffer_nolock = esp_apptrace_trax_flush_nolock,
.flush_up_buffer = esp_apptrace_trax_flush,
.down_buffer_config = esp_apptrace_trax_down_buffer_config,
.get_down_buffer = esp_apptrace_trax_down_buffer_get,
.put_down_buffer = esp_apptrace_trax_down_buffer_put,
.host_is_connected = esp_apptrace_trax_host_is_connected,
.set_header_size = esp_apptrace_trax_set_header_size,
};
*data = &s_trax_hw_data;
return &s_trax_hw;
@@ -40,6 +40,7 @@ typedef struct {
esp_apptrace_mem_block_t blocks[2]; // memory blocks
// ring buffer control struct for data from host (down buffer)
esp_apptrace_rb_t rb_down;
int header_size; ///< Size of the trace header (2 or 4 bytes)
} esp_apptrace_membufs_proto_data_t;
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, const esp_apptrace_mem_block_t blocks_cfg[2]);
-1
View File
@@ -2,7 +2,6 @@
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
CONFIG_ESP32_APPTRACE_DESTINATION CONFIG_APPTRACE_DESTINATION
CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE
CONFIG_ESP32_APPTRACE_DEST_TRAX CONFIG_APPTRACE_DEST_JTAG
CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE
CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE
@@ -32,19 +32,12 @@ static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
static uint16_t s_events_buf_filled;
static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
#if CONFIG_APPTRACE_SV_DEST_UART
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_UART
#if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
#define APPTRACE_SV_DEST_CPU 0
#else
#define APPTRACE_SV_DEST_CPU 1
#endif // CONFIG_APPTRACE_SV_DEST_CPU_0
#elif CONFIG_APPTRACE_SV_DEST_JTAG || (CONFIG_APPTRACE_ENABLE && CONFIG_APPTRACE_DEST_UART_NONE)
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_JTAG
#endif
/*********************************************************************
*
* Public code
@@ -70,13 +63,13 @@ void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo)
{
esp_err_t res;
if (s_events_buf_filled > 0) {
res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, tmo);
res = esp_apptrace_write(s_events_buf, s_events_buf_filled, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res);
}
}
// flush even if we failed to write buffered events, because no new events will be sent after STOP
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_SYSVIEW, min_sz, tmo);
res = esp_apptrace_flush_nolock(min_sz, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res);
}
@@ -124,7 +117,7 @@ void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo)
unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize)
{
uint32_t size = BufferSize;
esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_SYSVIEW, pData, &size, 0);
esp_err_t res = esp_apptrace_read(pData, &size, 0);
if (res != ESP_OK) {
return 0;
}
@@ -159,70 +152,70 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
{
uint8_t *pbuf = (uint8_t *)pBuffer;
uint8_t event_id = *pbuf;
#if CONFIG_APPTRACE_SV_DEST_UART
if (
(APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) &&
(
(event_id == SYSVIEW_EVTID_ISR_ENTER) ||
(event_id == SYSVIEW_EVTID_ISR_EXIT) ||
(event_id == SYSVIEW_EVTID_TASK_START_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_START_READY) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_READY) ||
(event_id == SYSVIEW_EVTID_MARK_START) ||
(event_id == SYSVIEW_EVTID_MARK_STOP) ||
(event_id == SYSVIEW_EVTID_TIMER_ENTER) ||
(event_id == SYSVIEW_EVTID_TIMER_EXIT) ||
(event_id == SYSVIEW_EVTID_STACK_INFO) ||
(event_id == SYSVIEW_EVTID_MODULEDESC)
)
) {
return NumBytes;
}
// This is workaround for SystemView!
// Without this line SystemView will hangs on when heap tracing enabled.
if (event_id == SYSVIEW_EVTID_MODULEDESC) {
return NumBytes;
if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_UART) {
if (
(APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) &&
(
(event_id == SYSVIEW_EVTID_ISR_ENTER) ||
(event_id == SYSVIEW_EVTID_ISR_EXIT) ||
(event_id == SYSVIEW_EVTID_TASK_START_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_START_READY) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_READY) ||
(event_id == SYSVIEW_EVTID_MARK_START) ||
(event_id == SYSVIEW_EVTID_MARK_STOP) ||
(event_id == SYSVIEW_EVTID_TIMER_ENTER) ||
(event_id == SYSVIEW_EVTID_TIMER_EXIT) ||
(event_id == SYSVIEW_EVTID_STACK_INFO) ||
(event_id == SYSVIEW_EVTID_MODULEDESC)
)
) {
return NumBytes;
}
// This is workaround for SystemView!
// Without this line SystemView will hangs on when heap tracing enabled.
if (event_id == SYSVIEW_EVTID_MODULEDESC) {
return NumBytes;
}
}
#endif // CONFIG_APPTRACE_SV_DEST_UART
if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
return 0;
}
#if CONFIG_APPTRACE_SV_DEST_JTAG
if (esp_cpu_get_core_id()) { // dual core specific code
// use the highest - 1 bit of event ID to indicate core ID
// the highest bit can not be used due to event ID encoding method
// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
if (*pbuf & 0x80) { // 2 bytes ID
*(pbuf + 1) |= (1 << 6);
} else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
*pbuf |= (1 << 6);
if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_JTAG) {
if (esp_cpu_get_core_id()) { // dual core specific code
// use the highest - 1 bit of event ID to indicate core ID
// the highest bit can not be used due to event ID encoding method
// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
if (*pbuf & 0x80) { // 2 bytes ID
*(pbuf + 1) |= (1 << 6);
} else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
*pbuf |= (1 << 6);
}
}
if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
esp_err_t res = esp_apptrace_write(s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
if (res != ESP_OK) {
return 0; // skip current data buffer only, accumulated events are kept
}
s_events_buf_filled = 0;
}
}
#endif // CONFIG_APPTRACE_SV_DEST_JTAG
#if CONFIG_APPTRACE_SV_DEST_JTAG
if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
s_events_buf_filled += NumBytes;
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_UART) {
esp_err_t res = esp_apptrace_write(pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO);
if (res != ESP_OK) {
return 0; // skip current data buffer only, accumulated events are kept
}
s_events_buf_filled = 0;
}
#endif
memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
s_events_buf_filled += NumBytes;
#if CONFIG_APPTRACE_SV_DEST_UART
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO);
if (res != ESP_OK) {
return 0; // skip current data buffer only, accumulated events are kept
}
s_events_buf_filled = 0;
#endif
if (event_id == SYSVIEW_EVTID_TRACE_STOP) {
SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
@@ -288,19 +281,20 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
*/
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags)
{
return esp_apptrace_down_buffer_config(ESP_APPTRACE_DEST_SYSVIEW, s_down_buf, sizeof(s_down_buf));
return esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf));
}
/*************************** Init hook ****************************
*
* This init function is placed here because this port file will be
* linked whenever SystemView is used.
* This init function is placed here because this port file will be linked whenever SystemView is used.
* It is used to initialize SystemView and app trace configuration by the init hook function.
* Otherwise, SystemView and app trace initialization needs to be done later in the app_main.
*/
ESP_SYSTEM_INIT_FN(sysview_init, SECONDARY, BIT(0), 120)
ESP_SYSTEM_INIT_FN(sysview_early_init, SECONDARY, BIT(0), 120)
{
esp_apptrace_set_header_size(ESP_APPTRACE_HEADER_SIZE_16);
SEGGER_SYSVIEW_Conf();
return ESP_OK;
}
/*************************** End of file ****************************/
@@ -9,6 +9,6 @@ components/app_trace/test_apps:
- esp_driver_uart
- esp_driver_gptimer
disable:
- if: IDF_TARGET in ["esp32c5", "esp32c61", "esp32h21", "esp32h4"]
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
temporary: true
reason: not support yet # TODO: [ESP32C5] IDF-8705, [ESP32C61] IDF-9306, [ESP32H21] IDF-11539 [ESP32H4] IDF-12325
reason: not support yet # TODO: [ESP32H21] IDF-11539 [ESP32H4] IDF-12325
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
# app_trace test
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,16 +17,15 @@
#include "freertos/semphr.h"
#include "freertos/task.h"
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
#include "esp_app_trace.h"
#include "esp_app_trace_util.h"
#define ESP_APPTRACE_TEST_USE_PRINT_LOCK 0
#define ESP_APPTRACE_TEST_PRN_WRERR_MAX 5
#define ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH 100
#define ESP_APPTRACE_TEST_BLOCK_SIZE 1024
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
const static char *TAG = "esp_apptrace_test";
#if ESP_APPTRACE_TEST_USE_PRINT_LOCK == 1
@@ -67,9 +66,9 @@ const static char *TAG = "esp_apptrace_test";
#define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
#if CONFIG_APPTRACE_SV_ENABLE == 0
#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, _b_, _s_, ESP_APPTRACE_TMO_INFINITE)
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, _b_, _s_, 0UL)
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, _b_, _s_, 0)
#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(_b_, _s_, ESP_APPTRACE_TMO_INFINITE)
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(_b_, _s_, 0UL)
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(_b_, _s_, 0)
typedef struct {
uint8_t *buf;
@@ -625,7 +624,7 @@ static int esp_logtrace_printf(const char *fmt, ...)
va_start(ap, fmt);
int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_JTAG, ESP_APPTRACE_TMO_INFINITE, fmt, ap);
int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_TMO_INFINITE, fmt, ap);
va_end(ap);
@@ -657,7 +656,7 @@ static void esp_logtrace_task(void *p)
break;
}
}
esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_DEST_JTAG, ESP_APPTRACE_TMO_INFINITE);
esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_TMO_INFINITE);
if (ret != ESP_OK) {
ESP_APPTRACE_TEST_LOGE("Failed to flush printf buf (%d)!", ret);
}
@@ -1,2 +1,3 @@
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
CONFIG_APPTRACE_ENABLE=y
CONFIG_APPTRACE_DEST_JTAG=y
@@ -32,7 +32,8 @@ set(COMPONENTS
main
efuse
esp_libc
esp_tee)
esp_tee
esp_stdio)
# EXTRA_COMPONENT_DIRS can be populated with directories containing one or several components.
# Make sure this variable contains `bootloader_components` directory of the project being compiled.
@@ -38,7 +38,7 @@ __attribute__((weak)) void bootloader_clock_configure(void)
#if CONFIG_IDF_TARGET_ESP32
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
* 240 MHz may cause the chip to lock up (see CPU-3.5 of the errata
* document). For rev. 0, switch to 240 instead if it has been enabled
* previously.
*/
@@ -1,17 +1,19 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "bootloader_random.h"
#include "esp_log.h"
#include "soc/syscon_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/apb_saradc_reg.h"
#include "soc/system_reg.h"
#include "esp_private/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h"
#include "hal/adc_ll.h"
#include "hal/temperature_sensor_ll.h"
#include "esp_private/sar_periph_ctrl.h"
#define ADC_RNG_CLKM_DIV_NUM 15
#define ADC_RNG_CLKM_DIV_B 0
#define ADC_RNG_CLKM_DIV_A 0
void bootloader_random_enable(void)
{
@@ -19,49 +21,57 @@ void bootloader_random_enable(void)
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0x3);
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M);
// Bridging sar2 internal reference voltage
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0);
#ifndef BOOTLOADER_BUILD
sar_periph_ctrl_adc_reset();
#else
tsens_ll_reg_values_t saved_tsens_regs = {};
tsens_ll_backup_registers(&saved_tsens_regs);
_adc_ll_reset_register();
// Restore temperature sensor related register values after ADC reset
_temperature_sensor_ll_reset_module();
tsens_ll_restore_registers(&saved_tsens_regs);
#endif
// Enable SAR ADC2 internal channel to read adc2 ref voltage for additional entropy
SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN_M);
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_APB_SARADC_RST_M);
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 0x2);
SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN_M);
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_GATED_M);
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_XPD_SAR_FORCE, 0x3);
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_DIV, 1);
_adc_ll_enable_bus_clock(true);
adc_ll_enable_func_clock(true);
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_APB);
adc_ll_digi_controller_clk_div(ADC_RNG_CLKM_DIV_NUM, ADC_RNG_CLKM_DIV_B, ADC_RNG_CLKM_DIV_A);
adc_ll_digi_set_power_manage(ADC_LL_POWER_SW_ON);
adc_ll_digi_set_fsm_time(ADC_LL_FSM_RSTB_WAIT_DEFAULT, ADC_LL_FSM_START_WAIT_DEFAULT,
ADC_LL_FSM_STANDBY_WAIT_DEFAULT);
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_RSTB_WAIT, 8);
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_XPD_WAIT, 5);
REG_SET_FIELD(APB_SARADC_FSM_WAIT_REG, APB_SARADC_STANDBY_WAIT, 100);
#ifndef BOOTLOADER_BUILD
regi2c_saradc_enable();
#else
regi2c_ctrl_ll_i2c_sar_periph_enable();
#endif
// enable analog i2c master clock for RNG runtime
ANALOG_CLOCK_ENABLE();
adc_ll_regi2c_init();
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_P_CLEAR_M);
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_P_CLEAR_M);
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_PATT_LEN, 0);
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB1_REG, APB_SARADC_SAR_PATT_TAB1, 0x9cffff);// Set adc2 internal channel & atten
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB2_REG, APB_SARADC_SAR_PATT_TAB2, 0xffffff);
// Set ADC sampling frequency
REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_TARGET, 100);
REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLKM_DIV_NUM, 15);
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG,APB_SARADC_MEAS_NUM_LIMIT);
SET_PERI_REG_MASK(APB_SARADC_DMA_CONF_REG, APB_SARADC_APB_ADC_TRANS_M);
SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG,APB_SARADC_TIMER_EN);
adc_digi_pattern_config_t pattern_config = {};
pattern_config.unit = ADC_UNIT_2;
pattern_config.atten = ADC_ATTEN_DB_12;
pattern_config.channel = ADC_CHANNEL_1; //Use reserved channel 10 to get internal voltage
adc_ll_digi_set_pattern_table(ADC_UNIT_2, 0, pattern_config);
adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, 1);
adc_ll_digi_dma_enable();
adc_ll_digi_set_clk_div(1);
adc_ll_digi_set_trigger_interval(100);
adc_ll_digi_trigger_enable();
}
void bootloader_random_disable(void)
{
/* Restore internal I2C bus state */
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
/* Restore SARADC to default mode */
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG,APB_SARADC_TIMER_EN);
CLEAR_PERI_REG_MASK(APB_SARADC_DMA_CONF_REG, APB_SARADC_APB_ADC_TRANS_M);
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB1_REG, APB_SARADC_SAR_PATT_TAB1, 0xffffff);
REG_SET_FIELD(APB_SARADC_SAR_PATT_TAB2_REG, APB_SARADC_SAR_PATT_TAB2, 0xffffff);
CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN_M);
REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_XPD_SAR_FORCE, 0);
REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0);
_adc_ll_enable_bus_clock(false);
adc_ll_digi_trigger_disable();
adc_ll_digi_reset_pattern_table();
adc_ll_regi2c_adc_deinit();
#ifndef BOOTLOADER_BUILD
regi2c_saradc_disable();
#endif
// disable analog i2c master clock
ANALOG_CLOCK_DISABLE();
}
@@ -717,7 +717,25 @@ static void load_image(const esp_image_metadata_t *image_data)
*/
ESP_LOGI(TAG, "Checking flash encryption...");
bool flash_encryption_enabled = esp_flash_encrypt_state();
if (!flash_encryption_enabled) {
if (flash_encryption_enabled) {
#if BOOTLOADER_BUILD
/* Ensure security eFuses are burnt */
esp_efuse_batch_write_begin();
esp_err_t err = esp_flash_encryption_enable_secure_features();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error setting security eFuses (err=0x%x).", err);
esp_efuse_batch_write_cancel();
return;
}
err = esp_efuse_batch_write_commit();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
return;
}
ESP_LOGI(TAG, "Security eFuses are burnt");
#endif // BOOTLOADER_BUILD
} else {
#ifdef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED is set, refusing to boot.");
return;
+13
View File
@@ -50,6 +50,9 @@ set(ble_mesh_v11_include_dirs
"esp_ble_mesh/v1.1/api/core/include"
"esp_ble_mesh/v1.1/api/models/include"
"esp_ble_mesh/v1.1/btc/include"
"esp_ble_mesh/v1.1/include"
"esp_ble_mesh/v1.1/dfu"
"esp_ble_mesh/v1.1/mbt"
)
if(CONFIG_IDF_DOC_BUILD)
@@ -631,9 +634,13 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/v1.1/api/core/esp_ble_mesh_sar_model_api.c"
"esp_ble_mesh/v1.1/api/core/esp_ble_mesh_srpl_model_api.c"
"esp_ble_mesh/v1.1/api/models/esp_ble_mesh_mbt_model_api.c"
"esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_model_api.c"
"esp_ble_mesh/v1.1/api/models/esp_ble_mesh_dfu_slot_api.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_agg_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_brc_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_df_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_slot.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_lcd_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_mbt_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_odp_model.c"
@@ -641,6 +648,12 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c"
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c"
"esp_ble_mesh/v1.1/mbt/blob_srv.c"
"esp_ble_mesh/v1.1/mbt/blob_cli.c"
"esp_ble_mesh/v1.1/dfu/dfu_cli.c"
"esp_ble_mesh/v1.1/dfu/dfu_srv.c"
"esp_ble_mesh/v1.1/dfu/dfu_slot.c"
"esp_ble_mesh/v1.1/dfu/dfu_metadata.c"
"esp_ble_mesh/lib/ext.c")
if(CONFIG_BLE_MESH_SAR_ENHANCEMENT)
list(APPEND srcs "esp_ble_mesh/core/transport.enh.c")
+6
View File
@@ -255,3 +255,9 @@ config BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX
default 0
help
IO number for UART TX port
config BT_LE_USED_MEM_STATISTICS_ENABLED
bool "Enable used memory statistics"
default n
help
Used in internal tests only. Enable used memory statistics.
+4
View File
@@ -89,6 +89,7 @@
#include "btc_ble_mesh_rpr_model.h"
#include "btc_ble_mesh_sar_model.h"
#include "btc_ble_mesh_srpl_model.h"
#include "btc_ble_mesh_dfu_model.h"
#endif /* CONFIG_BLE_MESH_V11_SUPPORT */
#endif /* #if CONFIG_BLE_MESH */
@@ -262,6 +263,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#if CONFIG_BLE_MESH_MBT_SRV
[BTC_PID_MBT_SERVER] = {btc_ble_mesh_mbt_server_call_handler, btc_ble_mesh_mbt_server_cb_handler },
#endif /* CONFIG_BLE_MESH_MBT_SRV */
#if CONFIG_BLE_MESH_DFU_CLI
[BTC_PID_DFU_CLIENT] = {btc_ble_mesh_dfu_client_call_handler, btc_ble_mesh_dfu_client_cb_handler},
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50
[BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler },
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -106,6 +106,10 @@ typedef enum {
BTC_PID_TIME_SCENE_SERVER,
BTC_PID_MBT_CLIENT,
BTC_PID_MBT_SERVER,
BTC_PID_BLOB_CLIENT,
BTC_PID_BLOB_SERVER,
BTC_PID_DFU_CLIENT,
BTC_PID_DFU_SERVER,
BTC_PID_BLE_MESH_BLE_COEX,
#endif /* CONFIG_BLE_MESH */
#if (BLE_FEAT_ISO_EN == TRUE)
+2
View File
@@ -141,7 +141,9 @@
#define LOG_LOCAL_LEVEL_MAPPING LOG_LOCAL_LEVEL
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#define BT_LOG_LEVEL_CHECK(LAYER, LEVEL) (MAX(LAYER##_INITIAL_TRACE_LEVEL, LOG_LOCAL_LEVEL_MAPPING) >= BT_TRACE_LEVEL_##LEVEL)
+3 -1
View File
@@ -458,10 +458,12 @@ config BT_LE_LL_DUP_SCAN_LIST_COUNT
config BT_LE_LL_SCA
int "BLE Sleep clock accuracy"
range 0 500
range 0 3000
default 60
help
Sleep clock accuracy of our device (in ppm)
The Bluetooth LE spec requires a Sleep Clock Accuracy (SCA) of < ±500 ppm.
This options allows for a larger value to enable the use of less accurate clock sources.
config BT_LE_LL_PEER_SCA_SET_ENABLE
bool "Enable to set constant peer SCA"
+1 -1
View File
@@ -575,7 +575,7 @@ struct ext_funcs_t ext_funcs_ro = {
._esp_intr_alloc = esp_intr_alloc_wrapper,
._esp_intr_free = esp_intr_free_wrapper,
._malloc = bt_osi_mem_malloc_internal,
._free = bt_osi_mem_free,
._free = bt_osi_mem_free_internal,
._task_create = task_create_wrapper,
._task_delete = task_delete_wrapper,
._osi_assert = osi_assert_wrapper,
+3 -1
View File
@@ -511,10 +511,12 @@ config BT_LE_LL_DUP_SCAN_LIST_COUNT
config BT_LE_LL_SCA
int "BLE Sleep clock accuracy"
range 0 500
range 0 3000
default 60
help
Sleep clock accuracy of our device (in ppm)
The Bluetooth LE spec requires a Sleep Clock Accuracy (SCA) of < ±500 ppm.
This options allows for a larger value to enable the use of less accurate clock sources.
config BT_LE_LL_PEER_SCA_SET_ENABLE
bool "Enable to set constant peer SCA"
+1 -1
View File
@@ -537,7 +537,7 @@ struct ext_funcs_t ext_funcs_ro = {
._esp_intr_alloc = esp_intr_alloc_wrapper,
._esp_intr_free = esp_intr_free_wrapper,
._malloc = bt_osi_mem_malloc_internal,
._free = bt_osi_mem_free,
._free = bt_osi_mem_free_internal,
._task_create = task_create_wrapper,
._task_delete = task_delete_wrapper,
._osi_assert = osi_assert_wrapper,
+3 -1
View File
@@ -552,10 +552,12 @@ config BT_LE_LL_DUP_SCAN_LIST_COUNT
config BT_LE_LL_SCA
int "BLE Sleep clock accuracy"
range 0 500
range 0 3000
default 60
help
Sleep clock accuracy of our device (in ppm)
The Bluetooth LE spec requires a Sleep Clock Accuracy (SCA) of < ±500 ppm.
This options allows for a larger value to enable the use of less accurate clock sources.
config BT_LE_LL_PEER_SCA_SET_ENABLE
bool "Enable to set constant peer SCA"
+1 -1
View File
@@ -553,7 +553,7 @@ struct ext_funcs_t ext_funcs_ro = {
._esp_intr_alloc = esp_intr_alloc_wrapper,
._esp_intr_free = esp_intr_free_wrapper,
._malloc = bt_osi_mem_malloc_internal,
._free = bt_osi_mem_free,
._free = bt_osi_mem_free_internal,
._task_create = task_create_wrapper,
._task_delete = task_delete_wrapper,
._osi_assert = osi_assert_wrapper,
+3 -1
View File
@@ -546,10 +546,12 @@ config BT_LE_LL_DUP_SCAN_LIST_COUNT
config BT_LE_LL_SCA
int "BLE Sleep clock accuracy"
range 0 500
range 0 3000
default 60
help
Sleep clock accuracy of our device (in ppm)
The Bluetooth LE spec requires a Sleep Clock Accuracy (SCA) of < ±500 ppm.
This options allows for a larger value to enable the use of less accurate clock sources.
config BT_LE_LL_PEER_SCA_SET_ENABLE
bool "Enable to set constant peer SCA"
+1 -1
View File
@@ -545,7 +545,7 @@ struct ext_funcs_t ext_funcs_ro = {
._esp_intr_alloc = esp_intr_alloc_wrapper,
._esp_intr_free = esp_intr_free_wrapper,
._malloc = bt_osi_mem_malloc_internal,
._free = bt_osi_mem_free,
._free = bt_osi_mem_free_internal,
._task_create = task_create_wrapper,
._task_delete = task_delete_wrapper,
._osi_assert = osi_assert_wrapper,
+205 -2
View File
@@ -1644,11 +1644,13 @@ if BLE_MESH
Enable support for Lighting server models.
config BLE_MESH_MBT_CLI
bool "BLOB Transfer Client model"
bool "BLOB Transfer Client model(Deprecated)"
depends on BLE_MESH_V11_SUPPORT
default n
help
Enable support for BLOB Transfer Client model.
Warn: This version of the Mesh Binary Large Object Transfer Model will be deprecated,
and a new version will be released in the future.
if BLE_MESH_MBT_CLI
@@ -1663,11 +1665,212 @@ if BLE_MESH
endif # BLE_MESH_MBT_CLI
config BLE_MESH_MBT_SRV
bool "BLOB Transfer Server model"
bool "BLOB Transfer Server model(Deprecated)"
depends on BLE_MESH_V11_SUPPORT
default n
help
Enable support for BLOB Transfer Server model.
Warn: This version of the Mesh Binary Large Object Transfer Model will be deprecated,
and a new version will be released in the future.
menu "Binary Larger Object Transfer model"
config BLE_MESH_BLOB_SRV
bool "Support for BLOB Transfer Server model"
depends on BLE_MESH_V11_SUPPORT
help
Enable the Binary Large Object (BLOB) Transfer Server model.
if BLE_MESH_BLOB_SRV
config BLE_MESH_BLOB_SRV_PULL_REQ_COUNT
int "Number of chunks to request for each pull"
default 4
range 1 16
help
In Pull mode (Pull BLOB Transfer Mode), the BLOB Transfer Server
requests a fixed number of chunks from the Client. Use this option to
control the chunk count in the request. If the BLOB Transfer Server
is instantiated on a Low Power node, the pull request count will be
trimmed to not overflow the Friend queue.
config BLE_MESH_BLOB_SIZE_MAX
int "Largest BLOB size in bytes"
default 524288
range 1 3257617792
help
The maximum object size a BLOB Transfer Server can receive.
config BLE_MESH_BLOB_BLOCK_SIZE_MIN
int "Minimum block size"
default 4096
range 64 1048576 # 2^6 - 2^20
help
Minimum acceptable block size in a BLOB transfer. The transfer block
size will be some number that is a power of two, and is between block
size min and block size max. If no such number exists, a compile
time warning will be issued.
config BLE_MESH_BLOB_BLOCK_SIZE_MAX
int "Maximum block size"
default 4096
range BLE_MESH_BLOB_BLOCK_SIZE_MIN 1048576
help
Maximum acceptable block size in a BLOB transfer. The transfer block
size will be some number that is a power of two, and is between block
size min and block size max. If no such number exists, a compile
time warning will be issued.
config BLE_MESH_BLOB_REPORT_TIMEOUT
int "Partial Block Report interval in Pull mode"
default 10
range 1 31
help
The timer value that Pull BLOB Transfer Server uses to report missed chunks.
config BLE_MESH_RX_BLOB_CHUNK_SIZE
depends on !BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT
int "BLOB Server chunk size"
default 8
range 8 377
help
Set the chunk size for the BLOB Server.
The actual maximum chunk size depends on how many segments are
possible and will be clamped to the max possible if set above.
see also: BLE_MESH_RX_SEG_MAX,
and the maximum SDU a node can receive.
endif # BLE_MESH_BLOB_SRV
config BLE_MESH_BLOB_CLI
bool "Support for BLOB Transfer Client model"
depends on BLE_MESH_V11_SUPPORT
help
Enable the Binary Large Object (BLOB) Transfer Client model.
if BLE_MESH_BLOB_CLI
config BLE_MESH_BLOB_CLI_BLOCK_RETRIES
int "Number of retries per block"
default 5
help
Controls the number of times the client will attempt to resend missing
chunks to the BLOB receivers for every block.
config BLE_MESH_TX_BLOB_CHUNK_SIZE
depends on !BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT
int "BLOB Client chunk size"
default 8
range 1 377
help
Set the chunk size for the BLOB Client.
The actual maximum chunk size depends on how many segments are
possible and will be clamped to the max possible if set above.
see also: BLE_MESH_TX_SEG_MAX,
and the maximum SDU a node can receive.
config BLE_MESH_TX_BLOB_CHUNK_SEND_INTERVAL
int "BLOB Client chunk send interval"
default 0
range 0 2147483647
help
Set the interval in milliseconds in which chunks are sent during the BLOB transfer.
Note: Without a delay between each sent chunk, the network might become too busy with the
BLOB transfer for other communications to succeed.
Note: Timing restrictions, like the timeout base, should be considered or changed
accordingly when setting this interval. Otherwise, the interval might be too big for the
timeout settings and cause timeouts.
endif # BLE_MESH_BLOB_CLI
menu "BLOB models common configuration"
visible if BLE_MESH_BLOB_SRV || BLE_MESH_BLOB_CLI
config BLE_MESH_BLOB_CHUNK_COUNT_MAX
int "Maximum chunk count per block"
default 256
range 1 2992
help
A BLOB transfer contains several blocks. Each block is made up of
several chunks. This option controls the maximum chunk count per
block.
config BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT
bool "Align chunk size to max segmented message size"
default y
endmenu #BLOB models common configuration
endmenu # Binary Larger Object Transfer model
menu "Device Firmware Update model"
config BLE_MESH_DFU_SRV
bool "Support for Firmware Update Server model"
depends on BLE_MESH_BLOB_SRV
help
Enable the Firmware Update Server model.
config BLE_MESH_DFU_CLI
bool "Support for Firmware Update Client model"
depends on BLE_MESH_BLOB_CLI
help
Enable the Firmware Update Client model.
menu "Firmware Update model configuration"
visible if BLE_MESH_DFU_SRV || BLE_MESH_DFU_CLI
config BLE_MESH_DFU_FWID_MAXLEN
int "DFU FWID max length"
default 16
range 0 106
help
This value defines the maximum length of an image's firmware ID.
config BLE_MESH_DFU_METADATA_MAXLEN
int "DFU metadata max length"
default 32
range 18 255 if BLE_MESH_DFU_METADATA
range 0 255
help
This value defines the maximum length of an image's metadata.
config BLE_MESH_DFU_METADATA
bool "Support for the default metadata format"
help
This option adds a set of functions that can be used to encode and decode a firmware
metadata using the format defined in the Bluetooth mesh DFU subsystem.
config BLE_MESH_DFU_URI_MAXLEN
int "DFU URI max length"
default 32
range 0 255
help
This value defines the maximum length of an image's URI, not including
a string terminator.
endmenu #Firmware Update model configuration
config BLE_MESH_DFU_SLOTS
bool "Firmware image slot manager"
default y if BLE_MESH_DFU_CLI
help
Enable the DFU image slot manager, for managing firmware distribution slots
for the Firmware Update Client model.
if BLE_MESH_DFU_SLOTS
config BLE_MESH_DFU_SLOT_CNT
int "Number of firmware image slots"
default 1
range 1 32767
help
This value defines the number of firmware slots the DFU image slot manager
can keep simultaneously.
endif #BLE_MESH_DFU_SLOTS
endmenu # Device Firmware Update model
endmenu #Support for BLE Mesh Client/Server models
@@ -1982,8 +1982,12 @@ typedef union {
#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f
#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV 0x1310
#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311
#define ESP_BLE_MESH_MODEL_ID_MBT_SRV 0x1400
#define ESP_BLE_MESH_MODEL_ID_MBT_CLI 0x1401
#define ESP_BLE_MESH_MODEL_ID_MBT_SRV 0x14fe
#define ESP_BLE_MESH_MODEL_ID_MBT_CLI 0x14ff
#define ESP_BLE_MESH_MODEL_ID_BLOB_SRV 0x1400
#define ESP_BLE_MESH_MODEL_ID_BLOB_CLI 0x1401
#define ESP_BLE_MESH_MODEL_ID_DFU_SRV 0x1402
#define ESP_BLE_MESH_MODEL_ID_DFU_CLI 0x1403
/**
* esp_ble_mesh_opcode_config_client_get_t belongs to esp_ble_mesh_opcode_t, this typedef is only
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1410,6 +1410,23 @@ typedef bt_mesh_client_user_data_t bt_mesh_mbt_client_t;
extern const struct bt_mesh_model_op bt_mesh_mbt_cli_op[];
extern const struct bt_mesh_model_cb bt_mesh_mbt_cli_cb;
#endif /* CONFIG_BLE_MESH_MBT_CLI */
#if CONFIG_BLE_MESH_BLOB_SRV
extern const struct bt_mesh_model_op _bt_mesh_blob_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_srv_cb;
#endif /* CONFIG_BLE_MESH_BLOB_SRV */
#if CONFIG_BLE_MESH_BLOB_CLI
typedef bt_mesh_client_user_data_t bt_mesh_blob_client_t;
extern const struct bt_mesh_model_op _bt_mesh_blob_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_cli_cb;
#endif /* CONFIG_BLE_MESH_BLOB_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
extern const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb;
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#if CONFIG_BLE_MESH_DFU_CLI
extern const struct bt_mesh_model_op _bt_mesh_dfu_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfu_cli_cb;
#endif /* CONFIG_BLE_MESH_DFU_CLI */
static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
{
@@ -2205,9 +2222,9 @@ static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
case BLE_MESH_MODEL_ID_MBT_CLI:
model->op = (esp_ble_mesh_model_op_t *)bt_mesh_mbt_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&bt_mesh_mbt_cli_cb;
bt_mesh_mbt_client_t *cli = (bt_mesh_mbt_client_t *)model->user_data;
if (cli) {
cli->publish_status = btc_ble_mesh_mbt_client_publish_callback;
bt_mesh_mbt_client_t *mbt_cli = (bt_mesh_mbt_client_t *)model->user_data;
if (mbt_cli) {
mbt_cli->publish_status = btc_ble_mesh_mbt_client_publish_callback;
}
break;
#endif /* CONFIG_BLE_MESH_MBT_CLI */
@@ -2220,6 +2237,43 @@ static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
}
break;
#endif /* CONFIG_BLE_MESH_MBT_SRV */
#if CONFIG_BLE_MESH_BLOB_CLI
case BLE_MESH_MODEL_ID_BLOB_CLI:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_blob_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_blob_cli_cb;
bt_mesh_blob_client_t *blob_cli = (bt_mesh_blob_client_t *)model->user_data;
if (blob_cli) {
/* TBD: do we need publish callback for Blob Transfer Client model? */
}
break;
#endif /* CONFIG_BLE_MESH_BLOB_CLI */
#if CONFIG_BLE_MESH_BLOB_SRV
case BLE_MESH_MODEL_ID_BLOB_SRV:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_blob_srv_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_blob_srv_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_BLOB_SRV */
#if CONFIG_BLE_MESH_DFU_CLI
case BLE_MESH_MODEL_ID_DFU_CLI:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_dfu_cli_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_dfu_cli_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
case BLE_MESH_MODEL_ID_DFU_SRV:
model->op = (esp_ble_mesh_model_op_t *)_bt_mesh_dfu_srv_op;
model->cb = (esp_ble_mesh_model_cbs_t *)&_bt_mesh_dfu_srv_cb;
if (model->pub) {
model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update;
}
break;
#endif /* CONFIG_BLE_MESH_DFU_SRV */
default:
goto set_vnd_op;
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -32,6 +32,27 @@ static inline void btc_ble_mesh_set_client_common_param(esp_ble_mesh_client_comm
output->ctx.send_cred = input->ctx.send_cred;
output->ctx.send_tag = input->ctx.send_tag;
output->msg_timeout = input->msg_timeout;
if (input->ctx.enh.adv_cfg_used) {
output->ctx.enh.adv_cfg_used = input->ctx.enh.adv_cfg_used;
output->ctx.enh.adv_cfg.adv_cnt = input->ctx.enh.adv_cfg.adv_cnt;
output->ctx.enh.adv_cfg.adv_itvl = input->ctx.enh.adv_cfg.adv_itvl;
output->ctx.enh.adv_cfg.channel_map = input->ctx.enh.adv_cfg.channel_map;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (input->ctx.enh.ext_adv_cfg_used) {
output->ctx.enh.ext_adv_cfg_used = input->ctx.enh.ext_adv_cfg_used;
output->ctx.enh.ext_adv_cfg.primary_phy = input->ctx.enh.ext_adv_cfg.primary_phy;
output->ctx.enh.ext_adv_cfg.secondary_phy = input->ctx.enh.ext_adv_cfg.secondary_phy;
output->ctx.enh.ext_adv_cfg.include_tx_power = input->ctx.enh.ext_adv_cfg.include_tx_power;
output->ctx.enh.ext_adv_cfg.tx_power = input->ctx.enh.ext_adv_cfg.tx_power;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (input->ctx.enh.long_pkt_cfg_used) {
output->ctx.enh.long_pkt_cfg_used = input->ctx.enh.long_pkt_cfg_used;
output->ctx.enh.long_pkt_cfg = input->ctx.enh.long_pkt_cfg;
}
#endif
#endif
}
}
@@ -37,7 +37,7 @@ extern "C" {
#endif
#endif
#define BLE_MESH_ADV_TASK_STACK_SIZE 3072
#define BLE_MESH_ADV_TASK_STACK_SIZE (3072)
#define BLE_MESH_ADV_TASK_NAME "mesh_adv_task"
#define BLE_MESH_ADV_TASK_PRIO (configMAX_PRIORITIES - 5)
@@ -1,6 +1,6 @@
/*
* SPDX-FileCopyrightText: 2016 Wind River Systems, Inc.
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -49,6 +49,8 @@ struct k_work;
*/
typedef void (*k_work_handler_t)(struct k_work *work);
typedef int32_t k_timeout_t;
struct k_work {
k_work_handler_t handler;
int index;
@@ -141,6 +143,65 @@ struct k_work {
*/
#define K_FOREVER (-1)
/**
* @brief Define for delayable work type.
*
* This macro maps the Zephyr delayable work type `k_work_delayable`
* to the ESP-IDF type `k_delayed_work`.
*/
#define k_work_delayable k_delayed_work
/**
* @brief Reschedule a delayable work item.
*
* This macro maps to `k_delayed_work_submit`, which cancels
* any existing pending submission of the work item and reschedules
* it with the new timeout delay.
*
* @param work Pointer to delayable work item.
* @param delay Timeout delay value.
* @return See implementation of `k_delayed_work_submit`.
*/
#define k_work_reschedule k_delayed_work_submit
/**
* @brief Schedule a delayable work item.
*
* This macro maps to `k_delayed_work_submit`,
* which schedules a work item to be processed
* after the specified timeout delay. If the work
* is already pending, the new delay is applied.
*
* @param work Pointer to delayable work item.
* @param delay Timeout delay value.
* @return See implementation of `k_delayed_work_submit`.
*/
#define k_work_schedule k_delayed_work_submit
/**
* @brief Cancel a delayable work item.
*
* This macro maps to `k_delayed_work_cancel`,
* which cancels a pending work submission
* associated with a delayable work item.
*
* @param work Pointer to delayable work item.
* @return See implementation of `k_delayed_work_cancel`.
*/
#define k_work_cancel_delayable k_delayed_work_cancel
/**
* @brief Initialize a delayable work item.
*
* This macro maps to `k_delayed_work_init`,
* which initializes a delayable work item with
* the provided handler function.
*
* @param work Pointer to delayable work item.
* @param handler Work item handler function.
*/
#define k_work_init_delayable k_delayed_work_init
/**
* @brief Get system uptime (32-bit version).
*
@@ -160,6 +221,27 @@ struct k_delayed_work {
struct k_work work;
};
#define _K_DELAYABLE_WORK_INITIALIZER(work_handler) { \
.work = { \
.handler = work_handler, \
}, \
}
/**
* @brief Convert a work item to its containing delayable work structure.
*
* This function uses container_of to derive the address of the containing
* k_work_delayable structure from the address of the embedded k_work structure.
*
* @param work Pointer to the embedded k_work structure within a k_work_delayable.
* @return Pointer to the containing k_work_delayable structure.
*/
static inline struct k_work_delayable *
k_work_delayable_from_work(struct k_work *work)
{
return CONTAINER_OF(work, struct k_work_delayable, work);
}
/**
* @brief Submit a delayed work item to the system workqueue.
*
@@ -209,6 +291,21 @@ int k_delayed_work_submit_periodic(struct k_delayed_work *work, int32_t period);
*/
int32_t k_delayed_work_remaining_get(struct k_delayed_work *work);
/**
* @brief Check if a delayable work item is pending execution.
*
* This function checks whether a delayable work item has been scheduled
* and is waiting to be processed. It returns true if the work item is in
* pending state (waiting for timeout expiration or being in work queue).
*
* @param dwork Pointer to delayable work item.
* @return true if work is pending, false otherwise.
*/
static inline bool k_work_delayable_is_pending(struct k_work_delayable *dwork)
{
return k_delayed_work_remaining_get(dwork);
}
/**
* @brief Submit a work item to the system workqueue.
*
@@ -267,10 +364,45 @@ int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler);
* @return Current uptime.
*/
int64_t k_uptime_get(void);
int64_t k_uptime_delta(int64_t *reftime);
void bt_mesh_timer_init(void);
void bt_mesh_timer_deinit(void);
/**
* @brief Initialize a statically-defined work item.
*
* This macro can be used to initialize a statically-defined workqueue work
* item, prior to its first use. For example,
*
* @code static K_WORK_DEFINE(<work>, <work_handler>); @endcode
*
* @param work Symbol name for work item object
* @param work_handler Function to invoke each time work item is processed.
*/
#define K_WORK_DEFINE(work, work_handler) \
struct k_work work = _K_WORK_INITIALIZER(work_handler)
/**
* @brief Initialize a statically-defined delayable work item.
*
* This macro can be used to initialize a statically-defined delayable
* work item, prior to its first use. For example,
*
* @code static K_WORK_DELAYABLE_DEFINE(<dwork>, <work_handler>); @endcode
*
* Note that if the runtime dependencies support initialization with
* k_work_init_delayable() using that will eliminate the initialized
* object in ROM that is produced by this macro and copied in at
* system startup.
*
* @param work Symbol name for delayable work item object
* @param work_handler Function to invoke each time work item is processed.
*/
#define K_WORK_DELAYABLE_DEFINE(work, work_handler) \
struct k_delayed_work work \
= _K_DELAYABLE_WORK_INITIALIZER(work_handler)
#ifdef __cplusplus
}
#endif
@@ -15,6 +15,8 @@
#define _BLE_MESH_UTILS_H_
#include <stddef.h>
#include <sys/cdefs.h>
#include <errno.h>
#include "esp_bit_defs.h"
#include "mesh/types.h"
#include "utils_loops.h"
@@ -94,6 +96,81 @@ extern "C" {
#define WB_DN(x) ROUND_DOWN(x, sizeof(void *))
#endif
/**
* @brief Whether @p ptr is an element of @p array
*
* This macro can be seen as a slightly stricter version of @ref PART_OF_ARRAY
* in that it also ensures that @p ptr is aligned to an array-element boundary
* of @p array.
*
* In C, passing a pointer as @p array causes a compile error.
*
* @param array the array in question
* @param ptr the pointer to check
*
* @return 1 if @p ptr is part of @p array, 0 otherwise
*/
#define IS_ARRAY_ELEMENT(array, ptr) \
((ptr) && POINTER_TO_UINT(array) <= POINTER_TO_UINT(ptr) && \
POINTER_TO_UINT(ptr) < POINTER_TO_UINT(&(array)[ARRAY_SIZE(array)]) && \
(POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) % sizeof((array)[0]) == 0)
/**
* @brief Index of @p ptr within @p array
*
* With `CONFIG_ASSERT=y`, this macro will trigger a runtime assertion
* when @p ptr does not fall into the range of @p array or when @p ptr
* is not aligned to an array-element boundary of @p array.
*
* In C, passing a pointer as @p array causes a compile error.
*
* @param array the array in question
* @param ptr pointer to an element of @p array
*
* @return the array index of @p ptr within @p array, on success
*/
#define ARRAY_INDEX(array, ptr) \
({ \
__ASSERT_NO_MSG(IS_ARRAY_ELEMENT(array, ptr)); \
(__typeof__((array)[0]) *)(ptr) - (array); \
})
/**
* @brief Divide and round up.
*
* Example:
* @code{.c}
* DIV_ROUND_UP(1, 2); // 1
* DIV_ROUND_UP(3, 2); // 2
* @endcode
*
* @param n Numerator.
* @param d Denominator.
*
* @return The result of @p n / @p d, rounded up.
*/
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
/**
* @brief Divide and round to the nearest integer.
*
* Example:
* @code{.c}
* DIV_ROUND_CLOSEST(5, 2); // 3
* DIV_ROUND_CLOSEST(5, -2); // -3
* DIV_ROUND_CLOSEST(5, 3); // 2
* @endcode
*
* @param n Numerator.
* @param d Denominator.
*
* @return The result of @p n / @p d, rounded to the nearest integer.
*/
#define DIV_ROUND_CLOSEST(n, d) \
((((n) < 0) ^ ((d) < 0)) ? ((n) - ((d) / 2)) / (d) : \
((n) + ((d) / 2)) / (d))
#ifndef ceiling_fraction
#define ceiling_fraction(numerator, divider) \
(((numerator) + ((divider) - 1)) / (divider))
@@ -125,6 +202,21 @@ extern "C" {
#define BIT(n) (1UL << (n))
#endif
/**
* @brief Set or clear a bit depending on a boolean value
*
* The argument @p var is a variable whose value is written to as a
* side effect.
*
* @param var Variable to be altered
* @param bit Bit number
* @param set if 0, clears @p bit in @p var; any other value sets @p bit
*/
#ifndef WRITE_BIT
#define WRITE_BIT(var, bit, set) \
((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit)))
#endif
#ifndef BIT_MASK
#define BIT_MASK(n) (BIT(n) - 1)
#endif
@@ -219,6 +311,20 @@ const char *bt_hex(const void *buf, size_t len);
void mem_rcopy(uint8_t *dst, uint8_t const *src, uint16_t len);
/**
* @brief Checks if a value is within range.
*
* @note @p val is evaluated twice.
*
* @param val Value to be checked.
* @param min Lower bound (inclusive).
* @param max Upper bound (inclusive).
*
* @retval true If value is within range
* @retval false If the value is not within range
*/
#define IN_RANGE(val, min, max) ((val) >= (min) && (val) <= (max))
#ifdef __cplusplus
}
#endif
+23 -1
View File
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2016 Intel Corporation
* SPDX-FileCopyrightText: 2016 Wind River Systems, Inc.
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -43,6 +43,28 @@ uint32_t k_uptime_get_32(void)
return (uint32_t)(esp_timer_get_time() / 1000);
}
/**
* @brief Get elapsed time.
*
* This routine computes the elapsed time between the current system uptime
* and an earlier reference time, in milliseconds.
*
* @param reftime Pointer to a reference time, which is updated to the current
* uptime upon return.
*
* @return Elapsed time.
*/
int64_t k_uptime_delta(int64_t *reftime)
{
int64_t uptime, delta;
uptime = k_uptime_get();
delta = uptime - *reftime;
*reftime = uptime;
return delta;
}
void bt_mesh_timer_init(void)
{
bm_alarm_hash_map = hash_map_new(BLE_MESH_ALARM_HASH_MAP_SIZE,
+26 -7
View File
@@ -37,7 +37,7 @@
extern const struct bt_mesh_comp *comp_0;
static uint16_t dev_primary_addr;
static int model_send(struct bt_mesh_model *model,
static int model_send(const struct bt_mesh_model *model,
struct bt_mesh_net_tx *tx, bool implicit_bind,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data);
@@ -300,7 +300,7 @@ static void mod_publish(struct k_work *work)
}
}
struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod)
{
return &comp_0->elem[mod->elem_idx];
}
@@ -548,12 +548,31 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
return NULL;
}
bool bt_mesh_has_addr(uint16_t addr)
{
uint16_t index;
if (BLE_MESH_ADDR_IS_UNICAST(addr)) {
return bt_mesh_elem_find(addr) != NULL;
}
for (index = 0; index < comp_0->elem_count; index++) {
struct bt_mesh_elem *elem = &comp_0->elem[index];
if (bt_mesh_elem_find_group(elem, addr)) {
return true;
}
}
return false;
}
uint8_t bt_mesh_elem_count(void)
{
return comp_0->elem_count;
}
static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
static bool model_has_key(const struct bt_mesh_model *mod, uint16_t key)
{
int i;
@@ -635,7 +654,7 @@ static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode, bool pull_bu
if (pull_buf) {
*opcode = net_buf_simple_pull_u8(buf) << 16;
/* Using LE for the CID since the model layer is defined as
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
* little-endian in the mesh spec and using BLE_MESH_MODEL_OP_3
* will declare the opcode in this way.
*/
*opcode |= net_buf_simple_pull_le16(buf);
@@ -793,7 +812,7 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode)
case 3:
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
/* Using LE for the CID since the model layer is defined as
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
* little-endian in the mesh spec and using BLE_MESH_MODEL_OP_3
* will declare the opcode in this way.
*/
net_buf_simple_add_le16(msg, opcode & 0xffff);
@@ -951,7 +970,7 @@ void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx)
}
#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */
static int model_send(struct bt_mesh_model *model,
static int model_send(const struct bt_mesh_model *model,
struct bt_mesh_net_tx *tx, bool implicit_bind,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
@@ -1041,7 +1060,7 @@ int bt_mesh_model_send_implicit(struct bt_mesh_model *model,
return model_send(model, &tx, implicit_bind, msg, cb, cb_data);
}
int bt_mesh_model_send(struct bt_mesh_model *model,
int bt_mesh_model_send(const struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
+2
View File
@@ -29,6 +29,8 @@ uint8_t bt_mesh_elem_count(void);
/* Find local element based on unicast or group address */
struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr);
bool bt_mesh_has_addr(uint16_t addr);
uint16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, uint16_t addr);
int bt_mesh_get_opcode(struct net_buf_simple *buf,
+4 -4
View File
@@ -362,6 +362,10 @@ void bt_mesh_adv_update(void)
void bt_mesh_adv_init(void)
{
bt_mesh_adv_common_init();
adv_queue = bt_mesh_adv_queue_get();
assert(adv_queue && adv_queue->q.handle && adv_queue->send);
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
bt_mesh_relay_adv_init();
@@ -370,10 +374,6 @@ void bt_mesh_adv_init(void)
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
bt_mesh_ble_adv_init();
#endif
bt_mesh_adv_common_init();
adv_queue = bt_mesh_adv_queue_get();
assert(adv_queue && adv_queue->q.handle && adv_queue->send);
#if CONFIG_BLE_MESH_RELAY_ADV_BUF && !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
QueueHandle_t relay_adv_handle =
+8 -2
View File
@@ -748,6 +748,12 @@ uint16_t ble_mesh_adv_buf_count_get(void)
adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT;
#endif
#endif
#if (CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \
!(CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE))
adv_count += CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT;
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
return adv_count;
}
@@ -822,13 +828,13 @@ void bt_mesh_adv_common_init(void)
#if CONFIG_BLE_MESH_EXT_ADV
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_PROV);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_DATA);
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
#if CONFIG_BLE_MESH_RELAY && !CONFIG_BLE_MESH_RELAY_ADV_BUF
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA);
#endif
#if CONFIG_BLE_MESH_LONG_PACKET
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_PROV);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_DATA);
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
#if CONFIG_BLE_MESH_RELAY && !CONFIG_BLE_MESH_RELAY_ADV_BUF
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
+29 -10
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,8 +15,12 @@
#include "mesh/buf.h"
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
/* Use independent ble adv queue only if multi adv instance is used */
static struct bt_mesh_adv_queue ble_adv_queue;
static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
#endif
static struct bt_mesh_adv_queue *p_ble_adv_queue;
#define BLE_MESH_BLE_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1)
/* length + advertising data + length + scan response data */
NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT,
@@ -28,8 +32,6 @@ static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
#define SEND_BLE_ADV_INFINITE 0xFFFF
static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
static struct bt_mesh_adv *ble_adv_alloc(int id, enum bt_mesh_adv_type type)
{
memset(&ble_adv_pool[id], 0, sizeof(struct bt_mesh_adv));
@@ -37,27 +39,30 @@ static struct bt_mesh_adv *ble_adv_alloc(int id, enum bt_mesh_adv_type type)
return &ble_adv_pool[id];
}
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
/* A separate post function is required only when using a separate queue */
static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
{
BT_DBG("%s", __func__);
if (ble_adv_queue.q.handle == NULL) {
if (p_ble_adv_queue->q.handle == NULL) {
BT_ERR("Invalid adv queue");
return;
}
if (front) {
if (xQueueSendToFront(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) {
if (xQueueSendToFront(p_ble_adv_queue->q.handle, msg, timeout) != pdTRUE) {
BT_ERR("Failed to send item to adv queue front");
bt_mesh_unref_buf(msg);
}
} else {
if (xQueueSend(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) {
if (xQueueSend(p_ble_adv_queue->q.handle, msg, timeout) != pdTRUE) {
BT_ERR("Failed to send item to adv queue back");
bt_mesh_unref_buf(msg);
}
}
}
#endif
static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout)
{
@@ -282,10 +287,20 @@ int bt_mesh_stop_ble_advertising(uint8_t index)
return 0;
}
struct bt_mesh_adv_queue *bt_mesh_ble_adv_queue_get(void)
{
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
bt_mesh_adv_queue_init(&ble_adv_queue, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, bt_mesh_ble_task_post);
return &ble_adv_queue;
#else
return bt_mesh_adv_queue_get();
#endif
}
void bt_mesh_ble_adv_init(void)
{
bt_mesh_adv_queue_init(&ble_adv_queue, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, bt_mesh_ble_task_post);
bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, &ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc);
p_ble_adv_queue = bt_mesh_ble_adv_queue_get();
bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, p_ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc);
#if CONFIG_BLE_MESH_USE_BLE_50
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INS, CONFIG_BLE_MESH_BLE_ADV_INST_ID);
@@ -308,7 +323,11 @@ void bt_mesh_ble_adv_deinit(void)
bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool);
memset(ble_adv_pool, 0, sizeof(ble_adv_pool));
bt_mesh_adv_queue_deinit(&ble_adv_queue);
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
/* In other cases, ble_adv queue is an adv queue,
* so ble does not need to deinit separately */
bt_mesh_adv_queue_deinit(p_ble_adv_queue);
#endif
bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE);
#if CONFIG_BLE_MESH_USE_BLE_50
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
@@ -929,20 +929,6 @@ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id,
tBTA_DM_BLE_EXT_ADV ext_adv = {0};
struct bt_mesh_hci_cp_set_adv_data set = {0};
if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
if (data->adv_data_len) {
set.len = data->adv_data_len;
memcpy(set.data, data->adv_data, data->adv_data_len);
BTA_DmBleGapConfigExtAdvDataRaw(false, inst_id, set.len, set.data);
}
if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) {
set.len = data->scan_rsp_data_len;
memcpy(set.data, data->scan_rsp_data, data->scan_rsp_data_len);
BTA_DmBleGapConfigExtAdvDataRaw(true, inst_id, set.len, set.data);
}
}
switch (param->adv_type) {
case BLE_MESH_ADV_IND:
case BLE_MESH_ADV_DIRECT_IND:
@@ -983,6 +969,20 @@ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id,
/* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */
BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params);
if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
if (data->adv_data_len) {
set.len = data->adv_data_len;
memcpy(set.data, data->adv_data, data->adv_data_len);
BTA_DmBleGapConfigExtAdvDataRaw(false, inst_id, set.len, set.data);
}
if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) {
set.len = data->scan_rsp_data_len;
memcpy(set.data, data->scan_rsp_data, data->scan_rsp_data_len);
BTA_DmBleGapConfigExtAdvDataRaw(true, inst_id, set.len, set.data);
}
}
BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv);
#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
@@ -14,6 +14,7 @@
#include "mesh/config.h"
#include "mesh/buf.h"
#include "mesh/timer.h"
#include "sys/types.h"
/**
* @brief Bluetooth Mesh Access Layer
@@ -151,8 +152,15 @@ struct bt_mesh_elem {
#define BLE_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f
#define BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV 0x1310
#define BLE_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311
#define BLE_MESH_MODEL_ID_MBT_SRV 0x1400
#define BLE_MESH_MODEL_ID_MBT_CLI 0x1401
#define BLE_MESH_MODEL_ID_BLOB_SRV 0x1400
#define BLE_MESH_MODEL_ID_BLOB_CLI 0x1401
#define BLE_MESH_MODEL_ID_DFU_SRV 0x1402
#define BLE_MESH_MODEL_ID_DFU_CLI 0x1403
#define BLE_MESH_MODEL_ID_DFD_SRV 0x1404
#define BLE_MESH_MODEL_ID_DFD_CLI 0x1405
#define BLE_MESH_MODEL_ID_MBT_SRV BLE_MESH_MODEL_ID_BLOB_SRV
#define BLE_MESH_MODEL_ID_MBT_CLI BLE_MESH_MODEL_ID_BLOB_CLI
typedef struct {
uint32_t adv_itvl;
@@ -520,6 +528,8 @@ struct bt_mesh_model_pub {
.update = _update, \
}
typedef ssize_t (*settings_read_cb)(void *cb_arg, void *data, size_t len);
/** Model callback functions. */
struct bt_mesh_model_cb {
/** @brief Model init callback.
@@ -613,7 +623,7 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode);
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_model_send(struct bt_mesh_model *model,
int bt_mesh_model_send(const struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb,
@@ -642,7 +652,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model);
*
* @return Pointer to the element that the given model belongs to.
*/
struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod);
/** @brief Find a SIG model.
*
+3
View File
@@ -430,6 +430,9 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt)
#endif
adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND &&
adv_rpt->adv_type != BLE_MESH_ADV_IND
#if CONFIG_BLE_MESH_EXT_ADV
&& adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND
#endif
#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
&& adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP
#endif
@@ -1,6 +1,6 @@
/*
* SPDX-FileCopyrightText: 2018 Intel Corporation
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -45,10 +45,12 @@
* key: "mesh/s/xxxx/b" -> write/read to set/get SIG MODEL Bind AppKey List
* key: "mesh/s/xxxx/s" -> write/read to set/get SIG MODEL Subscription List
* key: "mesh/s/xxxx/p" -> write/read to set/get SIG MODEL Publication
* key: "mesh/s/xxxx/d" -> write/read to set/get SIG MODEL Data
* key: "mesh/vnd" -> write/read to set/get all VENDOR MODEL model_keys.
* key: "mesh/v/xxxx/b" -> write/read to set/get VENDOR MODEL Bind AppKey List
* key: "mesh/v/xxxx/s" -> write/read to set/get VENDOR MODEL Subscription List
* key: "mesh/v/xxxx/p" -> write/read to set/get VENDOR MODEL Publication
* key: "mesh/v/xxxx/d" -> write/read to set/get VENDOR MODEL Data
* key: "mesh/vaddr" -> write/read to set/get all virtual addresses
* key: "mesh/va/xxxx" -> write/read to set/get the "xxxx" virtual address
* key: "mesh/dkca" -> write/read to set/get Device Key Candidate
@@ -2731,3 +2733,40 @@ void bt_mesh_settings_reset(bool erase)
}
#endif /* CONFIG_BLE_MESH_SETTINGS */
#define SETTINGS_MAX_DIR_DEPTH 8
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
const char *name, const void *data,
size_t data_len)
{
int err = 0;
char path[30] = {'\0'};
uint16_t model_key = 0U;
model_key = BLE_MESH_GET_MODEL_KEY(mod->elem_idx, mod->model_idx);
sprintf(path, "mesh/%s/%04x/d", vnd ? "v" : "s", model_key);
if (name) {
strcat(path, "/");
strncat(path, name, SETTINGS_MAX_DIR_DEPTH);
}
if (data_len) {
err = bt_mesh_save_core_settings(path, data, data_len);
if (err) {
BT_ERR("Failed to store %s", path);
return err;
}
err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key);
if (err) {
BT_ERR("Failed to add model data to %s, model_key 0x%04x",
vnd ? "mesh/vnd" : "mesh/sig", model_key);
}
} else {
bt_mesh_erase_core_settings(path);
bt_mesh_remove_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key);
}
return err;
}
@@ -35,6 +35,10 @@ void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
void bt_mesh_store_label(void);
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
const char *name, const void *data,
size_t data_len);
void bt_mesh_clear_role(void);
void bt_mesh_clear_net(void);
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+11 -8
View File
@@ -800,16 +800,19 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (tx->ctx->enh.long_pkt_cfg_used == true &&
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER) &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
if (tx->ctx->enh.long_pkt_cfg_used == true) {
if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
}
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
@@ -1151,11 +1151,14 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (tx->ctx->enh.long_pkt_cfg_used == true &&
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER) &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
if (tx->ctx->enh.long_pkt_cfg_used == true) {
if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
@@ -11,6 +11,7 @@
#define _TRANSPORT_H_
#include "net.h"
#include "access.h"
#ifdef __cplusplus
extern "C" {
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -183,12 +183,28 @@ static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
{
int32_t seg_rtx_to = 0, duration = 0, time = 0;
uint8_t seg_count = 0, seg_rtx_num = 0;
bool need_seg = false;
bool need_seg = bt_mesh_tag_send_segmented(ctx->send_tag);
uint8_t mic_size = 0;
if (msg->len > BLE_MESH_SDU_UNSEG_MAX ||
bt_mesh_tag_send_segmented(ctx->send_tag)) {
need_seg = true; /* Needs segmentation */
if (!need_seg) {
#if CONFIG_BLE_MESH_LONG_PACKET
if (ctx->enh.long_pkt_cfg_used == true) {
if ((ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) ||
(ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
msg->len > BLE_MESH_SDU_UNSEG_MAX)) {
need_seg = true; /* Needs segmentation */
}
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
need_seg = true; /* Needs segmentation */
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
need_seg = true; /* Needs segmentation */
}
#endif
}
mic_size = (need_seg && ctx->send_szmic == BLE_MESH_SEG_SZMIC_LONG &&
@@ -0,0 +1,148 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "btc/btc_manage.h"
#include "btc_ble_mesh_dfu_model.h"
#include "esp_ble_mesh_dfu_model_api.h"
#if CONFIG_BLE_MESH_DFU_CLI
static bool is_get_param_needed(esp_ble_mesh_opcode_t opcode)
{
switch (opcode) {
case ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET:
case ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK:
case ESP_BLE_MESH_DFU_OP_UPDATE_START:
return true;
default:
return false;
}
}
esp_err_t esp_ble_mesh_dfu_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_dfu_client_get_t *get)
{
btc_ble_mesh_dfu_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(params->ctx.addr) ||
(is_get_param_needed(params->opcode) && get == NULL)) {
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_DFU_CLIENT;
msg.act = BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE;
arg.dfu_get.params = params;
arg.dfu_get.get = get;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfu_client_args_t),
btc_ble_mesh_dfu_client_arg_deep_copy,
btc_ble_mesh_dfu_client_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_dfu_cli_img_send(esp_ble_mesh_dfu_cli_t *cli,
esp_ble_mesh_blob_cli_inputs_t *inputs,
esp_ble_mesh_blob_io_t *io,
esp_ble_mesh_dfu_cli_xfer_t *xfer)
{
btc_ble_mesh_dfu_client_args_t arg = {0};
btc_msg_t msg = {0};
if (cli == NULL || inputs == NULL ||
io == NULL || xfer == NULL) {
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_DFU_CLIENT;
msg.act = BTC_BLE_MESH_ACT_DFU_CLIENT_IMG_SEND;
arg.send_arg.cli = cli;
arg.send_arg.inputs = inputs;
arg.send_arg.io = io;
arg.send_arg.xfer = xfer;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfu_client_args_t),
NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
uint8_t esp_ble_mesh_dfu_cli_progress(esp_ble_mesh_dfu_cli_t *cli)
{
if (!cli) {
return 0;
}
return btc_ble_mesh_dfu_cli_progress(cli);
}
esp_err_t esp_ble_mesh_register_dfu_client_callback(esp_ble_mesh_dfu_client_cb_t callback)
{
return (btc_profile_cb_set(BTC_PID_DFU_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
void esp_ble_mesh_dfu_srv_verified(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_verified(srv);
}
void esp_ble_mesh_dfu_srv_rejected(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_rejected(srv);
}
void esp_ble_mesh_dfu_srv_cancel(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_cancel(srv);
}
void esp_ble_mesh_dfu_srv_applied(esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return;
}
btc_ble_mesh_dfu_srv_applied(srv);
}
bool esp_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return false;
}
return btc_ble_mesh_dfu_srv_is_busy(srv);
}
uint8_t esp_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv)
{
if (!srv) {
return 0;
}
return btc_ble_mesh_dfu_srv_progress(srv);
}
#endif /* CONFIG_BLE_MESH_DFU_SRV */
@@ -0,0 +1,102 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_ble_mesh_dfu_slot_api.h"
#include "btc_ble_mesh_dfu_slot.h"
int esp_ble_mesh_dfu_slot_count(void)
{
return btc_ble_mesh_dfu_slot_count();
}
esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_reserve(void)
{
return btc_ble_mesh_dfu_slot_reserve();
}
int esp_ble_mesh_dfu_slot_info_set(esp_ble_mesh_dfu_slot_t *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len)
{
if (!dfu_slot || !metadata ||
metadata_len == 0 ||
metadata_len > CONFIG_BLE_MESH_DFU_METADATA_MAXLEN) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_info_set(dfu_slot, size,
metadata, metadata_len);
}
int esp_ble_mesh_dfu_slot_fwid_set(esp_ble_mesh_dfu_slot_t *dfu_slot,
const uint8_t *fwid, size_t fwid_len)
{
if (!dfu_slot || !fwid || fwid_len == 0 ||
fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_fwid_set(dfu_slot, fwid,
fwid_len);
}
int esp_ble_mesh_dfu_slot_commit(esp_ble_mesh_dfu_slot_t *dfu_slot)
{
if (!dfu_slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_commit(dfu_slot);
}
void esp_ble_mesh_dfu_slot_release(const esp_ble_mesh_dfu_slot_t *dfu_slot)
{
if (!dfu_slot) {
return;
}
btc_ble_mesh_dfu_slot_release(dfu_slot);
}
int esp_ble_mesh_dfu_slot_del(const esp_ble_mesh_dfu_slot_t *slot)
{
if (!slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_del(slot);
}
void esp_ble_mesh_dfu_slot_del_all(void)
{
btc_ble_mesh_dfu_slot_del_all();
}
const esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_at(uint16_t img_idx)
{
return btc_ble_mesh_dfu_slot_at(img_idx);
}
int esp_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, esp_ble_mesh_dfu_slot_t **slot)
{
if (!fwid || fwid_len == 0 ||
fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN ||
!slot || !*slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_get(fwid, fwid_len, slot);
}
int esp_ble_mesh_dfu_slot_img_idx_get(const esp_ble_mesh_dfu_slot_t *slot)
{
if (!slot) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_dfu_slot_img_idx_get(slot);
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,20 +20,20 @@ extern int bt_mesh_get_transfer_progress(void *model, uint16_t unicast_addr,
uint8_t *block_percent, uint8_t *chunk_percent);
extern int bt_mesh_get_blob_reception_progress(void *model, uint8_t *reception_progress);
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback)
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback) __attribute__((deprecated))
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_MBT_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input)
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL)) {
(input->unicast_addr_count && input->unicast_addr == NULL)) {
return ESP_ERR_INVALID_ARG;
}
@@ -51,14 +51,14 @@ esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_ca
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input)
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL) ||
input->blob_data == NULL) {
(input->unicast_addr_count && input->unicast_addr == NULL) ||
input->blob_data == NULL) {
return ESP_ERR_INVALID_ARG;
}
@@ -76,7 +76,7 @@ esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *in
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input)
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -97,7 +97,7 @@ esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input)
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -118,7 +118,7 @@ esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input)
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -139,13 +139,13 @@ esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input)
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL)) {
(input->unicast_addr_count && input->unicast_addr == NULL)) {
return ESP_ERR_INVALID_ARG;
}
@@ -163,13 +163,13 @@ esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determi
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input)
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
if (input == NULL || input->model == NULL ||
(input->unicast_addr_count && input->unicast_addr == NULL)) {
(input->unicast_addr_count && input->unicast_addr == NULL)) {
return ESP_ERR_INVALID_ARG;
}
@@ -188,13 +188,13 @@ esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t
}
const esp_ble_mesh_blob_receiver_t *esp_ble_mesh_mbt_client_get_blob_receiver(esp_ble_mesh_model_t *model,
uint16_t unicast_addr)
uint16_t unicast_addr) __attribute__((deprecated))
{
return (const esp_ble_mesh_blob_receiver_t *)bt_mesh_get_blob_receiver((struct bt_mesh_model *)model,
unicast_addr);
}
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model)
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
return (const esp_ble_mesh_blob_receiver_t **)bt_mesh_get_active_blob_receiver((struct bt_mesh_model *)model);
}
@@ -202,14 +202,14 @@ const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_rec
esp_err_t esp_ble_mesh_mbt_client_get_transfer_progress(esp_ble_mesh_model_t *model,
uint16_t unicast_addr,
uint8_t *block_percent,
uint8_t *chunk_percent)
uint8_t *chunk_percent) __attribute__((deprecated))
{
return (bt_mesh_get_transfer_progress((struct bt_mesh_model *)model, unicast_addr,
block_percent, chunk_percent) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_set_transfer_ttl(esp_ble_mesh_model_t *model,
uint8_t transfer_ttl)
uint8_t transfer_ttl) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -231,7 +231,7 @@ esp_err_t esp_ble_mesh_mbt_client_set_transfer_ttl(esp_ble_mesh_model_t *model,
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model)
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -253,7 +253,7 @@ esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model
}
esp_err_t esp_ble_mesh_mbt_client_set_app_idx(esp_ble_mesh_model_t *model,
uint16_t app_idx)
uint16_t app_idx) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -275,7 +275,7 @@ esp_err_t esp_ble_mesh_mbt_client_set_app_idx(esp_ble_mesh_model_t *model,
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model)
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -297,7 +297,7 @@ esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model)
}
esp_err_t esp_ble_mesh_mbt_client_set_multicast_addr(esp_ble_mesh_model_t *model,
uint16_t multicast_addr)
uint16_t multicast_addr) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -319,7 +319,7 @@ esp_err_t esp_ble_mesh_mbt_client_set_multicast_addr(esp_ble_mesh_model_t *model
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model)
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model) __attribute__((deprecated))
{
btc_ble_mesh_mbt_client_args_t arg = {0};
btc_msg_t msg = {0};
@@ -342,14 +342,14 @@ esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *mod
#endif /* CONFIG_BLE_MESH_MBT_CLI */
#if CONFIG_BLE_MESH_MBT_SRV
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback)
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback) __attribute__((deprecated))
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_MBT_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input)
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_server_args_t arg = {0};
btc_msg_t msg = {0};
@@ -370,7 +370,7 @@ esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initializ
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input)
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_server_args_t arg = {0};
btc_msg_t msg = {0};
@@ -391,7 +391,7 @@ esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_r
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input)
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input) __attribute__((deprecated))
{
btc_ble_mesh_mbt_server_args_t arg = {0};
btc_msg_t msg = {0};
@@ -413,7 +413,7 @@ esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_ca
}
esp_err_t esp_ble_mesh_mbt_server_get_blob_reception_progress(esp_ble_mesh_model_t *model,
uint8_t *reception_progress)
uint8_t *reception_progress) __attribute__((deprecated))
{
return (bt_mesh_get_blob_reception_progress((struct bt_mesh_model *)model,
reception_progress) == 0 ? ESP_OK : ESP_FAIL);
@@ -0,0 +1,696 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_BLE_MESH_BLOB_MODEL_API_H_
#define _ESP_BLE_MESH_BLOB_MODEL_API_H_
#include "esp_ble_mesh_defs.h"
#include "esp_ble_mesh_blob_model_api.h"
#if CONFIG_BLE_MESH_BLOB_CLI || CONFIG_BLE_MESH_BLOB_SRV
#ifndef _BLE_MESH_BLOB_DEPRECATE_WARN
#define _BLE_MESH_BLOB_DEPRECATE_WARN
#warning Please note: All APIs published in this document are in Preview version and may undergo significant changes in the future.
#endif
#endif /* CONFIG_BLE_MESH_BLOB_CLI || CONFIG_BLE_MESH_BLOB_SRV */
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_BLE_MESH_BLOB_ID_SIZE 8
/** @def ESP_BLE_MESH_MODEL_BLOB_CLI
*
* @brief Define a new BLOB Transfer Client model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Client model.
*
* @param cli_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to the unique struct esp_ble_mesh_client_t.
*
* @return New BLOB Transfer Client model instance.
*/
#define ESP_BLE_MESH_MODEL_BLOB_CLI(cli_pub, cli_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_BLOB_CLI, \
NULL, cli_pub, cli_data)
/** @def ESP_BLE_MESH_MODEL_BLOB_SRV
*
* @brief Define a new BLOB Transfer Server model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Server model.
*
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_blob_trans_srv_t.
*
* @return New BLOB Transfer Server model instance.
*/
#define ESP_BLE_MESH_MODEL_BLOB_SRV(srv_pub, srv_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_BLOB_SRV, \
NULL, srv_pub, srv_data)
/** BLOB stream. */
typedef struct esp_ble_mesh_blob_io esp_ble_mesh_blob_io_t;
/** @brief BLOB Transfer Server instance. */
typedef struct esp_ble_mesh_blob_srv esp_ble_mesh_blob_srv_t;
/** @brief BLOB Transfer Server model event handlers. */
typedef struct esp_ble_mesh_blob_srv_cb esp_ble_mesh_blob_srv_cb_t;
/** Target node's Pull mode (Pull BLOB Transfer Mode) context used
* while sending chunks to the Target node.
*/
typedef struct esp_ble_mesh_blob_target_pull esp_ble_mesh_blob_target_pull_t;
/** BLOB Transfer Client Target node. */
typedef struct esp_ble_mesh_blob_target esp_ble_mesh_blob_target_t;
/** BLOB transfer information. */
typedef struct esp_ble_mesh_blob_xfer_info esp_ble_mesh_blob_xfer_info_t;
/** BLOB Transfer Client transfer inputs. */
typedef struct esp_ble_mesh_blob_cli_inputs esp_ble_mesh_blob_cli_inputs_t;
/** Transfer capabilities of a Target node. */
typedef struct esp_ble_mesh_blob_cli_caps esp_ble_mesh_blob_cli_caps_t;
/**
* @brief BLOB Transfer Client model instance.
* @note Preview version, the contents of this struct may change in the future.
*/
typedef struct esp_ble_mesh_blob_cli esp_ble_mesh_blob_cli_t;
/** Event handler callbacks for the BLOB Transfer Client model. */
typedef struct esp_ble_mesh_blob_cli_cb esp_ble_mesh_blob_cli_cb_t;
/** BLOB transfer. */
typedef struct esp_ble_mesh_blob_xfer esp_ble_mesh_blob_xfer_t;
/** BLOB transfer data block. */
typedef struct esp_ble_mesh_blob_block esp_ble_mesh_blob_block_t;
/** BLOB data chunk. */
typedef struct esp_ble_mesh_blob_chunk esp_ble_mesh_blob_chunk_t;
/** Transfer phase. */
typedef enum esp_ble_mesh_blob_xfer_phase {
ESP_BLE_MESH_BLOB_XFER_PHASE_INACTIVE, /*!< The BLOB Transfer Server is awaiting configuration. */
ESP_BLE_MESH_BLOB_XFER_PHASE_WAITING_FOR_START, /*!< The BLOB Transfer Server is ready to receive a BLOB transfer. */
ESP_BLE_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK, /*!< The BLOB Transfer Server is waiting for the next block of data. */
ESP_BLE_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK, /*!< The BLOB Transfer Server is waiting for the next chunk of data. */
ESP_BLE_MESH_BLOB_XFER_PHASE_COMPLETE, /*!< The BLOB was transferred successfully. */
ESP_BLE_MESH_BLOB_XFER_PHASE_SUSPENDED, /*!< The BLOB transfer is paused. */
} esp_ble_mesh_blob_xfer_phase_t;
/** BLOB transfer mode. */
typedef enum esp_ble_mesh_blob_xfer_mode {
ESP_BLE_MESH_BLOB_XFER_MODE_NONE, /*!< No valid transfer mode. */
ESP_BLE_MESH_BLOB_XFER_MODE_PUSH, /*!< Push mode (Push BLOB Transfer Mode). */
ESP_BLE_MESH_BLOB_XFER_MODE_PULL, /*!< Pull mode (Pull BLOB Transfer Mode). */
ESP_BLE_MESH_BLOB_XFER_MODE_ALL, /*!< Both modes are valid. */
} esp_ble_mesh_blob_xfer_mode_t;
/** BLOB model status codes. */
typedef enum esp_ble_mesh_blob_status {
/** The message was processed successfully. */
ESP_BLE_MESH_BLOB_SUCCESS,
/** The Block Number field value is not within the range of blocks being
* transferred.
*/
ESP_BLE_MESH_BLOB_ERR_INVALID_BLOCK_NUM,
/** The block size is smaller than the size indicated by the Min Block
* Size Log state or is larger than the size indicated by the Max Block
* Size Log state.
*/
ESP_BLE_MESH_BLOB_ERR_INVALID_BLOCK_SIZE,
/** The chunk size exceeds the size indicated by the Max Chunk Size
* state, or the number of chunks exceeds the number specified by the
* Max Total Chunks state.
*/
ESP_BLE_MESH_BLOB_ERR_INVALID_CHUNK_SIZE,
/** The operation cannot be performed while the server is in the current
* phase.
*/
ESP_BLE_MESH_BLOB_ERR_WRONG_PHASE,
/** A parameter value in the message cannot be accepted. */
ESP_BLE_MESH_BLOB_ERR_INVALID_PARAM,
/** The message contains a BLOB ID value that is not expected. */
ESP_BLE_MESH_BLOB_ERR_WRONG_BLOB_ID,
/** There is not enough space available in memory to receive the BLOB.
*/
ESP_BLE_MESH_BLOB_ERR_BLOB_TOO_LARGE,
/** The transfer mode is not supported by the BLOB Transfer Server
* model.
*/
ESP_BLE_MESH_BLOB_ERR_UNSUPPORTED_MODE,
/** An internal error occurred on the node. */
ESP_BLE_MESH_BLOB_ERR_INTERNAL,
/** The requested information cannot be provided while the server is in
* the current phase.
*/
ESP_BLE_MESH_BLOB_ERR_INFO_UNAVAILABLE,
} esp_ble_mesh_blob_status_t;
/** BLOB Transfer Client state. */
typedef enum esp_ble_mesh_blob_cli_state {
ESP_BLE_MESH_BLOB_CLI_STATE_NONE, /*!< No transfer is active. */
ESP_BLE_MESH_BLOB_CLI_STATE_CAPS_GET, /*!< Retrieving transfer capabilities. */
ESP_BLE_MESH_BLOB_CLI_STATE_START, /*!< Sending transfer start. */
ESP_BLE_MESH_BLOB_CLI_STATE_BLOCK_START, /*!< Sending block start. */
ESP_BLE_MESH_BLOB_CLI_STATE_BLOCK_SEND, /*!< Sending block chunks. */
ESP_BLE_MESH_BLOB_CLI_STATE_BLOCK_CHECK, /*!< Checking block status. */
ESP_BLE_MESH_BLOB_CLI_STATE_XFER_CHECK, /*!< Checking transfer status. */
ESP_BLE_MESH_BLOB_CLI_STATE_CANCEL, /*!< Cancelling transfer. */
ESP_BLE_MESH_BLOB_CLI_STATE_SUSPENDED, /*!< Transfer is suspended. */
ESP_BLE_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET, /*!< Checking transfer progress. */
} esp_ble_mesh_blob_cli_state_t;
/** BLOB stream interaction mode. */
typedef enum esp_ble_mesh_blob_io_mode {
ESP_BLE_MESH_BLOB_READ, /*!< Read data from the stream. */
ESP_BLE_MESH_BLOB_WRITE, /*!< Write data to the stream. */
} esp_ble_mesh_blob_io_mode_t;
/** BLOB transfer. */
struct esp_ble_mesh_blob_xfer {
uint64_t id; /*!< BLOB ID. */
size_t size; /*!< Total BLOB size in bytes. */
esp_ble_mesh_blob_xfer_mode_t mode; /*!< BLOB transfer mode. */
uint8_t block_size_log; /*!< Logarithmic representation of the block size. */
uint16_t chunk_size; /*!< Base chunk size. May be smaller for the last chunk. */
};
/** BLOB transfer data block. */
struct esp_ble_mesh_blob_block {
size_t size; /*!< Block size in bytes */
off_t offset; /*!< Offset in bytes from the start of the BLOB. */
uint16_t number; /*!< Block number */
uint16_t chunk_count; /*!< Number of chunks in block. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX,
8)]; /*!< Bitmap of missing chunks. */
};
/** BLOB data chunk. */
struct esp_ble_mesh_blob_chunk {
off_t offset; /*!< Offset of the chunk data from the start of the block. */
size_t size; /*!< Chunk data size. */
uint8_t *data; /*!< Chunk data. */
};
/** BLOB stream. */
struct esp_ble_mesh_blob_io {
/** @brief Open callback.
*
* Called when the reader is opened for reading.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param mode Direction of the stream (read/write).
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*open)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
esp_ble_mesh_blob_io_mode_t mode);
/** @brief Close callback.
*
* Called when the reader is closed.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
*/
void (*close)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer);
/** @brief Block start callback.
*
* Called when a new block is opened for sending. Each block is only
* sent once, and are always sent in increasing order. The data chunks
* inside a single block may be requested out of order and multiple
* times.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that was started.
*/
int (*block_start)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block);
/** @brief Block end callback.
*
* Called when the current block has been transmitted in full.
* No data from this block will be requested again, and the application
* data associated with this block may be discarded.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that finished sending.
*/
void (*block_end)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block);
/** @brief Chunk data write callback.
*
* Used by the BLOB Transfer Server on incoming data.
*
* Each block is divided into chunks of data. This callback is called
* when a new chunk of data is received. Chunks may be received in
* any order within their block.
*
* If the callback returns successfully, this chunk will be marked as
* received, and will not be received again unless the block is
* restarted due to a transfer suspension. If the callback returns a
* non-zero value, the chunk remains unreceived, and the BLOB Transfer
* Client will attempt to resend it later.
*
* Note that the Client will only perform a limited number of attempts
* at delivering a chunk before dropping a Target node from the transfer.
* The number of retries performed by the Client is implementation
* specific.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Received chunk.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*write)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block,
const esp_ble_mesh_blob_chunk_t *chunk);
/** @brief Chunk data read callback.
*
* Used by the BLOB Transfer Client to fetch outgoing data.
*
* The Client calls the chunk data request callback to populate a chunk
* message going out to the Target nodes. The data request callback
* may be called out of order and multiple times for each offset, and
* cannot be used as an indication of progress.
*
* Returning a non-zero status code on the chunk data request callback
* results in termination of the transfer.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Chunk to get the data of. The buffer pointer to by the
* @c data member should be filled by the callback.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*read)(const esp_ble_mesh_blob_io_t *io,
const esp_ble_mesh_blob_xfer_t *xfer,
const esp_ble_mesh_blob_block_t *block,
const esp_ble_mesh_blob_chunk_t *chunk);
};
/** @brief BLOB Transfer Server model event handlers.
*
* All callbacks are optional.
*/
struct esp_ble_mesh_blob_srv_cb {
/** @brief Transfer start callback.
*
* Called when the transfer has started with the prepared BLOB ID.
*
* @param srv BLOB Transfer Server instance.
* @param ctx Message context for the incoming start message. The
* entire transfer will be sent from the same source
* address.
* @param xfer Transfer parameters.
*
* @return 0 on success, or (negative) error code to reject the
* transfer.
*/
int (*start)(esp_ble_mesh_blob_srv_t *srv, esp_ble_mesh_msg_ctx_t *ctx,
esp_ble_mesh_blob_xfer_t *xfer);
/** @brief Transfer end callback.
*
* Called when the transfer ends, either because it was cancelled, or
* because it finished successfully. A new transfer may be prepared.
*
* @note The transfer may end before it's started if the start
* parameters are invalid.
*
* @param srv BLOB Transfer Server instance.
* @param id BLOB ID of the cancelled transfer.
* @param success Whether the transfer was successful.
*/
void (*end)(esp_ble_mesh_blob_srv_t *srv, uint64_t id, bool success);
/** @brief Transfer suspended callback.
*
* Called if the Server timed out while waiting for a transfer packet.
* A suspended transfer may resume later from the start of the current
* block. Any received chunks in the current block should be discarded,
* they will be received again if the transfer resumes.
*
* The transfer will call @c resumed again when resuming.
*
* @note The BLOB Transfer Server does not run a timer in the suspended state,
* and it's up to the application to determine whether the
* transfer should be permanently cancelled. Without interaction,
* the transfer will be suspended indefinitely, and the BLOB Transfer
* Server will not accept any new transfers.
*
* @param srv BLOB Transfer Server instance.
*/
void (*suspend)(esp_ble_mesh_blob_srv_t *srv);
/** @brief Transfer resume callback.
*
* Called if the transfer is resumed after being suspended.
*
* @param srv BLOB Transfer Server instance.
*/
void (*resume)(esp_ble_mesh_blob_srv_t *srv);
/** @brief Transfer recovery callback.
*
* Called when the Bluetooth mesh subsystem is started if the device is rebooted
* in the middle of a transfer.
*
* Transfers will not be resumed after a reboot if this callback is not
* defined.
*
* @param srv BLOB Transfer Server instance.
* @param xfer Transfer to resume.
* @param io BLOB stream return parameter. Must be set to a valid
* BLOB stream by the callback.
*
* @return 0 on success, or (negative) error code to abandon the
* transfer.
*/
int (*recover)(esp_ble_mesh_blob_srv_t *srv,
esp_ble_mesh_blob_xfer_t *xfer,
esp_ble_mesh_blob_io_t **io);
};
#if defined(CONFIG_BLE_MESH_BLOB_SRV)
#define ESP_BLE_MESH_BLOB_BLOCKS_MAX \
(DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_SIZE_MAX, \
CONFIG_BLE_MESH_BLOB_BLOCK_SIZE_MIN))
#else
#define ESP_BLE_MESH_BLOB_BLOCKS_MAX 1
#endif
/** @brief BLOB Transfer Server instance. */
struct esp_ble_mesh_blob_srv {
/** Event handler callbacks. */
esp_ble_mesh_blob_srv_cb_t *cb;
/** Runtime state: */
esp_ble_mesh_blob_io_t *io;
struct k_delayed_work rx_timeout;
esp_ble_mesh_blob_block_t block;
esp_ble_mesh_model_t *mod;
esp_ble_mesh_blob_xfer_phase_t phase;
/** State of blob serber. */
struct esp_ble_mesh_blob_srv_state {
esp_ble_mesh_blob_xfer_t xfer;
uint16_t cli;
uint16_t app_idx;
uint16_t timeout_base;
uint16_t mtu_size;
uint8_t ttl;
/* Bitfield of pending blocks. */
BLE_MESH_ATOMIC_DEFINE(blocks, ESP_BLE_MESH_BLOB_BLOCKS_MAX);
} state;
/* Pull mode (Pull BLOB Transfer Mode) behavior. */
struct {
uint16_t chunk_idx;
struct k_delayed_work report;
} pull;
};
/** Target node's Pull mode (Pull BLOB Transfer Mode) context used
* while sending chunks to the Target node.
*/
struct esp_ble_mesh_blob_target_pull {
int64_t block_report_timestamp; /*!< Timestamp when the Block Report Timeout Timer expires for this Target node. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX, 8)]; /*!< Missing chunks reported by this Target node. */
};
/** BLOB Transfer Client Target node. */
struct esp_ble_mesh_blob_target {
sys_snode_t n; /*!< Linked list node */
uint16_t addr; /*!< Target node address. */
/** Target node's Pull mode context.
* Needs to be initialized when sending a BLOB in Pull mode.
*/
esp_ble_mesh_blob_target_pull_t *pull;
uint8_t status; /*!< BLOB transfer status, see esp_ble_mesh_blob_status. */
uint8_t procedure_complete: 1, /*!< Procedure has been completed. */
acked: 1, /*!< Message has been acknowledged. Not used when sending. */
timedout: 1, /*!< Target node didn't respond after specified timeout. */
skip: 1; /*!< Skip Target node from broadcast. */
};
/** BLOB transfer information. */
struct esp_ble_mesh_blob_xfer_info {
esp_ble_mesh_blob_status_t status; /*!< BLOB transfer status. */
esp_ble_mesh_blob_xfer_mode_t mode; /*!< BLOB transfer mode. */
esp_ble_mesh_blob_xfer_phase_t phase; /*!< BLOB transfer phase. */
uint64_t id; /*!< BLOB ID. */
uint32_t size; /*!< BLOB size in octets. */
uint8_t block_size_log; /*!< Logarithmic representation of the block size. */
uint16_t mtu_size; /*!< MTU size in octets. */
const uint8_t *missing_blocks; /*!< Bit field indicating blocks that were not received. */
};
/** BLOB Transfer Client transfer inputs. */
struct esp_ble_mesh_blob_cli_inputs {
/** Linked list of Target nodes. Each node should point to
* esp_ble_mesh_blob_target_t::n.
*/
sys_slist_t targets;
/** AppKey index to send with. */
uint16_t app_idx;
/** Group address destination for the BLOB transfer, or
* ESP_BLE_MESH_ADDR_UNASSIGNED to send every message to each Target
* node individually.
*/
uint16_t group;
/** Time to live value of BLOB transfer messages. */
uint8_t ttl;
/** Additional response time for the Target nodes, in 10-second increments.
*
* The extra time can be used to give the Target nodes more time to respond
* to messages from the Client. The actual timeout will be calculated
* according to the following formula:
*
* @verbatim
* timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
* @endverbatim
*
* If a Target node fails to respond to a message from the Client within the
* configured transfer timeout, the Target node is dropped.
*/
uint16_t timeout_base;
};
/** Transfer capabilities of a Target node. */
struct esp_ble_mesh_blob_cli_caps {
size_t max_size; /*!< Max BLOB size. */
uint8_t min_block_size_log; /*!< Logarithmic representation of the minimum block size. */
uint8_t max_block_size_log; /*!< Logarithmic representation of the maximum block size. */
uint16_t max_chunks; /*!< Max number of chunks per block. */
uint16_t max_chunk_size; /*!< Max chunk size. */
uint16_t mtu_size; /*!< Max MTU size. */
esp_ble_mesh_blob_xfer_mode_t modes; /*!< Supported transfer modes. */
};
/** Event handler callbacks for the BLOB Transfer Client model.
*
* All handlers are optional.
*/
struct esp_ble_mesh_blob_cli_cb {
/** @brief Capabilities retrieval completion callback.
*
* Called when the capabilities retrieval procedure completes, indicating that
* a common set of acceptable transfer parameters have been established
* for the given list of Target nodes. All compatible Target nodes have
* status code ESP_BLE_MESH_BLOB_SUCCESS.
*
* @param cli BLOB Transfer Client instance.
* @param caps Safe transfer capabilities if the transfer capabilities
* of at least one Target node has satisfied the Client, or NULL otherwise.
*/
void (*caps)(esp_ble_mesh_blob_cli_t *cli,
const esp_ble_mesh_blob_cli_caps_t *caps);
/** @brief Target node loss callback.
*
* Called whenever a Target node has been lost due to some error in the
* transfer. Losing a Target node is not considered a fatal error for
* the Client until all Target nodes have been lost.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that was lost.
* @param reason Reason for the Target node loss.
*/
void (*lost_target)(esp_ble_mesh_blob_cli_t *cli,
esp_ble_mesh_blob_target_t *target,
esp_ble_mesh_blob_status_t reason);
/** @brief Transfer is suspended.
*
* Called when the transfer is suspended due to response timeout from all Target nodes.
*
* @param cli BLOB Transfer Client instance.
*/
void (*suspend)(esp_ble_mesh_blob_cli_t *cli);
/** @brief Transfer end callback.
*
* Called when the transfer ends.
*
* @param cli BLOB Transfer Client instance.
* @param xfer Completed transfer.
* @param success Status of the transfer.
* Is @c true if at least one Target
* node received the whole transfer.
*/
void (*end)(esp_ble_mesh_blob_cli_t *cli,
const esp_ble_mesh_blob_xfer_t *xfer, bool success);
/** @brief Transfer progress callback
*
* The content of @c info is invalidated upon exit from the callback.
* Therefore it needs to be copied if it is planned to be used later.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that responded to the request.
* @param info BLOB transfer information.
*/
void (*xfer_progress)(esp_ble_mesh_blob_cli_t *cli,
esp_ble_mesh_blob_target_t *target,
const esp_ble_mesh_blob_xfer_info_t *info);
/** @brief End of Get Transfer Progress procedure.
*
* Called when all Target nodes have responded or the procedure timed-out.
*
* @param cli BLOB Transfer Client instance.
*/
void (*xfer_progress_complete)(esp_ble_mesh_blob_cli_t *cli);
};
/** @cond INTERNAL_HIDDEN */
typedef struct {
/** Called for every Target node in unicast mode, or once in case of multicast mode. */
void (*send)(esp_ble_mesh_blob_cli_t *cli, uint16_t dst);
/** Called after every @ref blob_cli_broadcast_ctx::send callback. */
void (*send_complete)(esp_ble_mesh_blob_cli_t *cli, uint16_t dst);
/** If @ref blob_cli_broadcast_ctx::acked is true, called after all Target nodes
* have confirmed reception by @ref blob_cli_broadcast_rsp. Otherwise, called
* after transmission has been completed.
*/
void (*next)(esp_ble_mesh_blob_cli_t *cli);
/** If true, every transmission needs to be confirmed by @ref blob_cli_broadcast_rsp before
* @ref blob_cli_broadcast_ctx::next is called.
*/
bool acked;
/** If true, the message is always sent in a unicast way. */
bool force_unicast;
/** If true, non-responsive Target nodes won't be dropped after transfer has timed out. */
bool optional;
/** Set to true by the BLOB Transfer Client between blob_cli_broadcast
* and broadcast_complete calls.
*/
bool is_inited;
/* Defines a time in ms by which the broadcast API postpones sending the message to a next
* target or completing the broadcast.
*/
uint32_t post_send_delay_ms;
} esp_blob_cli_broadcast_ctx_t;
/** INTERNAL_HIDDEN @endcond */
/**
* @brief BLOB Transfer Client model instance.
* @note Preview version, the contents of this struct may change in the future.
*/
struct esp_ble_mesh_blob_cli {
/** Event handler callbacks */
const esp_ble_mesh_blob_cli_cb_t *cb;
/** Runtime state */
const esp_ble_mesh_model_t *mod;
/** Firmware transfer information */
struct {
esp_ble_mesh_blob_target_t *target;
esp_blob_cli_broadcast_ctx_t ctx;
struct k_delayed_work retry;
/* Represents Client Timeout timer in a timestamp. Used in Pull mode only. */
int64_t cli_timestamp;
struct k_work complete;
uint16_t pending;
uint8_t retries;
uint8_t sending : 1,
cancelled : 1;
} tx;
/** Firmware IO operation callbacks */
const esp_ble_mesh_blob_io_t *io;
/** BLOB Transfer Client transfer inputs. */
const esp_ble_mesh_blob_cli_inputs_t *inputs;
/** BLOB transfer. */
const esp_ble_mesh_blob_xfer_t *xfer;
/** Interval between chunk transmissions, in milliseconds. */
uint32_t chunk_interval_ms;
/** BLOCK count */
uint16_t block_count;
/** CHUNK index */
uint16_t chunk_idx;
/** Max Transfer Unit Size of BLOB Transfer */
uint16_t mtu_size;
/** State of blob client mode transfer */
esp_ble_mesh_blob_cli_state_t state;
/** BLOB transfer data block. */
esp_ble_mesh_blob_block_t block;
/** Transfer capabilities of a Target node. */
esp_ble_mesh_blob_cli_caps_t caps;
};
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_BLOB_MODEL_API_H_ */
@@ -0,0 +1,999 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_BLE_MESH_DFU_MODEL_API_H_
#define _ESP_BLE_MESH_DFU_MODEL_API_H_
#include "esp_ble_mesh_defs.h"
#include "esp_ble_mesh_blob_model_api.h"
#include "esp_ble_mesh_dfu_slot_api.h"
#if CONFIG_BLE_MESH_DFU_CLI || CONFIG_BLE_MESH_DFU_SRV
#ifndef _BLE_MESH_BLOB_DEPRECATE_WARN
#define _BLE_MESH_BLOB_DEPRECATE_WARN
#warning Please note: All APIs published in this document are in Preview version and may undergo significant changes in the future.
#endif
#endif /* CONFIG_BLE_MESH_DFU_CLI || CONFIG_BLE_MESH_DFU_SRV */
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x08)
#define ESP_BLE_MESH_DFU_OP_UPDATE_INFO_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x09)
#define ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0a)
#define ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0b)
#define ESP_BLE_MESH_DFU_OP_UPDATE_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0c)
#define ESP_BLE_MESH_DFU_OP_UPDATE_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0d)
#define ESP_BLE_MESH_DFU_OP_UPDATE_CANCEL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0e)
#define ESP_BLE_MESH_DFU_OP_UPDATE_APPLY ESP_BLE_MESH_MODEL_OP_2(0x83, 0x0f)
#define ESP_BLE_MESH_DFU_OP_UPDATE_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x10)
#if CONFIG_BLE_MESH_DFU_CLI
/** @def ESP_BLE_MESH_MODEL_DFU_CLI
*
* @brief Define a new DFU Client model.
*
* @note This API needs to be called for each element on which
* the application needs to have a DFU Client model.
*
* @param cli_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to the unique struct esp_ble_mesh_client_t.
*
* @return New DFU Client model instance.
*/
#define ESP_BLE_MESH_MODEL_DFU_CLI(cli_pub, cli_data) \
ESP_BLE_MESH_MODEL_BLOB_CLI(NULL, &(cli_data)->blob), \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_DFU_CLI, \
NULL, cli_pub, cli_data)
/** @def ESP_BLE_MESH_DFU_CLI_INIT
*
* @brief Initialize a DFU Client model instance.
*
* @note This macro is used to initialize the DFU Client model.
* It sets the callback handlers for the DFU Client.
*
* @param _handlers Pointer to the callback handler structure (esp_ble_mesh_dfu_cli_cb_t).
*
* @return An initialized DFU Client model instance.
*/
#define ESP_BLE_MESH_DFU_CLI_INIT(_handlers) \
{ \
.cb = _handlers, \
}
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
/** @def ESP_BLE_MESH_MODEL_DFU_SRV
*
* @brief Define a new DFU Server model.
*
* @note This API needs to be called for each element on which
* the application needs to have a DFU Server model.
*
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_dfu_trans_srv_t.
*
* @return New DFU Server model instance.
*/
#define ESP_BLE_MESH_MODEL_DFU_SRV(srv_pub, srv_data) \
ESP_BLE_MESH_MODEL_BLOB_SRV(NULL, &(srv_data)->blob), \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_DFU_SRV, \
NULL, srv_pub, srv_data)
/** @def ESP_BLE_MESH_DFU_SRV_INIT
*
* @brief Initialize a DFU Server model instance.
*
* @note This macro is used to initialize the DFU Server model.
* It sets the callback handlers and image information for the DFU Server.
*
* @param _handlers Pointer to the callback handler structure (esp_ble_mesh_dfu_srv_cb_t).
* @param _imgs Pointer to the array of DFU images (esp_ble_mesh_dfu_img_t).
* @param _img_count Number of DFU images in the array.
*
* @return An initialized DFU Server model instance.
*/
#define ESP_BLE_MESH_DFU_SRV_INIT(_handlers, _imgs, _img_count) \
{ \
.cb = _handlers, \
.imgs = _imgs, .img_count = _img_count, \
}
#endif /* CONFIG_BLE_MESH_DFU_SRV */
/** @brief DFU image structure. **/
typedef struct esp_ble_mesh_dfu_img esp_ble_mesh_dfu_img_t;
#if CONFIG_BLE_MESH_DFU_CLI
/** @brief DFU Client model instance structure.
*
* This structure represents a DFU (Device Firmware Update) Client model instance.
* It contains the necessary fields for managing DFU operations as a client.
* Should be initialized with ESP_BLE_MESH_DFU_CLI_INIT.
*
* @note Preview version, the contents of this struct may change in the future.
*/
typedef struct esp_ble_mesh_dfu_cli esp_ble_mesh_dfu_cli_t;
/** @brief DFU iteration action enumeration.
*
* This enumeration defines the possible actions that can be taken
* during DFU iteration callbacks. It controls whether to continue
* or stop iterating through DFU images.
*/
typedef enum esp_ble_mesh_dfu_iter esp_ble_mesh_dfu_iter_t;
/** @brief DFU image callback.
*
* The image callback is called for every DFU image on the Target node when
* calling bt_mesh_dfu_cli_imgs_get.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context of the received message.
* @param idx Image index.
* @param total Total number of images on the Target node.
* @param img Image information for the given image index.
* @param cb_data Callback data.
*
* @retval ESP_BLE_MESH_DFU_ITER_STOP Stop iterating through the image list and
* return from bt_mesh_dfu_cli_imgs_get.
* @retval ESP_BLE_MESH_DFU_ITER_CONTINUE Continue iterating through the image list
* if any images remain.
*/
typedef esp_ble_mesh_dfu_iter_t (*esp_ble_mesh_dfu_img_cb_t)(esp_ble_mesh_dfu_cli_t *cli,
esp_ble_mesh_msg_ctx_t *ctx, uint8_t idx,
uint8_t total, const esp_ble_mesh_dfu_img_t *img,
void *cb_data);
/** @brief DFU image slot structure.
*
* This structure represents a DFU image slot used for DFU distribution.
* It contains information about the firmware image including size,
* firmware ID, metadata, and their respective lengths.
*/
typedef struct esp_ble_mesh_dfu_slot esp_ble_mesh_dfu_slot_t;
/** @brief DFU Target node structure.
*
* This structure represents a DFU Target node in the mesh network.
* It contains information about the target's BLOB transfer status,
* image index, expected DFU effect, current status, and phase.
*/
typedef struct esp_ble_mesh_dfu_target esp_ble_mesh_dfu_target_t;
/** @brief DFU Client callback structure.
*
* This structure contains callback function pointers for DFU Client events
* such as transfer suspension, completion, application, confirmation,
* and target node loss.
*/
typedef struct esp_ble_mesh_dfu_cli_cb esp_ble_mesh_dfu_cli_cb_t;
/** @brief DFU Client model instance structure.
*
* This structure represents a DFU (Device Firmware Update) Client model instance.
* It contains the necessary fields for managing DFU operations as a client.
* Should be initialized with ESP_BLE_MESH_DFU_CLI_INIT.
*
* @note Preview version, the contents of this struct may change in the future.
*/
typedef struct esp_ble_mesh_dfu_cli esp_ble_mesh_dfu_cli_t;
/** @brief DFU Client BLOB transfer parameters structure.
*
* This structure contains parameters for BLOB transfer during DFU operations,
* including block size logarithmic representation and base chunk size.
*/
typedef struct esp_ble_mesh_dfu_cli_xfer_blob_params esp_ble_mesh_dfu_cli_xfer_blob_params_t;
/** @brief DFU Client transfer parameters structure.
*
* This structure contains parameters for DFU transfer operations,
* including BLOB ID, image slot, transfer mode, and BLOB parameters.
*/
typedef struct esp_ble_mesh_dfu_cli_xfer esp_ble_mesh_dfu_cli_xfer_t;
/** @brief Device Firmware Update Info Get parameters structure.
*
* This structure contains parameters for the Firmware Update Information Get message,
* including the first index and entries limit for requesting firmware information.
*/
typedef struct esp_ble_mesh_device_firmware_update_info_get esp_ble_mesh_device_firmware_update_info_get_t;
/** @brief Device Firmware Update Metadata Check parameters structure.
*
* This structure contains parameters for the Firmware Update Metadata Check message,
* including the update firmware index and vendor-specific metadata.
*/
typedef struct esp_ble_mesh_device_firmware_update_metadata_check esp_ble_mesh_device_firmware_update_metadata_check_t;
/** @brief DFU Client get message union.
*
* This union contains different parameter structures for various DFU Client
* get messages, allowing type-safe access to message-specific parameters.
*/
typedef union esp_ble_mesh_dfu_client_get esp_ble_mesh_dfu_client_get_t;
/** @brief DFU Client send arguments structure.
*
* This structure contains arguments for sending firmware via DFU Client,
* including the client instance, transfer inputs, BLOB stream, and transfer parameters.
*/
typedef struct esp_ble_mesh_dfu_cli_send_arg esp_ble_mesh_dfu_cli_send_arg_t;
/** @brief Firmware information structure.
*
* This structure contains information about firmware including firmware ID
* and update URI for retrieving new firmware.
*/
typedef struct esp_ble_mesh_firmware_info esp_ble_mesh_firmware_info_t;
/** @brief Device Firmware Update Info Status response structure.
*
* This structure contains the response parameters for Firmware Update Information
* Status message, including firmware information list count and details.
*/
typedef struct esp_ble_mesh_device_firmware_update_info_status esp_ble_mesh_device_firmware_update_info_status_t;
/** @brief Device Firmware Update Metadata Check Status response structure.
*
* This structure contains the response parameters for Firmware Update Metadata
* Check Status message, including status code and additional information.
*/
typedef struct esp_ble_mesh_device_firmware_metadata_check_status esp_ble_mesh_device_firmware_metadata_check_status_t;
/** @brief Device Firmware Update Status response structure.
*
* This structure contains the response parameters for various Firmware Update
* Status messages (Get, Start, Cancel, Apply), including status, phase,
* TTL, timeout base, BLOB ID, and firmware image index.
*/
typedef struct esp_ble_mesh_device_firmware_update_status esp_ble_mesh_device_firmware_update_status_t;
/** @brief DFU Client send callback structure.
*
* This structure contains the result of sending DFU Client messages,
* including error code indicating success or failure.
*/
typedef struct esp_ble_mesh_dfu_client_send_cb esp_ble_mesh_dfu_client_send_cb_t;
/** @brief DFU Client receive callback union.
*
* This union contains different response structures for various DFU Client
* received status messages, allowing type-safe access to message-specific responses.
*/
typedef union esp_ble_mesh_dfu_client_recv_cb esp_ble_mesh_dfu_client_recv_cb_t;
/** @brief DFU Client callback parameters structure.
*
* This structure contains parameters for DFU Client callbacks, including
* common client parameters and a union of send/receive callback data.
*/
typedef struct esp_ble_mesh_dfu_client_cb_param esp_ble_mesh_dfu_client_cb_param_t;
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
/** @brief Firmware Update Server instance structure.
*
* This structure represents a DFU (Device Firmware Update) Server model instance.
* It contains the necessary fields for managing DFU operations as a server.
* Should be initialized with ESP_BLE_MESH_DFU_SRV_INIT.
*
* @note Preview version, the contents of this struct may change in the future.
*/
typedef struct esp_ble_mesh_dfu_srv esp_ble_mesh_dfu_srv_t;
/** @brief Firmware Update Server callback structure.
*
* This structure contains callback function pointers for DFU Server events
* such as transfer check, start, end, recovery, and apply.
*/
typedef struct esp_ble_mesh_dfu_srv_cb esp_ble_mesh_dfu_srv_cb_t;
#endif /* CONFIG_BLE_MESH_DFU_SRV */
/** DFU transfer phase. */
typedef enum esp_ble_mesh_dfu_phase {
/** Ready to start a Receive Firmware procedure. */
ESP_BLE_MESH_DFU_PHASE_IDLE,
/** The Transfer BLOB procedure failed. */
ESP_BLE_MESH_DFU_PHASE_TRANSFER_ERR,
/** The Receive Firmware procedure is being executed. */
ESP_BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE,
/** The Verify Firmware procedure is being executed. */
ESP_BLE_MESH_DFU_PHASE_VERIFY,
/** The Verify Firmware procedure completed successfully. */
ESP_BLE_MESH_DFU_PHASE_VERIFY_OK,
/** The Verify Firmware procedure failed. */
ESP_BLE_MESH_DFU_PHASE_VERIFY_FAIL,
/** The Apply New Firmware procedure is being executed. */
ESP_BLE_MESH_DFU_PHASE_APPLYING,
/** Firmware transfer has been canceled. */
ESP_BLE_MESH_DFU_PHASE_TRANSFER_CANCELED,
/** Firmware applying succeeded. */
ESP_BLE_MESH_DFU_PHASE_APPLY_SUCCESS,
/** Firmware applying failed. */
ESP_BLE_MESH_DFU_PHASE_APPLY_FAIL,
/** Phase of a node was not yet retrieved. */
ESP_BLE_MESH_DFU_PHASE_UNKNOWN,
} esp_ble_mesh_dfu_phase_t;
/** Expected effect of a DFU transfer. */
typedef enum esp_ble_mesh_dfu_effect {
/** No changes to node Composition Data. */
ESP_BLE_MESH_DFU_EFFECT_NONE,
/** Node Composition Data changed and the node does not support remote
* provisioning.
*/
ESP_BLE_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR,
/** 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.
*/
ESP_BLE_MESH_DFU_EFFECT_COMP_CHANGE,
/** Node will be unprovisioned after the update. */
ESP_BLE_MESH_DFU_EFFECT_UNPROV,
} esp_ble_mesh_dfu_effect_t;
/** DFU status. */
typedef enum esp_ble_mesh_dfu_status {
/** The message was processed successfully. */
ESP_BLE_MESH_DFU_SUCCESS,
/** Insufficient resources on the node */
ESP_BLE_MESH_DFU_ERR_RESOURCES,
/** The operation cannot be performed while the Server is in the current
* phase.
*/
ESP_BLE_MESH_DFU_ERR_WRONG_PHASE,
/** An internal error occurred on the node. */
ESP_BLE_MESH_DFU_ERR_INTERNAL,
/** The message contains a firmware index value that is not expected. */
ESP_BLE_MESH_DFU_ERR_FW_IDX,
/** The metadata check failed. */
ESP_BLE_MESH_DFU_ERR_METADATA,
/** The Server cannot start a firmware update. */
ESP_BLE_MESH_DFU_ERR_TEMPORARILY_UNAVAILABLE,
/** Another BLOB transfer is in progress. */
ESP_BLE_MESH_DFU_ERR_BLOB_XFER_BUSY,
} esp_ble_mesh_dfu_status_t;
#if CONFIG_BLE_MESH_DFU_CLI
/** Action for DFU iteration callbacks. */
enum esp_ble_mesh_dfu_iter {
/** Stop iterating. */
ESP_BLE_MESH_DFU_ITER_STOP,
/** Continue iterating. */
ESP_BLE_MESH_DFU_ITER_CONTINUE,
};
/** @brief DFU transfer states
*
* This enumeration defines the various states of a DFU (Device Firmware Update) transfer.
* These states track the progress of firmware distribution from idle state through
* transfer, verification, application, and confirmation phases.
*/
typedef enum esp_ble_mesh_dfu_xfer_state {
/** Idle state - No DFU transfer is in progress. */
ESP_BLE_MESH_DFU_XFER_IDLE,
/** Transfer state - Firmware data is being transferred to target nodes. */
ESP_BLE_MESH_DFU_XFER_TRANSFER,
/** Refresh state - Transfer is paused or being refreshed. */
ESP_BLE_MESH_DFU_XFER_REFRESH,
/** Verified state - Firmware has been successfully verified on target nodes. */
ESP_BLE_MESH_DFU_XFER_VERIFIED,
/** Apply state - Firmware is being applied on target nodes. */
ESP_BLE_MESH_DFU_XFER_APPLY,
/** Applied state - Firmware has been successfully applied on target nodes. */
ESP_BLE_MESH_DFU_XFER_APPLIED,
/** Confirm state - Waiting for confirmation from target nodes. */
ESP_BLE_MESH_DFU_XFER_CONFIRM,
/** Cancel state - DFU transfer has been cancelled. */
ESP_BLE_MESH_DFU_XFER_CANCEL,
/** Suspended state - DFU transfer has been suspended. */
ESP_BLE_MESH_DFU_XFER_SUSPENDED,
} esp_ble_mesh_dfu_xfer_state_t;
/** @brief Callback events of Device Firmware Update Client Model
*
* This enumeration defines the various callback events that can be generated
* by the DFU (Device Firmware Update) Client model. These events are used
* to notify the application about different stages and states of the DFU process,
* including message sending, timeouts, response reception, and image transfer completion.
*/
typedef enum {
/** DFU Client message sending completed event.
* This event is triggered when a DFU Client message has been successfully sent.
*/
ESP_BLE_MESH_DFU_CLIENT_SEND_COMP_EVT,
/** DFU Client timeout event.
* This event is triggered when a DFU Client operation times out waiting for a response.
*/
ESP_BLE_MESH_DFU_CLIENT_TIMEOUT_EVT,
/** DFU Client received Get response event.
* This event is triggered when the DFU Client receives a response to a Get message.
*/
ESP_BLE_MESH_DFU_CLIENT_RECV_GET_RSP_EVT,
/** DFU Client image send completed event.
* This event is triggered when the DFU Client has completed sending a firmware image.
*/
ESP_BLE_MESH_DFU_CLIENT_IMG_SEND_CMP_EVT,
/** Maximum DFU Client event value (used for bounds checking). */
ESP_BLE_MESH_DFU_CLIENT_EVT_MAX,
} esp_ble_mesh_dfu_client_cb_event_t;
#endif /* CONFIG_BLE_MESH_DFU_CLI */
/** DFU image instance.
*
* Each DFU image represents a single updatable firmware image.
*/
struct esp_ble_mesh_dfu_img {
/** Firmware ID. */
const void *fwid;
/** Length of the firmware ID. */
size_t fwid_len;
/** Update URI, or NULL. */
const char *uri;
};
#if CONFIG_BLE_MESH_DFU_CLI
/** DFU image slot for DFU distribution. */
struct esp_ble_mesh_dfu_slot {
/** Size of the firmware in bytes. */
size_t size;
/** Length of the firmware ID. */
size_t fwid_len;
/** Length of the metadata. */
size_t metadata_len;
/** Firmware ID. */
uint8_t fwid[CONFIG_BLE_MESH_DFU_FWID_MAXLEN];
/** Metadata. */
uint8_t metadata[CONFIG_BLE_MESH_DFU_METADATA_MAXLEN];
};
/** DFU Target node. */
struct esp_ble_mesh_dfu_target {
/** BLOB Target node */
esp_ble_mesh_blob_target_t blob;
/** Image index on the Target node */
uint8_t img_idx;
/** Expected DFU effect, see bt_mesh_dfu_effect. */
uint8_t effect;
/** Current DFU status, see bt_mesh_dfu_status. */
uint8_t status;
/** Current DFU phase, see bt_mesh_dfu_phase. */
uint8_t phase;
};
/** Firmware Update Client event callbacks. */
struct esp_ble_mesh_dfu_cli_cb {
/** @brief BLOB transfer is suspended.
*
* Called when the BLOB transfer is suspended due to response timeout from all Target nodes.
*
* @param cli Firmware Update Client model instance.
*/
void (*suspended)(esp_ble_mesh_dfu_cli_t *cli);
/** @brief DFU ended.
*
* Called when the DFU transfer ends, either because all Target nodes were
* lost or because the transfer was completed successfully.
*
* @param cli Firmware Update Client model instance.
* @param reason Reason for ending.
*/
void (*ended)(esp_ble_mesh_dfu_cli_t *cli,
esp_ble_mesh_dfu_status_t reason);
/** @brief DFU transfer applied on all active Target nodes.
*
* Called at the end of the apply procedure.
*
* @param cli Firmware Update Client model instance.
*/
void (*applied)(esp_ble_mesh_dfu_cli_t *cli);
/** @brief DFU transfer confirmed on all active Target nodes.
*
* Called at the end of the apply procedure.
*
* @param cli Firmware Update Client model instance.
*/
void (*confirmed)(esp_ble_mesh_dfu_cli_t *cli);
/** @brief DFU Target node was lost.
*
* A DFU Target node was dropped from the receivers list. The Target node's
* @c status is set to reflect the reason for the failure.
*
* @param cli Firmware Update Client model instance.
* @param target DFU Target node that was lost.
*/
void (*lost_target)(esp_ble_mesh_dfu_cli_t *cli,
esp_ble_mesh_dfu_target_t *target);
};
/** Firmware Update Client model instance.
* Should be initialized with ESP_BLE_MESH_DFU_CLI_INIT.
*
* @note Preview version, the contents of this struct may change in the future.
*/
struct esp_ble_mesh_dfu_cli {
/** Callback structure. */
const esp_ble_mesh_dfu_cli_cb_t *cb;
/** Underlying BLOB Transfer Client. */
esp_ble_mesh_blob_cli_t blob;
/** runtime state */
uint32_t op;
/** ble mesh model instance. */
esp_ble_mesh_model_t *mod;
/** BLOB Transfer information */
struct {
const esp_ble_mesh_dfu_slot_t *slot;
const esp_ble_mesh_blob_io_t *io;
esp_ble_mesh_blob_xfer_t blob;
uint8_t state;
uint8_t flags;
} xfer;
/** Current request */
void *req;
};
/** BLOB parameters for Firmware Update Client transfer */
struct esp_ble_mesh_dfu_cli_xfer_blob_params {
/** Logarithmic representation of the block size. */
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
};
/** Firmware Update Client transfer parameters */
struct esp_ble_mesh_dfu_cli_xfer {
/** BLOB ID to use for this transfer, or 0 to set it randomly. */
uint64_t blob_id;
/** DFU image slot to transfer. */
const esp_ble_mesh_dfu_slot_t *slot;
/** Transfer mode (Push (Push BLOB Transfer Mode) or Pull (Pull BLOB Transfer Mode)) */
enum esp_ble_mesh_blob_xfer_mode mode;
/** BLOB parameters to be used for the transfer, or NULL to retrieve Target nodes'
* capabilities before sending a firmware.
*/
const esp_ble_mesh_dfu_cli_xfer_blob_params_t *blob_params;
};
/**
* @brief Parameters of Device Firmware Update Info Get.
*/
struct esp_ble_mesh_device_firmware_update_info_get {
uint8_t first_index; /*!< Index of the first requested entry from the Firmware Information List state */
uint8_t entries_limit; /*!< Maximum number of entries that the server includes in a Firmware Update Information Status message */
esp_ble_mesh_dfu_img_cb_t img_cb; /*!< Added by Espressif, callback function used to walkthrough recceived images */
};
/**
* @brief Parameters of Device Firmware Update Firmware Metadata Check.
*/
struct esp_ble_mesh_device_firmware_update_metadata_check {
uint8_t update_firmware_index; /*!< Index of the firmware image in the Firmware Information List state to check */
struct net_buf_simple *metadata; /*!< Vendor-specific metadata */
};
/**
* @brief Device Firmware Update Client model get message union.
* For ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET
* ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK
* ESP_BLE_MESH_DFU_OP_UPDATE_START
* the get_state parameter in the `esp_ble_mesh_dfu_client_get_state` function should not be set to NULL.
*/
union esp_ble_mesh_dfu_client_get {
esp_ble_mesh_device_firmware_update_info_get_t dfu_update_info_get; /*!< For ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET */
esp_ble_mesh_device_firmware_update_metadata_check_t dfu_metadata_check; /*!< For ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK */
};
/**
* @brief Parameters of Device Firmware Update Client
* model to send Firmware.
*/
struct esp_ble_mesh_dfu_cli_send_arg {
esp_ble_mesh_dfu_cli_t *cli; /*!< Device Firmware Update Client model instance */
esp_ble_mesh_blob_cli_inputs_t *inputs; /*!< BLOB Transfer Client transfer inputs. */
esp_ble_mesh_blob_io_t *io; /*!< BLOB stream. */
esp_ble_mesh_dfu_cli_xfer_t *xfer; /*!< Firmware Update Client transfer parameters */
};
/**
* @brief Struct of firmware information.
*/
struct esp_ble_mesh_firmware_info {
struct net_buf_simple *fw_id; /*!< Firmware ID */
struct net_buf_simple *update_uri; /*!< URI used to retrieve a new firmware */
};
/**
* @brief Response of Firmware Update Information Get Message
*/
struct esp_ble_mesh_device_firmware_update_info_status {
uint8_t fw_info_list_cnt; /*!< The number of entries in the Firmware Information List */
uint8_t first_index; /*!< Index of the first requested entry from the Firmware Information List */
esp_ble_mesh_firmware_info_t *fw_info_list; /*!< List of firmware information entries */
};
/**
* @brief Response of Firmware Update Firmware Metadata Check Message
*/
struct esp_ble_mesh_device_firmware_metadata_check_status {
uint8_t status : 3; /*!< Status Code from the firmware metadata check */
uint8_t additional_info : 5; /*!< The Firmware Update Additional Information state from the Firmware Update Server (see Section 4.1.3)*/
uint8_t update_firmware_image_index; /*!< Index of the firmware image in the Firmware Information List state that was checked*/
};
/**
* @brief Response of Firmware Update Get Message,
* Firmware Update Start Message,
* Firmware Update Cancel Message,
* Firmware Update Apply Message.
*/
struct esp_ble_mesh_device_firmware_update_status {
uint8_t status : 3; /*!< Status Code for the requesting message */
uint8_t update_phase : 3; /*!< The Update Phase state of the Firmware Update Server */
uint8_t update_ttl; /*!< TTL value to use during firmware image transfer */
uint8_t additional_info : 5; /*!< The Firmware Update Additional Information state from the Firmware Update Server (see Section 4.1.3)*/
uint16_t update_timeout_base; /*!< Used to compute the timeout of the firmware image transfer */
uint64_t update_blob_id; /*!< BLOB identifier for the firmware image */
uint8_t update_fw_img_idx; /*!< The index of the firmware image in the Firmware Information List state being updated*/
};
/** Result of sending Device Firmware Update Client messages */
struct esp_ble_mesh_dfu_client_send_cb {
int err_code; /*!< Result of sending a message */
};
/**
* @brief Device Firmware Update Client model received message union
*/
union esp_ble_mesh_dfu_client_recv_cb {
esp_ble_mesh_device_firmware_update_info_status_t dfu_update_info_status; /*!< ESP_BLE_MESH_MODEL_OP_DIRECTED_CONTROL_STATUS */
esp_ble_mesh_device_firmware_metadata_check_status_t dfu_metadata_check_status; /*!< ESP_BLE_MESH_MODEL_OP_PATH_METRIC_STATUS */
esp_ble_mesh_device_firmware_update_status_t dfu_firmware_update_status; /*!< ESP_BLE_MESH_MODEL_OP_DISCOVERY_TABLE_CAPS_STATUS */
};
/** Device Firmware Update Client model callback parameters */
struct esp_ble_mesh_dfu_client_cb_param {
esp_ble_mesh_client_common_param_t *params; /*!< Client common parameters, used by all events. */
/** Union of DF Client callback */
union {
esp_ble_mesh_dfu_client_send_cb_t send; /*!< Result of sending a message */
esp_ble_mesh_dfu_client_recv_cb_t recv; /*!< Parameters of received status message */
};
};
/**
* @brief Bluetooth Mesh Device Firmware Update client and server model functions.
*/
/**
* @brief Device Firmware Update Client model callback function type
* @param event: Event type
* @param param: Pointer to callback parameter
*/
typedef void (* esp_ble_mesh_dfu_client_cb_t)(esp_ble_mesh_dfu_client_cb_event_t event,
esp_ble_mesh_dfu_client_cb_param_t *param);
/**
* @brief Device Firmware Update Server model callback function type
* @param event: Event type
* @param param: Pointer to callback parameter
*/
typedef void (* esp_ble_mesh_dfu_server_cb_t)(esp_ble_mesh_dfu_client_cb_event_t event,
esp_ble_mesh_dfu_client_cb_param_t *param);
/**
* @brief Register BLE Mesh Device Firmware Update Client model callback.
*
* @param callback: Pointer to the callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_dfu_client_callback(esp_ble_mesh_dfu_client_cb_t callback);
/**
* @brief Get the value of Device Firmware Server model state with the corresponding get message.
*
* @param params: Pointer to BLE Mesh common client parameters.
* @param get: Pointer to a union, each kind of opcode corresponds to one structure inside.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_dfu_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_dfu_client_get_t *get);
/** @brief Start distributing a DFU.
*
* Starts distribution of the firmware in the given slot to the list of DFU
* Target nodes in @c ctx. The transfer runs in the background, and its end is
* signalled through the bt_mesh_dfu_cli_cb::ended callback.
*
* @note The BLOB Transfer Client transfer inputs @c targets list must point to a list of
* bt_mesh_dfu_target nodes. The contents of `inputs`, `io`, `xfer` must not be changed or
* released from the beginning to the end of the transmission.
*
* @param cli Firmware Update Client model instance.
* @param inputs BLOB Transfer Client transfer inputs.
* @param io BLOB stream to read BLOB from.
* @param xfer Firmware Update Client transfer parameters.
*
* @return 0 on success, or (negative) error code otherwise.
*/
esp_err_t esp_ble_mesh_dfu_cli_img_send(esp_ble_mesh_dfu_cli_t *cli,
esp_ble_mesh_blob_cli_inputs_t *inputs,
esp_ble_mesh_blob_io_t *io,
esp_ble_mesh_dfu_cli_xfer_t *xfer);
/** @brief Get progress as a percentage of completion.
*
* @param cli Firmware Update Client model instance.
*
* @return The progress of the current transfer in percent, or 0 if no
* transfer is active.
*/
uint8_t esp_ble_mesh_dfu_cli_progress(esp_ble_mesh_dfu_cli_t *cli);
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
/** @brief Firmware Update Server event callbacks. */
struct esp_ble_mesh_dfu_srv_cb {
/** @brief Transfer check callback.
*
* The transfer check can be used to validate the incoming transfer
* before it starts. The contents of the metadata is implementation
* specific, and should contain all the information the application
* needs to determine whether this image should be accepted, and what
* the effect of the transfer would be.
*
* If applying the image will have an effect on the provisioning state
* of the mesh stack, this can be communicated through the @c effect
* return parameter.
*
* The metadata check can be performed both as part of starting a new
* transfer and as a separate procedure.
*
* This handler is optional.
*
* @param srv Firmware Update Server instance.
* @param img DFU image the metadata check is performed on.
* @param metadata Image metadata.
* @param effect Return parameter for the image effect on the
* provisioning state of the mesh stack.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*check)(esp_ble_mesh_dfu_srv_t *srv,
const esp_ble_mesh_dfu_img_t *img,
struct net_buf_simple *metadata,
esp_ble_mesh_dfu_effect_t *effect);
/** @brief Transfer start callback.
*
* Called when the Firmware Update Server is ready to start a new DFU transfer.
* The application must provide an initialized BLOB stream to be used
* during the DFU transfer.
*
* The following error codes are treated specially, and should be used
* to communicate these issues:
* - @c -ENOMEM: The device cannot fit this image.
* - @c -EBUSY: The application is temporarily unable to accept the
* transfer.
* - @c -EALREADY: The device has already received and verified this
* image, and there's no need to transfer it again. The Firmware Update model
* will skip the transfer phase, and mark the image as verified.
*
* This handler is mandatory.
*
* @param srv Firmware Update Server instance.
* @param img DFU image being updated.
* @param metadata Image metadata.
* @param io BLOB stream return parameter. Must be set to a
* valid BLOB stream by the callback.
*
* @return 0 on success, or (negative) error code otherwise. Return
* codes @c -ENOMEM, @c -EBUSY @c -EALREADY will be passed to
* the updater, other error codes are reported as internal
* errors.
*/
int (*start)(esp_ble_mesh_dfu_srv_t *srv,
const esp_ble_mesh_dfu_img_t *img,
struct net_buf_simple *metadata,
const esp_ble_mesh_blob_io_t **io);
/** @brief Transfer end callback.
*
* This handler is optional.
*
* If the transfer is successful, the application should verify the
* firmware image, and call either bt_mesh_dfu_srv_verified or
* bt_mesh_dfu_srv_rejected depending on the outcome.
*
* If the transfer fails, the Firmware Update Server will be available for new
* transfers immediately after this function returns.
*
* @param srv Firmware Update Server instance.
* @param img DFU image that failed the update.
* @param success Whether the DFU transfer was successful.
*/
void (*end)(esp_ble_mesh_dfu_srv_t *srv,
const esp_ble_mesh_dfu_img_t *img, bool success);
/** @brief Transfer recovery callback.
*
* If the device reboots in the middle of a transfer, the Firmware Update Server
* calls this function when the Bluetooth mesh subsystem is started.
*
* This callback is optional, but transfers will not be recovered after
* a reboot without it.
*
* @param srv Firmware Update Server instance.
* @param img DFU image being updated.
* @param io BLOB stream return parameter. Must be set to a valid BLOB
* stream by the callback.
*
* @return 0 on success, or (negative) error code to abandon the
* transfer.
*/
int (*recover)(esp_ble_mesh_dfu_srv_t *srv,
const esp_ble_mesh_dfu_img_t *img,
const esp_ble_mesh_blob_io_t **io);
/** @brief Transfer apply callback.
*
* Called after a transfer has been validated, and the updater sends an
* apply message to the Target nodes.
*
* This handler is optional.
*
* @param srv Firmware Update Server instance.
* @param img DFU image that should be applied.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*apply)(esp_ble_mesh_dfu_srv_t *srv,
const esp_ble_mesh_dfu_img_t *img);
};
/** @brief Firmware Update Server instance.
*
* Should be initialized with ESP_BLE_MESH_DFU_SRV_INIT.
* @note Preview version, the contents of this struct may change in the future.
*/
struct esp_ble_mesh_dfu_srv {
/** Underlying BLOB Transfer Server. */
esp_ble_mesh_blob_srv_t blob;
/** Callback structure. */
const esp_ble_mesh_dfu_srv_cb_t *cb;
/** List of updatable images. */
const esp_ble_mesh_dfu_img_t *imgs;
/** Number of updatable images. */
size_t img_count;
/** Runtime state */
esp_ble_mesh_model_t *mod;
/** Update information */
struct {
/* Effect of transfer, @see bt_mesh_dfu_effect. */
uint8_t effect;
/* Current phase, @see bt_mesh_dfu_phase. */
uint8_t phase;
uint8_t ttl;
uint8_t idx;
uint16_t timeout_base;
uint16_t meta;
} update;
};
/** @brief Accept the received DFU transfer.
*
* Should be called at the end of a successful DFU transfer.
*
* If the DFU transfer completes successfully, the application should verify
* the image validity (including any image authentication or integrity checks),
* and call this function if the image is ready to be applied.
*
* @param srv Firmware Update Server instance.
*/
void esp_ble_mesh_dfu_srv_verified(esp_ble_mesh_dfu_srv_t *srv);
/** @brief Reject the received DFU transfer.
*
* Should be called at the end of a successful DFU transfer.
*
* If the DFU transfer completes successfully, the application should verify
* the image validity (including any image authentication or integrity checks),
* and call this function if one of the checks fail.
*
* @param srv Firmware Update Server instance.
*/
void esp_ble_mesh_dfu_srv_rejected(esp_ble_mesh_dfu_srv_t *srv);
/** @brief Cancel the ongoing DFU transfer.
*
* @param srv Firmware Update Server instance.
*/
void esp_ble_mesh_dfu_srv_cancel(esp_ble_mesh_dfu_srv_t *srv);
/** @brief Confirm that the received DFU transfer was applied.
*
* Should be called as a result of the `bt_mesh_dfu_srv_cb.apply` callback.
*
* @param srv Firmware Update Server instance.
*/
void esp_ble_mesh_dfu_srv_applied(esp_ble_mesh_dfu_srv_t *srv);
/** @brief Check if the Firmware Update Server is busy processing a transfer.
*
* @param srv Firmware Update Server instance.
*
* @return true if a DFU procedure is in progress, false otherwise.
*/
bool esp_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv);
/** @brief Get the progress of the current DFU procedure, in percent.
*
* @param srv Firmware Update Server instance.
*
* @return The current transfer progress in percent.
*/
uint8_t esp_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv);
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_DFU_MODEL_API_H_ */
@@ -0,0 +1,148 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_BLE_MESH_DFU_SLOT_API_H_
#define _ESP_BLE_MESH_DFU_SLOT_API_H_
#include "esp_ble_mesh_dfu_model_api.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
#ifndef _BLE_MESH_BLOB_DEPRECATE_WARN
#define _BLE_MESH_BLOB_DEPRECATE_WARN
#warning Please note: All APIs published in this document are in Preview version and may undergo significant changes in the future.
#endif
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */
typedef struct esp_ble_mesh_dfu_slot esp_ble_mesh_dfu_slot_t;
typedef enum esp_ble_mesh_dfu_iter
(*esp_ble_mesh_dfu_slot_cb_t) (const esp_ble_mesh_dfu_slot_t *slot, void *user_data);
/** @brief Get the number of slots committed to the firmware list.
*
* @return Number of committed slots.
*/
int esp_ble_mesh_dfu_slot_count(void);
/** @brief Reserve a new DFU image slot for a distributable image.
*
* A DFU image slot represents a single distributable DFU image with all its
* metadata. The slot data must be set using esp_ble_mesh_dfu_slot_info_set and
* esp_ble_mesh_dfu_slot_fwid_set, and the slot committed using
* esp_ble_mesh_dfu_slot_commit for the slot to be considered part of the slot
* list.
*
* @return
* - slot : A pointer to the reserved slot
* - @c NULL : Slot allocation failed
*/
esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_reserve(void);
/** @brief Set the size and metadata for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the
* metadata.
* @param size The size of the image.
* @param metadata Metadata or NULL.
* @param metadata_len Length of the metadata, at most @c
* CONFIG_BLE_MESH_DFU_METADATA_MAXLEN.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter or invalid metadata parameter
* - @c ESP_ERR_INVALID_SIZE : metadata length is zero or exceeds @c CONFIG_BLE_MESH_DFU_METADATA_MAXLEN
*/
int esp_ble_mesh_dfu_slot_info_set(esp_ble_mesh_dfu_slot_t *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len);
/** @brief Set the new fwid for the incoming image for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the fwid.
* @param fwid Fwid to set.
* @param fwid_len Length of the fwid, at most @c
* CONFIG_BLE_MESH_DFU_FWID_MAXLEN.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter or invalid fwid parameter
* - @c ESP_ERR_INVALID_SIZE : fwid length is zero or exceeds @c CONFIG_BLE_MESH_DFU_FWID_MAXLEN
*/
int esp_ble_mesh_dfu_slot_fwid_set(esp_ble_mesh_dfu_slot_t *dfu_slot,
const uint8_t *fwid, size_t fwid_len);
/** @brief Commit the reserved slot to the list of slots, and store it
* persistently.
*
* If the commit fails for any reason, the slot will still be in the reserved
* state after this call.
*
* @param dfu_slot Pointer to the reserved slot.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter or slot has been committed
* - @c ESP_ERR_INVALID_SIZE : slot size is zero
*/
int esp_ble_mesh_dfu_slot_commit(esp_ble_mesh_dfu_slot_t *dfu_slot);
/** @brief Release a reserved slot so that it can be reserved again.
*
* @param dfu_slot Pointer to the reserved slot.
*/
void esp_ble_mesh_dfu_slot_release(const esp_ble_mesh_dfu_slot_t *dfu_slot);
/** @brief Delete a committed DFU image slot.
*
* @param slot Slot to delete. Must be a valid pointer acquired from this
* module.
*
* @return
* - 0 : success
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter
*/
int esp_ble_mesh_dfu_slot_del(const esp_ble_mesh_dfu_slot_t *slot);
/** @brief Delete all DFU image slots.
*/
void esp_ble_mesh_dfu_slot_del_all(void);
/** @brief Get the DFU image slot at the given firmware image list index.
*
* @param img_idx DFU image slot index.
*
* @return
* - slot : A pointer to the reserved slot
* - @c NULL : No slot exists with the given index
*/
const esp_ble_mesh_dfu_slot_t *esp_ble_mesh_dfu_slot_at(uint16_t img_idx);
/** @brief Get the committed DFU image slot for the image with the given
* firmware ID.
*
* @param fwid Firmware ID.
* @param fwid_len Firmware ID length.
* @param slot Slot pointer to fill.
*
* @return
* - index : Slot index
* - @c ESP_ERR_INVALID_ARG : invalid fwid parameter or invalid slot parameter
* - @c ESP_ERR_INVALID_SIZE : fwid length is zero
* - @c ESP_ERR_NOT_FOUND : no slot exists with the given firmware id
*/
int esp_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, esp_ble_mesh_dfu_slot_t **slot);
/** @brief Get the index in the firmware image list for the given slot.
*
* @param slot Slot to find.
*
* @return
* - index : Slot index
* - @c ESP_ERR_INVALID_ARG : invalid slot parameter
* - @c ESP_ERR_NOT_FOUND : The slot does not exist
*/
int esp_ble_mesh_dfu_slot_img_idx_get(const esp_ble_mesh_dfu_slot_t *slot);
#endif /* _ESP_BLE_MESH_FW_SLOT_API_H_ */
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,51 +9,86 @@
#include "esp_ble_mesh_defs.h"
#if CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI
#ifndef _BLE_MESH_MBT_DEPRECATE_WARN
#define _BLE_MESH_MBT_DEPRECATE_WARN
#warning "warning: 'All content in this document, including data structures and APIs, will be deprecated."
#endif
#endif /* CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI */
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
/** @cond */
#if (CONFIG_BLE_MESH_MBT_SRV && CONFIG_BLE_MESH_BLOB_SRV) || \
(CONFIG_BLE_MESH_MBT_CLI && CONFIG_BLE_MESH_BLOB_CLI)
#error "BLOB Transfer Model and BLOB Model cannot be enabled at the same time"
#endif
/** @endcond */
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x00)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x01)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_CANCEL ESP_BLE_MESH_MODEL_OP_2(0x83, 0x02)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_TRANSFER_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x03)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_BLOCK_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x05)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_BLOCK_START ESP_BLE_MESH_MODEL_OP_2(0x83, 0x04)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_PARTIAL_BLOCK_REPORT ESP_BLE_MESH_MODEL_OP_1(0x65)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_BLOCK_STATUS ESP_BLE_MESH_MODEL_OP_1(0x67)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_CHUNK_TRANSFER ESP_BLE_MESH_MODEL_OP_1(0x66)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_INFORMATION_GET ESP_BLE_MESH_MODEL_OP_2(0x83, 0x06)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_MODEL_OP_BLOB_INFORMATION_STATUS ESP_BLE_MESH_MODEL_OP_2(0x83, 0x07)
/** @deprecated This macro will be deprecated in future versions. */
#define ESP_BLE_MESH_BLOB_ID_SIZE 8
/** @def ESP_BLE_MESH_MODEL_MBT_CLI
/** @def ESP_BLE_MESH_MODEL_MBT_CLI
*
* @brief Define a new BLOB Transfer Client model.
* @brief Define a new BLOB Transfer Client model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Client model.
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Client model.
*
* @param cli_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to the unique struct esp_ble_mesh_client_t.
* @deprecated This macro will be deprecated in future versions.
*
* @return New BLOB Transfer Client model instance.
* @param cli_pub Pointer to unique struct esp_ble_mesh_model_pub_t.
* @param cli_data Pointer to unique struct esp_ble_mesh_client_t.
*
* @return New BLOB Transfer Client model instance.
*/
#define ESP_BLE_MESH_MODEL_MBT_CLI(cli_pub, cli_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_MBT_CLI, \
NULL, cli_pub, cli_data)
/** @def ESP_BLE_MESH_MODEL_MBT_SRV
/** @def ESP_BLE_MESH_MODEL_MBT_SRV
*
* @brief Define a new BLOB Transfer Server model.
* @brief Define a new BLOB Transfer Server model.
*
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Server model.
* @note This API needs to be called for each element on which
* the application needs to have a BLOB Transfer Server model.
*
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_blob_trans_srv_t.
* @deprecated This macro will be deprecated in future versions.
*
* @return New BLOB Transfer Server model instance.
* @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t.
* @param srv_data Pointer to the unique struct esp_ble_mesh_blob_trans_srv_t.
*
* @return New BLOB Transfer Server model instance.
*/
#define ESP_BLE_MESH_MODEL_MBT_SRV(srv_pub, srv_data) \
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_MBT_SRV, \
@@ -61,125 +96,125 @@ extern "C" {
/** BLOB Transfer Server model context */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
} esp_ble_mesh_mbt_srv_t;
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
} esp_ble_mesh_mbt_srv_t __attribute__((deprecated));
/** Parameters of BLOB receiver */
typedef struct {
uint16_t unicast_addr; /*!< Unicast address of the server */
uint8_t retrieved_transfer_phase; /*!< Retrieved transfer phase of the server */
uint8_t status:4; /*!< Status of the last operation */
uint16_t blocks_not_received_len; /*!< Indicates the length which blocks were not received by the server. */
uint8_t *blocks_not_received; /*!< Indicates which blocks were not received by the server. */
uint16_t missing_chunks_len; /*!< Indicates which chunks were not received in the current block */
uint8_t *missing_chunks; /*!< Indicates which chunks were not received by the server in the current block */
/* The followings are the additional information contained in status messages. */
uint8_t transfer_mode:2; /*!< BLOB transfer mode */
uint8_t expected_blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< Expected BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t block_size_log; /*!< Indicates the block size */
uint16_t transfer_mtu_size; /*!< MTU size in octets */
bool block_status_recv; /*!< Indicate if Blob Block Status is received as a response. */
} esp_ble_mesh_blob_receiver_t; /*!< Structure of BLOB receiver */
uint16_t unicast_addr; /*!< Unicast address of the server */
uint8_t retrieved_transfer_phase; /*!< Retrieved transfer phase of the server */
uint8_t status: 4; /*!< Status of the last operation */
uint16_t blocks_not_received_len; /*!< Indicates the length which blocks were not received by the server. */
uint8_t *blocks_not_received; /*!< Indicates which blocks were not received by the server. */
uint16_t missing_chunks_len; /*!< Indicates which chunks were not received in the current block */
uint8_t *missing_chunks; /*!< Indicates which chunks were not received by the server in the current block */
/* The following are the additional information contained in status messages. */
uint8_t transfer_mode: 2; /*!< BLOB transfer mode */
uint8_t expected_blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< Expected BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t block_size_log; /*!< Indicates the block size */
uint16_t transfer_mtu_size; /*!< MTU size in octets */
bool block_status_recv; /*!< Indicate if Blob Block Status is received as a response. */
} esp_ble_mesh_blob_receiver_t __attribute__((deprecated)); /*!< Structure of BLOB receiver */
/** Parameters of BLOB Information Status */
typedef struct {
uint8_t min_block_size_log; /*!< Min Block Size Log */
uint8_t max_block_size_log; /*!< Max Block Size Log */
uint16_t max_total_chunks; /*!< Max Total Chunks */
uint16_t max_chunk_size; /*!< Max Chunk Size */
uint32_t max_blob_size; /*!< Max BLOB Size */
uint16_t server_mtu_size; /*!< Server MTU size */
uint8_t supported_transfer_mode; /*!< Supported Transfer Mode */
} esp_ble_mesh_blob_capabilities_t; /*!< Parameters of BLOB Information Status */
uint8_t min_block_size_log; /*!< Min Block Size Log */
uint8_t max_block_size_log; /*!< Max Block Size Log */
uint16_t max_total_chunks; /*!< Max Total Chunks */
uint16_t max_chunk_size; /*!< Max Chunk Size */
uint32_t max_blob_size; /*!< Max BLOB Size */
uint16_t server_mtu_size; /*!< Server MTU size */
uint8_t supported_transfer_mode; /*!< Supported Transfer Mode */
} esp_ble_mesh_blob_capabilities_t __attribute__((deprecated)); /*!< Parameters of BLOB Information Status */
/** Parameters of BLOB retrieve capabilities */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_retrieve_capabilities_t; /*!< Parameters of BLOB retrieve capabilities */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_retrieve_capabilities_t __attribute__((deprecated)); /*!< Parameters of BLOB retrieve capabilities */
/** Parameters of BLOB transfer */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t *blob_data; /*!< BLOB data */
uint8_t transfer_mode; /*!< BLOB transfer mode */
uint16_t client_timeout_base; /*!< Time wait for messages from the serve */
} esp_ble_mesh_transfer_blob_t; /*!< Parameters of BLOB transfer */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint32_t blob_size; /*!< BLOB size in octets */
uint8_t *blob_data; /*!< BLOB data */
uint8_t transfer_mode; /*!< BLOB transfer mode */
uint16_t client_timeout_base; /*!< Time wait for messages from the serve */
} esp_ble_mesh_transfer_blob_t __attribute__((deprecated)); /*!< Parameters of BLOB transfer */
/** Parameters of BLOB Block Status message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint16_t block_number; /*!< Block number of the current block */
uint16_t chunk_size; /*!< Chunk Size (in octets) for the current block */
} esp_ble_mesh_send_block_t; /*!< BLOB Block Status message structure */
uint16_t block_number; /*!< Block number of the current block */
uint16_t chunk_size; /*!< Chunk Size (in octets) for the current block */
} esp_ble_mesh_send_block_t __attribute__((deprecated)); /*!< BLOB Block Status message structure */
/** Parameters of BLOB send message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_send_data_t; /*!< Parameters of BLOB send message */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_send_data_t __attribute__((deprecated)); /*!< Parameters of BLOB send message */
/** Parameters of determine Block Status message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_determine_block_status_t; /*!< Parameters of determine Block Status message */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_determine_block_status_t __attribute__((deprecated)); /*!< Parameters of determine Block Status message */
/** Parameters of determine Block Status message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_determine_transfer_status_t; /*!< Parameters of determine Block Status message */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
} esp_ble_mesh_determine_transfer_status_t __attribute__((deprecated)); /*!< Parameters of determine Block Status message */
/** Parameters of cancel transfer message */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
esp_ble_mesh_model_t *model; /*!< Pointer to BLOB Transfer Server model */
uint8_t msg_role; /*!< Role of the device - Node/Provisioner */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint16_t multicast_addr; /*!< Multicast Address state */
uint16_t app_idx; /*!< AppKey Index state */
uint8_t transfer_ttl; /*!< Transfer TTL state */
uint8_t unicast_addr_count; /*!< The count of unicast address */
uint16_t *unicast_addr; /*!< Unicast address list */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
} esp_ble_mesh_cancel_transfer_t; /*!< Parameters of cancel transfer message */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
} esp_ble_mesh_cancel_transfer_t __attribute__((deprecated)); /*!< Parameters of cancel transfer message */
/**
* @brief BLOB Transfer Client model procedure result
@@ -193,113 +228,113 @@ typedef struct {
typedef union {
/** Retrieve capabilities status */
struct {
int error_code; /*!< Result of starting Retrieve Capabilities procedure */
esp_ble_mesh_retrieve_capabilities_t input; /*!< Input of starting Retrieve Capabilities procedure */
} retrieve_capabilities_status; /*!< Retrieve capabilities status */
int error_code; /*!< Result of starting Retrieve Capabilities procedure */
esp_ble_mesh_retrieve_capabilities_t input; /*!< Input of starting Retrieve Capabilities procedure */
} retrieve_capabilities_status; /*!< Retrieve capabilities status */
/** Transfer BLOB status */
struct {
int error_code; /*!< Result of starting Transfer BLOB procedure */
esp_ble_mesh_transfer_blob_t input; /*!< Input of starting Transfer BLOB procedure */
} transfer_blob_status; /*!< Transfer BLOB status */
int error_code; /*!< Result of starting Transfer BLOB procedure */
esp_ble_mesh_transfer_blob_t input; /*!< Input of starting Transfer BLOB procedure */
} transfer_blob_status; /*!< Transfer BLOB status */
/** Send block status */
struct {
int error_code; /*!< Result of starting Send Block sub-procedure */
esp_ble_mesh_send_block_t input; /*!< Input of starting Send Block sub-procedure */
} send_block_status; /*!< Send block status */
int error_code; /*!< Result of starting Send Block sub-procedure */
esp_ble_mesh_send_block_t input; /*!< Input of starting Send Block sub-procedure */
} send_block_status; /*!< Send block status */
/** Send data status */
struct {
int error_code; /*!< Result of starting Send Data sub-procedure */
esp_ble_mesh_send_data_t input; /*!< Input of starting Send Data sub-procedure */
} send_data_status; /*!< Send data status */
int error_code; /*!< Result of starting Send Data sub-procedure */
esp_ble_mesh_send_data_t input; /*!< Input of starting Send Data sub-procedure */
} send_data_status; /*!< Send data status */
/** Determine block status */
struct {
int error_code; /*!< Result of starting Determine Block Status sub-procedure */
esp_ble_mesh_determine_block_status_t input; /*!< Input of starting Determine Block Status sub-procedure */
} determine_block_status_status; /*!< Determine block status */
int error_code; /*!< Result of starting Determine Block Status sub-procedure */
esp_ble_mesh_determine_block_status_t input; /*!< Input of starting Determine Block Status sub-procedure */
} determine_block_status_status; /*!< Determine block status */
/** Determine transfer status */
struct {
int error_code; /*!< Result of starting Determine Transfer Status procedure */
esp_ble_mesh_determine_transfer_status_t input; /*!< Input of starting Determine Transfer Status procedure */
} determine_transfer_status_status; /*!< Determine transfer status */
int error_code; /*!< Result of starting Determine Transfer Status procedure */
esp_ble_mesh_determine_transfer_status_t input; /*!< Input of starting Determine Transfer Status procedure */
} determine_transfer_status_status; /*!< Determine transfer status */
/** Cancel transfer status */
struct {
int error_code; /*!< Result of starting Cancel Transfer procedure */
esp_ble_mesh_cancel_transfer_t input; /*!< Input of starting Cancel Transfer procedure */
} cancel_transfer_status; /*!< Cancel transfer status */
int error_code; /*!< Result of starting Cancel Transfer procedure */
esp_ble_mesh_cancel_transfer_t input; /*!< Input of starting Cancel Transfer procedure */
} cancel_transfer_status; /*!< Cancel transfer status */
/** Retrieve capabilities complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Retrieve Capabilities procedure */
} retrieve_capabilities_comp; /*!< Retrieve capabilities complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Retrieve Capabilities procedure */
} retrieve_capabilities_comp; /*!< Retrieve capabilities complete */
/** Transfer BLOB complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Transfer BLOB procedure */
} transfer_blob_comp; /*!< Transfer BLOB complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Transfer BLOB procedure */
} transfer_blob_comp; /*!< Transfer BLOB complete */
/** Send block complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Block sub-procedure */
} send_block_comp; /*!< Send block complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Block sub-procedure */
} send_block_comp; /*!< Send block complete */
/** Send data complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Data sub-procedure */
} send_data_comp; /*!< Send data complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Send Data sub-procedure */
} send_data_comp; /*!< Send data complete */
/** Determine block status complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Block Status sub-procedure */
} determine_block_status_comp; /*!< Determine block status complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Block Status sub-procedure */
} determine_block_status_comp; /*!< Determine block status complete */
/** Determine transfer status complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Transfer Status procedure */
} determine_transfer_status_comp; /*!< Determine transfer status complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Determine Transfer Status procedure */
} determine_transfer_status_comp; /*!< Determine transfer status complete */
/** Cancel transfer complete */
struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Cancel Transfer procedure */
} cancel_transfer_comp; /*!< Cancel transfer complete */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t result; /*!< Result of Cancel Transfer procedure */
} cancel_transfer_comp; /*!< Cancel transfer complete */
/** Set transfer TTL */
struct {
int error_code; /*!< Result of setting Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} set_transfer_ttl; /*!< Set transfer TTL */
int error_code; /*!< Result of setting Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} set_transfer_ttl; /*!< Set transfer TTL */
/** Clear transfer TTL */
struct {
int error_code; /*!< Result of clearing Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_transfer_ttl; /*!< Clear transfer TTL */
int error_code; /*!< Result of clearing Transfer TTL state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_transfer_ttl; /*!< Clear transfer TTL */
/** Set application index */
struct {
int error_code; /*!< Result of setting AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t app_idx; /*!< AppKey Index state */
} set_app_idx; /*!< Set application index */
int error_code; /*!< Result of setting AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t app_idx; /*!< AppKey Index state */
} set_app_idx; /*!< Set application index */
/** Clear application index */
struct {
int error_code; /*!< Result of clearing AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_app_idx; /*!< Clear application index */
int error_code; /*!< Result of clearing AppKey Index state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_app_idx; /*!< Clear application index */
/** Set multicast address */
struct {
int error_code; /*!< Result of setting Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t multicast_addr; /*!< Multicast Address state */
} set_multicast_addr; /*!< Set multicast address */
int error_code; /*!< Result of setting Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint16_t multicast_addr; /*!< Multicast Address state */
} set_multicast_addr; /*!< Set multicast address */
/** Clear multicast address */
struct {
int error_code; /*!< Result of clearing Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_multicast_addr; /*!< Clear multicast address */
} esp_ble_mesh_mbt_client_cb_value_t; /*!< BLOB Transfer Client model callback values union */
int error_code; /*!< Result of clearing Multicast Address state */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
} clear_multicast_addr; /*!< Clear multicast address */
} esp_ble_mesh_mbt_client_cb_value_t; /*!< BLOB Transfer Client model callback values union */
/** BLOB Transfer Client model callback parameters */
typedef struct {
esp_ble_mesh_mbt_client_cb_value_t value; /*!< BLOB Transfer Client model callback values */
} esp_ble_mesh_mbt_client_cb_param_t; /*!< BLOB Transfer Client model callback parameters */
esp_ble_mesh_mbt_client_cb_value_t value; /*!< BLOB Transfer Client model callback values */
} esp_ble_mesh_mbt_client_cb_param_t __attribute__((deprecated)); /*!< BLOB Transfer Client model callback parameters */
/**
* This enum value is the event of BLOB Transfer Client model.
@@ -327,30 +362,30 @@ typedef enum {
ESP_BLE_MESH_MBT_CLIENT_SET_MULTICAST_ADDR_COMP_EVT,
ESP_BLE_MESH_MBT_CLIENT_CLEAR_MULTICAST_ADDR_COMP_EVT,
ESP_BLE_MESH_MBT_CLIENT_EVT_MAX,
} esp_ble_mesh_mbt_client_cb_event_t;
} esp_ble_mesh_mbt_client_cb_event_t __attribute__((deprecated));
/** Parameters of initialize BLOB receive */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint16_t timeout; /*!< Timeout */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_initialize_blob_receive_t; /*!< Structure of initialize BLOB receive */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
uint16_t timeout; /*!< Timeout */
uint8_t transfer_ttl; /*!< Transfer TTL state */
} esp_ble_mesh_initialize_blob_receive_t __attribute__((deprecated)); /*!< Structure of initialize BLOB receive */
/** Parameters of cancel BLOB receive */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
uint8_t blob_id[ESP_BLE_MESH_BLOB_ID_SIZE]; /*!< BLOB identifier list */
} esp_ble_mesh_cancel_blob_receive_t;/*!< */
} esp_ble_mesh_cancel_blob_receive_t __attribute__((deprecated));/*!< */
/** Parameters of cancel BLOB receive */
typedef struct {
esp_ble_mesh_model_t *model; /*!< Pointer to the BLOB Transfer Client model */
esp_ble_mesh_blob_capabilities_t caps; /*!< Parameters of BLOB Information Status */
} esp_ble_mesh_set_blob_capabilities_t;/*!< */
} esp_ble_mesh_set_blob_capabilities_t __attribute__((deprecated));
/**
* @brief BLOB Transfer Server model callback value union
@@ -358,61 +393,61 @@ typedef struct {
typedef union {
/** Initialize BLOB receive complete */
struct {
int error_code; /*!< Result of initializing BLOB receive */
esp_ble_mesh_initialize_blob_receive_t input; /*!< Input of initializing BLOB receive */
} initialize_blob_receive_comp; /*!< Initialize BLOB receive complete */
int error_code; /*!< Result of initializing BLOB receive */
esp_ble_mesh_initialize_blob_receive_t input; /*!< Input of initializing BLOB receive */
} initialize_blob_receive_comp; /*!< Initialize BLOB receive complete */
/** Cancel BLOB receive complete */
struct {
int error_code; /*!< Result of canceling BLOB receive */
esp_ble_mesh_cancel_blob_receive_t input; /*!< Input of canceling BLOB receive */
} cancel_blob_receive_comp; /*!< Cancel BLOB receive complete */
int error_code; /*!< Result of canceling BLOB receive */
esp_ble_mesh_cancel_blob_receive_t input; /*!< Input of canceling BLOB receive */
} cancel_blob_receive_comp; /*!< Cancel BLOB receive complete */
/** Set BLOB capabilities complete */
struct {
int error_code; /*!< Result of setting BLOB capabilities */
esp_ble_mesh_set_blob_capabilities_t input; /*!< Input of setting BLOB capabilities */
} set_blob_capabilities_comp; /*!< Set BLOB capabilities complete */
int error_code; /*!< Result of setting BLOB capabilities */
esp_ble_mesh_set_blob_capabilities_t input; /*!< Input of setting BLOB capabilities */
} set_blob_capabilities_comp; /*!< Set BLOB capabilities complete */
/** BLOB transfer get */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Get message context */
} blob_transfer_get; /*!< BLOB transfer get */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Get message context */
} blob_transfer_get; /*!< BLOB transfer get */
/** BLOB transfer start */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Start message context */
} blob_transfer_start; /*!< BLOB transfer start */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Start message context */
} blob_transfer_start; /*!< BLOB transfer start */
/** BLOB transfer cancel */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Cancel message context */
} blob_transfer_cancel; /*!< BLOB transfer cancel */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Transfer Cancel message context */
} blob_transfer_cancel; /*!< BLOB transfer cancel */
/** BLOB block get */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Get message context */
} blob_block_get; /*!< BLOB block get */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Get message context */
} blob_block_get; /*!< BLOB block get */
/** BLOB block start */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Start message context */
} blob_block_start; /*!< BLOB block start */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Block Start message context */
} blob_block_start; /*!< BLOB block start */
/** BLOB chunk transfer */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Chunk Transfer message context */
} blob_chunk_transfer; /*!< BLOB chunk transfer */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Chunk Transfer message context */
} blob_chunk_transfer; /*!< BLOB chunk transfer */
/** BLOB information get */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Information Get message context */
} blob_information_get; /*!< BLOB information get */
esp_ble_mesh_msg_ctx_t ctx; /*!< BLOB Information Get message context */
} blob_information_get; /*!< BLOB information get */
/** Block receive complete */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB block completely */
} block_receive_comp; /*!< Block receive complete */
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB block completely */
} block_receive_comp; /*!< Block receive complete */
/** BLOB receive complete */
struct {
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB completely */
} blob_receive_comp; /*!< BLOB receive complete */
} esp_ble_mesh_mbt_server_cb_value_t; /*!< BLOB Transfer Server model callback value union */
esp_ble_mesh_msg_ctx_t ctx; /*!< Information of receiving BLOB completely */
} blob_receive_comp; /*!< BLOB receive complete */
} esp_ble_mesh_mbt_server_cb_value_t __attribute__((deprecated)); /*!< BLOB Transfer Server model callback value union */
/** BLOB Transfer Server model callback parameters */
typedef struct {
esp_ble_mesh_mbt_server_cb_value_t value; /*!< Value of the received blob transfer messages */
} esp_ble_mesh_mbt_server_cb_param_t; /*!< BLOB Transfer Server model callback parameters */
esp_ble_mesh_mbt_server_cb_value_t value; /*!< Value of the received blob transfer messages */
} esp_ble_mesh_mbt_server_cb_param_t __attribute__((deprecated)); /*!< BLOB Transfer Server model callback parameters */
/** This enum value is the event of BLOB Transfer Server model */
typedef enum {
@@ -430,7 +465,7 @@ typedef enum {
ESP_BLE_MESH_MBT_SERVER_BLOB_RECEIVE_COMP_EVT,
ESP_BLE_MESH_MBT_SERVER_BLOB_RECEIVE_TIMEOUT_EVT,
ESP_BLE_MESH_MBT_SERVER_EVT_MAX,
} esp_ble_mesh_mbt_server_cb_event_t;
} esp_ble_mesh_mbt_server_cb_event_t __attribute__((deprecated));
/**
* @brief BLOB Transfer Client model callback function type
@@ -453,96 +488,116 @@ typedef void (* esp_ble_mesh_mbt_server_cb_t)(esp_ble_mesh_mbt_server_cb_event_t
/**
* @brief Register BLE Mesh BLOB Transfer Client model callback.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] callback: Pointer to the callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback);
esp_err_t esp_ble_mesh_register_mbt_client_callback(esp_ble_mesh_mbt_client_cb_t callback) __attribute__((deprecated));
/**
* @brief Register BLE Mesh BLOB Transfer Server model callback.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] callback: Pointer to the callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback);
esp_err_t esp_ble_mesh_register_mbt_server_callback(esp_ble_mesh_mbt_server_cb_t callback) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Retrieve Capabilities procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Retrieve Capabilities procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input);
esp_err_t esp_ble_mesh_mbt_client_retrieve_capabilities(esp_ble_mesh_retrieve_capabilities_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Transfer BLOB procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Transfer BLOB procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input);
esp_err_t esp_ble_mesh_mbt_client_transfer_blob(esp_ble_mesh_transfer_blob_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Send Block sub-procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Send Block sub-procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input);
esp_err_t esp_ble_mesh_mbt_client_send_block(esp_ble_mesh_send_block_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Send Data sub-procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Send Data sub-procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input);
esp_err_t esp_ble_mesh_mbt_client_send_data(esp_ble_mesh_send_data_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Determine Block Status sub-procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Determine Block Status sub-procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input);
esp_err_t esp_ble_mesh_mbt_client_determine_block_status(esp_ble_mesh_determine_block_status_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Determine Transfer Status procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Determine Transfer Status procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input);
esp_err_t esp_ble_mesh_mbt_client_determine_transfer_status(esp_ble_mesh_determine_transfer_status_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client starts Cancel Transfer procedure.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of Cancel Transfer procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input);
esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client gets BLOB receiver.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] unicast_addr: Unicast address of the BLOB receiver.
*
@@ -550,21 +605,25 @@ esp_err_t esp_ble_mesh_mbt_client_cancel_transfer(esp_ble_mesh_cancel_transfer_t
*
*/
const esp_ble_mesh_blob_receiver_t *esp_ble_mesh_mbt_client_get_blob_receiver(esp_ble_mesh_model_t *model,
uint16_t unicast_addr);
uint16_t unicast_addr) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client gets active BLOB receiver list.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return Active BLOB receiver list on success or NULL on failure.
*
*/
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model);
const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_receiver(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client gets BLOB transfer progress.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] unicast_addr: Unicast address of the BLOB receiver.
* @param[in] block_percent: Block reception percent to be updated.
@@ -576,11 +635,13 @@ const esp_ble_mesh_blob_receiver_t **esp_ble_mesh_mbt_client_get_active_blob_rec
esp_err_t esp_ble_mesh_mbt_client_get_transfer_progress(esp_ble_mesh_model_t *model,
uint16_t unicast_addr,
uint8_t *block_percent,
uint8_t *chunk_percent);
uint8_t *chunk_percent) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client sets Transfer TTL state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] transfer_ttl: Transfer TTL state value.
*
@@ -588,21 +649,25 @@ esp_err_t esp_ble_mesh_mbt_client_get_transfer_progress(esp_ble_mesh_model_t *mo
*
*/
esp_err_t esp_ble_mesh_mbt_client_set_transfer_ttl(esp_ble_mesh_model_t *model,
uint8_t transfer_ttl);
uint8_t transfer_ttl) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client clear Transfer TTL state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model);
esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client sets AppKey Index state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] app_idx: AppKey Index state value.
*
@@ -610,21 +675,25 @@ esp_err_t esp_ble_mesh_mbt_client_clear_transfer_ttl(esp_ble_mesh_model_t *model
*
*/
esp_err_t esp_ble_mesh_mbt_client_set_app_idx(esp_ble_mesh_model_t *model,
uint16_t app_idx);
uint16_t app_idx) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client clear AppKey Index state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model);
esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client sets Multicast Address state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
* @param[in] multicast_addr: Multicast Address state value.
*
@@ -632,51 +701,61 @@ esp_err_t esp_ble_mesh_mbt_client_clear_app_idx(esp_ble_mesh_model_t *model);
*
*/
esp_err_t esp_ble_mesh_mbt_client_set_multicast_addr(esp_ble_mesh_model_t *model,
uint16_t multicast_addr);
uint16_t multicast_addr) __attribute__((deprecated));
/**
* @brief BLOB Transfer Client clear Multicast Address state.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model);
esp_err_t esp_ble_mesh_mbt_client_clear_multicast_addr(esp_ble_mesh_model_t *model) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server initializes BLOB receive.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of initializing BLOB receive.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input);
esp_err_t esp_ble_mesh_mbt_server_initialize_blob_receive(esp_ble_mesh_initialize_blob_receive_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server cancels BLOB receive.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of cancelling BLOB receive.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input);
esp_err_t esp_ble_mesh_mbt_server_cancel_blob_receive(esp_ble_mesh_cancel_blob_receive_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server sets BLOB capabilities.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] input: The input of setting BLOB capabilities.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input);
esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_capabilities_t *input) __attribute__((deprecated));
/**
* @brief BLOB Transfer Server gets current BLOB reception progress.
*
* @deprecated This function will be deprecated in future versions.
*
* @param[in] model: BLOB Transfer Server model.
* @param[in] reception_progress: Reception progress to be updated.
*
@@ -684,7 +763,11 @@ esp_err_t esp_ble_mesh_mbt_server_set_blob_capabilities(esp_ble_mesh_set_blob_ca
*
*/
esp_err_t esp_ble_mesh_mbt_server_get_blob_reception_progress(esp_ble_mesh_model_t *model,
uint8_t *reception_progress);
uint8_t *reception_progress) __attribute__((deprecated));
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
}
@@ -0,0 +1,414 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "btc_ble_mesh_model_common.h"
#include "btc_ble_mesh_dfu_model.h"
#include "esp_ble_mesh_dfu_model_api.h"
#include "mesh_v1.1/dfu/dfu_cli.h"
#include "mesh_v1.1/dfu/dfu_srv.h"
#if CONFIG_BLE_MESH_DFU_CLI
/* Device Firmware Update Client model related functions */
static inline void btc_ble_mesh_dfu_client_cb_to_app(btc_ble_mesh_dfu_client_cb_evt_t event,
esp_ble_mesh_dfu_client_cb_param_t *param)
{
esp_ble_mesh_dfu_client_cb_t btc_ble_mesh_cb =
btc_profile_cb_get(BTC_PID_DFU_CLIENT);
if (btc_ble_mesh_cb) {
btc_ble_mesh_cb(event, param);
}
}
void btc_ble_mesh_dfu_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
{
btc_ble_mesh_dfu_client_args_t *dst = p_dest;
btc_ble_mesh_dfu_client_args_t *src = p_src;
if (!msg || !dst || !src) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
switch (msg->act) {
case BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE: {
dst->dfu_get.params = bt_mesh_calloc(sizeof(esp_ble_mesh_client_common_param_t));
if (dst->dfu_get.params) {
memcpy(dst->dfu_get.params, src->dfu_get.params,
sizeof(esp_ble_mesh_client_common_param_t));
} else {
BT_ERR("%s, Out of memory, act %d", __func__, msg->act);
break;
}
if (src->dfu_get.get) {
dst->dfu_get.get = bt_mesh_calloc(sizeof(esp_ble_mesh_dfu_client_get_t));
if (dst->dfu_get.get) {
memcpy(dst->dfu_get.get, src->dfu_get.get,
sizeof(esp_ble_mesh_dfu_client_get_t));
if (src->dfu_get.params->opcode == ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK) {
if (src->dfu_get.get->dfu_metadata_check.metadata) {
dst->dfu_get.get->dfu_metadata_check.metadata = bt_mesh_alloc_buf(src->dfu_get.get->dfu_metadata_check.metadata->len);
if (dst->dfu_get.get->dfu_metadata_check.metadata) {
net_buf_simple_add_mem(dst->dfu_get.get->dfu_metadata_check.metadata,
src->dfu_get.get->dfu_metadata_check.metadata->data,
src->dfu_get.get->dfu_metadata_check.metadata->len);
} else {
BT_ERR("Out of memory for metadata");
return;
}
} else {
BT_ERR("Metadata should be exists");
return;
}
}
} else {
BT_ERR("%s, Out of memory, act %d", __func__, msg->act);
}
}
break;
}
default:
BT_DBG("%s, Unknown act %d", __func__, msg->act);
break;
}
}
void btc_ble_mesh_dfu_client_arg_deep_free(btc_msg_t *msg)
{
btc_ble_mesh_dfu_client_args_t *arg = NULL;
if (!msg) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
arg = (btc_ble_mesh_dfu_client_args_t *)msg->arg;
switch (msg->act) {
case BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE:
if (arg->dfu_get.params) {
bt_mesh_free(arg->dfu_get.params);
}
if (arg->dfu_get.get) {
bt_mesh_free(arg->dfu_get.get);
}
break;
default:
break;
}
}
static void btc_ble_mesh_dfu_client_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src)
{
esp_ble_mesh_dfu_client_cb_param_t *p_dest_data = p_dest;
esp_ble_mesh_dfu_client_cb_param_t *p_src_data = p_src;
uint16_t length = 0;
if (!msg || !p_src_data || !p_dest_data) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
if (p_src_data->params) {
p_dest_data->params = bt_mesh_calloc(sizeof(esp_ble_mesh_client_common_param_t));
if (!p_dest_data->params) {
BT_ERR("%s, Out of memory, act %d", __func__, msg->act);
return;
}
memcpy(p_dest_data->params, p_src_data->params, sizeof(esp_ble_mesh_client_common_param_t));
}
switch (msg->act) {
case ESP_BLE_MESH_DFU_CLIENT_RECV_GET_RSP_EVT:
if (p_src_data->params) {
switch (p_src_data->params->opcode) {
case ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET:
if (p_src_data->recv.dfu_update_info_status.fw_info_list_cnt) {
length = p_src_data->recv.dfu_update_info_status.fw_info_list_cnt * sizeof(esp_ble_mesh_firmware_info_t);
p_dest_data->recv.dfu_update_info_status.fw_info_list = bt_mesh_calloc(length);
if (!p_dest_data->recv.dfu_update_info_status.fw_info_list) {
BT_ERR("%s, Out of memory, act %d", __func__, msg->act);
return;
}
memcpy(p_dest_data->recv.dfu_update_info_status.fw_info_list,
p_src_data->recv.dfu_update_info_status.fw_info_list,
length);
}
break;
default:
break;
}
}
case ESP_BLE_MESH_DFU_CLIENT_SEND_COMP_EVT:
case ESP_BLE_MESH_DFU_CLIENT_TIMEOUT_EVT:
case ESP_BLE_MESH_DFU_CLIENT_IMG_SEND_CMP_EVT:
break;
default:
break;
}
}
static void btc_ble_mesh_dfu_client_free_req_data(btc_msg_t *msg)
{
esp_ble_mesh_dfu_client_cb_param_t *arg = NULL;
if (!msg) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
if (msg->act >= ESP_BLE_MESH_DFU_CLIENT_EVT_MAX) {
BT_ERR("%s, Invalid event %d", msg->act);
return;
}
arg = (esp_ble_mesh_dfu_client_cb_param_t *)msg->arg;
switch (msg->act) {
case ESP_BLE_MESH_DFU_CLIENT_RECV_GET_RSP_EVT:
if (arg->params) {
switch (arg->params->opcode) {
case ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET:
bt_mesh_free(arg->recv.dfu_update_info_status.fw_info_list);
break;
default:
break;
}
}
case ESP_BLE_MESH_DFU_CLIENT_SEND_COMP_EVT:
case ESP_BLE_MESH_DFU_CLIENT_TIMEOUT_EVT:
case ESP_BLE_MESH_DFU_CLIENT_IMG_SEND_CMP_EVT:
break;
default:
BT_WARN("Unprocessed event %d", msg->act);
break;
}
if (arg->params) {
bt_mesh_free(arg->params);
}
return;
}
static void btc_ble_mesh_dfu_client_cb(esp_ble_mesh_dfu_client_cb_param_t *cb_params, uint8_t act)
{
btc_msg_t msg = {0};
/* If corresponding callback is not registered, event will not be posted. */
if (!btc_profile_cb_get(BTC_PID_DFU_CLIENT)) {
return;
}
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_DFU_CLIENT;
msg.act = act;
btc_transfer_context(&msg, cb_params, sizeof(esp_ble_mesh_dfu_client_cb_param_t),
btc_ble_mesh_dfu_client_copy_req_data,
btc_ble_mesh_dfu_client_free_req_data);
}
void bt_mesh_dfu_client_cb_evt_to_btc(uint32_t opcode, uint8_t event,
struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
const uint8_t *val, size_t len)
{
esp_ble_mesh_dfu_client_cb_param_t cb_params = {0};
esp_ble_mesh_client_common_param_t params = {0};
uint8_t act = 0;
if (!model || !ctx || len > sizeof(cb_params.recv)) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
switch (event) {
case BTC_BLE_MESH_EVT_DFU_CLIENT_TIMEOUT:
act = ESP_BLE_MESH_DFU_CLIENT_TIMEOUT_EVT;
break;
case BTC_BLE_MESH_EVT_DFU_CLIENT_RECV_GET_RSP:
act = ESP_BLE_MESH_DFU_CLIENT_RECV_GET_RSP_EVT;
break;
case BTC_BLE_MESH_EVT_DFU_CLIENT_IMG_SEND_CMP:
act = ESP_BLE_MESH_DFU_CLIENT_IMG_SEND_CMP_EVT;
break;
default:
BT_ERR("Unknown Device Firmware Update client event type %d", event);
return;
}
params.opcode = opcode;
params.model = (esp_ble_mesh_model_t *)model;
params.ctx.net_idx = ctx->net_idx;
params.ctx.app_idx = ctx->app_idx;
params.ctx.addr = ctx->addr;
params.ctx.recv_ttl = ctx->recv_ttl;
params.ctx.recv_op = ctx->recv_op;
params.ctx.recv_dst = ctx->recv_dst;
params.ctx.recv_rssi = ctx->recv_rssi;
params.ctx.send_ttl = ctx->send_ttl;
cb_params.params = &params;
if (val && len) {
memcpy(&cb_params.recv, val, len);
}
btc_ble_mesh_dfu_client_cb(&cb_params, act);
}
static int btc_ble_mesh_dfu_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_dfu_client_get_t *get)
{
bt_mesh_client_common_param_t param = {0};
struct bt_mesh_dfu_cli *dfu_cli = NULL;
if (params == NULL ||
params->model == NULL ||
params->model->user_data == NULL) {
BT_ERR("%s, Invalid parameter %d %p %p", __func__, params == NULL, params->model, params->model->user_data);
return -EINVAL;
}
dfu_cli = (struct bt_mesh_dfu_cli *)params->model->user_data;
switch (params->opcode) {
case ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET:
case ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK:
case ESP_BLE_MESH_DFU_OP_UPDATE_START:
if (get == NULL) {
BT_ERR("Invalid Device Firmware Update Get");
return -EINVAL;
}
break;
default:
break;
}
btc_ble_mesh_set_client_common_param(params, &param, false);
switch (param.opcode) {
case ESP_BLE_MESH_DFU_OP_UPDATE_INFO_GET:
return bt_mesh_dfu_cli_imgs_get(dfu_cli, &param.ctx, (bt_mesh_dfu_img_cb_t) get->dfu_update_info_get.img_cb,
NULL, get->dfu_update_info_get.first_index,
get->dfu_update_info_get.entries_limit);
case ESP_BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK:
return bt_mesh_dfu_cli_metadata_check(dfu_cli, &param.ctx, get->dfu_metadata_check.update_firmware_index,
get->dfu_metadata_check.metadata);
case ESP_BLE_MESH_DFU_OP_UPDATE_GET:
return bt_mesh_dfu_cli_status_get(dfu_cli, &param.ctx);
case ESP_BLE_MESH_DFU_OP_UPDATE_START:
// automatic start
return 0;
case ESP_BLE_MESH_DFU_OP_UPDATE_CANCEL:
return bt_mesh_dfu_cli_cancel(dfu_cli, &param.ctx);
case ESP_BLE_MESH_DFU_OP_UPDATE_APPLY:
return bt_mesh_dfu_cli_apply(dfu_cli);
default:
BT_ERR("Invalid Device firmware Get opcode 0x%04x", param.opcode);
return -EINVAL;
}
}
void btc_ble_mesh_dfu_client_call_handler(btc_msg_t *msg)
{
esp_ble_mesh_dfu_client_cb_param_t cb = {0};
btc_ble_mesh_dfu_client_args_t *arg = NULL;
if (!msg) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
arg = (btc_ble_mesh_dfu_client_args_t *)msg->arg;
switch (msg->act) {
case BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE:
cb.params = arg->dfu_get.params;
cb.send.err_code = btc_ble_mesh_dfu_client_get_state(arg->dfu_get.params,
arg->dfu_get.get);
btc_ble_mesh_dfu_client_cb(&cb,
ESP_BLE_MESH_DFU_CLIENT_SEND_COMP_EVT);
break;
case BTC_BLE_MESH_ACT_DFU_CLIENT_IMG_SEND:
cb.send.err_code = bt_mesh_dfu_cli_send((struct bt_mesh_dfu_cli *)arg->send_arg.cli,
(struct bt_mesh_blob_cli_inputs *)arg->send_arg.inputs,
(struct bt_mesh_blob_io *)arg->send_arg.io,
(struct bt_mesh_dfu_cli_xfer *)arg->send_arg.xfer);
btc_ble_mesh_dfu_client_cb(&cb,
ESP_BLE_MESH_DFU_CLIENT_IMG_SEND_CMP_EVT);
break;
default:
break;
}
btc_ble_mesh_dfu_client_arg_deep_free(msg);
}
void btc_ble_mesh_dfu_client_cb_handler(btc_msg_t *msg)
{
esp_ble_mesh_dfu_client_cb_param_t *arg = NULL;
if (!msg) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
arg = (esp_ble_mesh_dfu_client_cb_param_t *)msg->arg;
if (msg->act < ESP_BLE_MESH_DFU_CLIENT_EVT_MAX) {
btc_ble_mesh_dfu_client_cb_to_app(msg->act, arg);
} else {
BT_ERR("%s, Unknown act %d", __func__, msg->act);
}
btc_ble_mesh_dfu_client_free_req_data(msg);
}
uint8_t btc_ble_mesh_dfu_cli_progress(struct esp_ble_mesh_dfu_cli *cli)
{
return bt_mesh_dfu_cli_progress((struct bt_mesh_dfu_cli *)cli);
}
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
void btc_ble_mesh_dfu_srv_verified(esp_ble_mesh_dfu_srv_t *srv)
{
bt_mesh_dfu_srv_verified((struct bt_mesh_dfu_srv *)srv);
}
void btc_ble_mesh_dfu_srv_rejected(esp_ble_mesh_dfu_srv_t *srv)
{
bt_mesh_dfu_srv_rejected((struct bt_mesh_dfu_srv *)srv);
}
void btc_ble_mesh_dfu_srv_cancel(esp_ble_mesh_dfu_srv_t *srv)
{
bt_mesh_dfu_srv_cancel((struct bt_mesh_dfu_srv *)srv);
}
void btc_ble_mesh_dfu_srv_applied(esp_ble_mesh_dfu_srv_t *srv)
{
bt_mesh_dfu_srv_applied((struct bt_mesh_dfu_srv *)srv);
}
bool btc_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv)
{
return bt_mesh_dfu_srv_is_busy((struct bt_mesh_dfu_srv *)srv);
}
uint8_t btc_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv)
{
return bt_mesh_dfu_srv_progress((struct bt_mesh_dfu_srv *)srv);
}
#endif /* CONFIG_BLE_MESH_DFU_SRV */
@@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "dfu_slot.h"
#include "esp_ble_mesh_dfu_model_api.h"
#include "esp_ble_mesh_dfu_slot_api.h"
#include "btc_ble_mesh_dfu_slot.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
int btc_ble_mesh_dfu_slot_count(void)
{
return bt_mesh_dfu_slot_count();
}
struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_reserve(void)
{
return (struct esp_ble_mesh_dfu_slot *)bt_mesh_dfu_slot_reserve();
}
int btc_ble_mesh_dfu_slot_info_set(struct esp_ble_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len)
{
return bt_mesh_dfu_slot_info_set((struct bt_mesh_dfu_slot *) dfu_slot, size,
metadata, metadata_len);
}
int btc_ble_mesh_dfu_slot_fwid_set(struct esp_ble_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len)
{
return bt_mesh_dfu_slot_fwid_set((struct bt_mesh_dfu_slot *) dfu_slot, fwid,
fwid_len);
}
int btc_ble_mesh_dfu_slot_commit(struct esp_ble_mesh_dfu_slot *dfu_slot)
{
return bt_mesh_dfu_slot_commit((struct bt_mesh_dfu_slot *) dfu_slot);
}
void btc_ble_mesh_dfu_slot_release(const struct esp_ble_mesh_dfu_slot *dfu_slot)
{
bt_mesh_dfu_slot_release((const struct bt_mesh_dfu_slot *)dfu_slot);
}
int btc_ble_mesh_dfu_slot_del(const struct esp_ble_mesh_dfu_slot *slot)
{
return bt_mesh_dfu_slot_del((const struct bt_mesh_dfu_slot *)slot);
}
void btc_ble_mesh_dfu_slot_del_all(void)
{
bt_mesh_dfu_slot_del_all();
}
const struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_at(uint16_t img_idx)
{
return (const struct esp_ble_mesh_dfu_slot *)bt_mesh_dfu_slot_at(img_idx);
}
int btc_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct esp_ble_mesh_dfu_slot **slot)
{
return bt_mesh_dfu_slot_get(fwid, fwid_len, (struct bt_mesh_dfu_slot **)slot);
}
int btc_ble_mesh_dfu_slot_img_idx_get(const struct esp_ble_mesh_dfu_slot *slot)
{
return bt_mesh_dfu_slot_img_idx_get((const struct bt_mesh_dfu_slot *)slot);
}
size_t btc_ble_mesh_dfu_slot_foreach(esp_ble_mesh_dfu_slot_cb_t cb, void *user_data)
{
return bt_mesh_dfu_slot_foreach((bt_mesh_dfu_slot_cb_t)cb, user_data);
}
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */
@@ -0,0 +1,74 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BTC_BLE_MESH_DFU_MODEL_H_
#define _BTC_BLE_MESH_DFU_MODEL_H_
#include "btc/btc_manage.h"
#include "esp_ble_mesh_dfu_model_api.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_BLE_MESH_DFU_CLI
typedef enum {
BTC_BLE_MESH_ACT_DFU_CLIENT_GET_STATE,
BTC_BLE_MESH_ACT_DFU_CLIENT_IMG_SEND,
BTC_BLE_MESH_ACT_DFU_CLIENT_MAX,
} btc_ble_mesh_dfu_client_act_t;
typedef union {
struct {
esp_ble_mesh_client_common_param_t *params;
esp_ble_mesh_dfu_client_get_t *get;
} dfu_get;
struct {
struct esp_ble_mesh_dfu_cli *cli;
struct esp_ble_mesh_blob_cli_inputs *inputs;
struct esp_ble_mesh_blob_io *io;
struct esp_ble_mesh_dfu_cli_xfer *xfer;
} send_arg;
} btc_ble_mesh_dfu_client_args_t;
typedef enum {
BTC_BLE_MESH_EVT_DFU_CLIENT_TIMEOUT,
BTC_BLE_MESH_EVT_DFU_CLIENT_RECV_GET_RSP,
BTC_BLE_MESH_EVT_DFU_CLIENT_IMG_SEND_CMP,
BTC_BLE_MESH_EVT_DFU_CLIENT_MAX,
} btc_ble_mesh_dfu_client_cb_evt_t;
void btc_ble_mesh_dfu_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
void btc_ble_mesh_dfu_client_arg_deep_free(btc_msg_t *msg);
void bt_mesh_dfu_client_cb_evt_to_btc(uint32_t opcode, uint8_t event,
struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
const uint8_t *val, size_t len);
void btc_ble_mesh_dfu_client_call_handler(btc_msg_t *msg);
void btc_ble_mesh_dfu_client_cb_handler(btc_msg_t *msg);
uint8_t btc_ble_mesh_dfu_cli_progress(struct esp_ble_mesh_dfu_cli *cli);
#endif /* CONFIG_BLE_MESH_DFU_CLI */
#if CONFIG_BLE_MESH_DFU_SRV
void btc_ble_mesh_dfu_srv_verified(esp_ble_mesh_dfu_srv_t *srv);
void btc_ble_mesh_dfu_srv_rejected(esp_ble_mesh_dfu_srv_t *srv);
void btc_ble_mesh_dfu_srv_cancel(esp_ble_mesh_dfu_srv_t *srv);
void btc_ble_mesh_dfu_srv_applied(esp_ble_mesh_dfu_srv_t *srv);
bool btc_ble_mesh_dfu_srv_is_busy(const esp_ble_mesh_dfu_srv_t *srv);
uint8_t btc_ble_mesh_dfu_srv_progress(const esp_ble_mesh_dfu_srv_t *srv);
#endif /* CONFIG_BLE_MESH_DFU_SRV */
#ifdef __cplusplus
}
#endif
#endif /* _BTC_BLE_MESH_DFU_MODEL_H_ */
@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BTC_BLE_MESH_DFU_SLOT_H_
#define _BTC_BLE_MESH_DFU_SLOT_H_
int btc_ble_mesh_dfu_slot_count(void);
struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_reserve(void);
int btc_ble_mesh_dfu_slot_info_set(struct esp_ble_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len);
int btc_ble_mesh_dfu_slot_fwid_set(struct esp_ble_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len);
int btc_ble_mesh_dfu_slot_commit(struct esp_ble_mesh_dfu_slot *dfu_slot);
void btc_ble_mesh_dfu_slot_release(const struct esp_ble_mesh_dfu_slot *dfu_slot);
int btc_ble_mesh_dfu_slot_del(const struct esp_ble_mesh_dfu_slot *slot);
void btc_ble_mesh_dfu_slot_del_all(void);
const struct esp_ble_mesh_dfu_slot *btc_ble_mesh_dfu_slot_at(uint16_t img_idx);
int btc_ble_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct esp_ble_mesh_dfu_slot **slot);
int btc_ble_mesh_dfu_slot_img_idx_get(const struct esp_ble_mesh_dfu_slot *slot);
size_t btc_ble_mesh_dfu_slot_foreach(esp_ble_mesh_dfu_slot_cb_t cb, void *user_data);
#endif /* _BTC_BLE_MESH_DFU_SLOT_H_ */
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,6 +14,11 @@
extern "C" {
#endif
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
typedef enum {
BTC_BLE_MESH_ACT_MBT_CLIENT_RETRIEVE_CAPABILITIES,
BTC_BLE_MESH_ACT_MBT_CLIENT_TRANSFER_BLOB,
@@ -136,6 +141,10 @@ void bt_mesh_mbt_server_cb_evt_to_btc(uint8_t event,
struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx);
#if CONFIG_IDF_CI_BUILD
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
}
#endif
+35
View File
@@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "access.h"
/* @todo: adapt to dfd client */
#if CONFIG_BLE_MESH_DFD_SRV
#define BT_MESH_DFD_OP_RECEIVERS_ADD BLE_MESH_MODEL_OP_2(0x83, 0x11)
#define BT_MESH_DFD_OP_RECEIVERS_DELETE_ALL BLE_MESH_MODEL_OP_2(0x83, 0x12)
#define BT_MESH_DFD_OP_RECEIVERS_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x13)
#define BT_MESH_DFD_OP_RECEIVERS_GET BLE_MESH_MODEL_OP_2(0x83, 0x14)
#define BT_MESH_DFD_OP_RECEIVERS_LIST BLE_MESH_MODEL_OP_2(0x83, 0x15)
#define BT_MESH_DFD_OP_CAPABILITIES_GET BLE_MESH_MODEL_OP_2(0x83, 0x16)
#define BT_MESH_DFD_OP_CAPABILITIES_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x17)
#define BT_MESH_DFD_OP_GET BLE_MESH_MODEL_OP_2(0x83, 0x18)
#define BT_MESH_DFD_OP_START BLE_MESH_MODEL_OP_2(0x83, 0x19)
#define BT_MESH_DFD_OP_SUSPEND BLE_MESH_MODEL_OP_2(0x83, 0x1a)
#define BT_MESH_DFD_OP_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x1b)
#define BT_MESH_DFD_OP_APPLY BLE_MESH_MODEL_OP_2(0x83, 0x1c)
#define BT_MESH_DFD_OP_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x1d)
#define BT_MESH_DFD_OP_UPLOAD_GET BLE_MESH_MODEL_OP_2(0x83, 0x1e)
#define BT_MESH_DFD_OP_UPLOAD_START BLE_MESH_MODEL_OP_2(0x83, 0x1f)
#define BT_MESH_DFD_OP_UPLOAD_START_OOB BLE_MESH_MODEL_OP_2(0x83, 0x20)
#define BT_MESH_DFD_OP_UPLOAD_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x21)
#define BT_MESH_DFD_OP_UPLOAD_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x22)
#define BT_MESH_DFD_OP_FW_GET BLE_MESH_MODEL_OP_2(0x83, 0x23)
#define BT_MESH_DFD_OP_FW_GET_BY_INDEX BLE_MESH_MODEL_OP_2(0x83, 0x24)
#define BT_MESH_DFD_OP_FW_DELETE BLE_MESH_MODEL_OP_2(0x83, 0x25)
#define BT_MESH_DFD_OP_FW_DELETE_ALL BLE_MESH_MODEL_OP_2(0x83, 0x26)
#define BT_MESH_DFD_OP_FW_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x27)
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_DFD_SRV_INTERNAL_H__
#define _BLE_MESH_v11_DFD_SRV_INTERNAL_H__
#include "mesh_v1.1/dfu/dfd_srv.h"
#if CONFIG_BLE_MESH_DFD_SRV
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_dfd_start_params {
uint16_t app_idx, timeout_base, slot_idx, group;
enum bt_mesh_blob_xfer_mode xfer_mode;
uint8_t ttl;
bool apply;
};
enum bt_mesh_dfd_status bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv *srv, uint16_t addr,
uint8_t img_idx);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv *srv);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv,
struct bt_mesh_dfd_start_params *params);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv *srv);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv,
struct bt_mesh_msg_ctx *ctx);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv *srv);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, size_t *fwid_len,
const uint8_t **fwid);
enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv *srv);
#ifdef __cplusplus
}
#endif
#endif
#endif /* _BLE_MESH_v11_DFD_SRV_INTERNAL_H__ */
+47
View File
@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh/buf.h"
#if CONFIG_BLE_MESH_DFU_SRV || CONFIG_BLE_MESH_DFU_CLI
#define BLE_MESH_DFU_OP_UPDATE_INFO_GET BLE_MESH_MODEL_OP_2(0x83, 0x08)
#define BLE_MESH_DFU_OP_UPDATE_INFO_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x09)
#define BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK BLE_MESH_MODEL_OP_2(0x83, 0x0a)
#define BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x0b)
#define BLE_MESH_DFU_OP_UPDATE_GET BLE_MESH_MODEL_OP_2(0x83, 0x0c)
#define BLE_MESH_DFU_OP_UPDATE_START BLE_MESH_MODEL_OP_2(0x83, 0x0d)
#define BLE_MESH_DFU_OP_UPDATE_CANCEL BLE_MESH_MODEL_OP_2(0x83, 0x0e)
#define BLE_MESH_DFU_OP_UPDATE_APPLY BLE_MESH_MODEL_OP_2(0x83, 0x0f)
#define BLE_MESH_DFU_OP_UPDATE_STATUS BLE_MESH_MODEL_OP_2(0x83, 0x10)
#define DFU_UPDATE_INFO_STATUS_MSG_MINLEN (4 + CONFIG_BLE_MESH_DFU_FWID_MAXLEN + \
CONFIG_BLE_MESH_DFU_URI_MAXLEN)
#define DFU_UPDATE_START_MSG_MAXLEN (12 + CONFIG_BLE_MESH_DFU_METADATA_MAXLEN)
static inline uint16_t dfu_metadata_checksum(struct net_buf_simple *buf)
{
/* Simple Fletcher-16 checksum to ensure duplicate start messages don't
* have different metadata.
*/
struct net_buf_simple_state state;
uint8_t sum[2] = {0, 0};
net_buf_simple_save(buf, &state);
while (buf->len) {
uint8_t byte = net_buf_simple_pull_u8(buf);
sum[0] += byte;
sum[1] += sum[0];
}
net_buf_simple_restore(buf, &state);
return (sum[0] << 8U) | sum[1];
}
#endif /* CONFIG_BLE_MESH_DFU_SRV || CONFIG_BLE_MESH_DFU_CLI */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,105 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "crypto.h"
#include "access.h"
#include "mesh/byteorder.h"
#include "mesh/buf.h"
#include "mesh_v1.1/dfu/dfu_metadata.h"
#if CONFIG_BLE_MESH_DFU_METADATA
int bt_mesh_dfu_metadata_decode(struct net_buf_simple *buf,
struct bt_mesh_dfu_metadata *metadata)
{
if (buf->len < 12) {
return -EMSGSIZE;
}
metadata->fw_ver.major = net_buf_simple_pull_u8(buf);
metadata->fw_ver.minor = net_buf_simple_pull_u8(buf);
metadata->fw_ver.revision = net_buf_simple_pull_le16(buf);
metadata->fw_ver.build_num = net_buf_simple_pull_le32(buf);
metadata->fw_size = net_buf_simple_pull_le24(buf);
metadata->fw_core_type = net_buf_simple_pull_u8(buf);
if (metadata->fw_core_type & BLE_MESH_DFU_FW_CORE_TYPE_APP) {
if (buf->len < 6) {
return -EMSGSIZE;
}
metadata->comp_hash = net_buf_simple_pull_le32(buf);
metadata->elems = net_buf_simple_pull_le16(buf);
}
metadata->user_data = buf->len > 0 ? buf->data : NULL;
metadata->user_data_len = buf->len;
return 0;
}
int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata,
struct net_buf_simple *buf)
{
size_t md_len_min = 12 + metadata->user_data_len;
if (metadata->fw_core_type & BLE_MESH_DFU_FW_CORE_TYPE_APP) {
md_len_min += 6;
}
if (net_buf_simple_tailroom(buf) < md_len_min) {
return -EMSGSIZE;
}
net_buf_simple_add_u8(buf, metadata->fw_ver.major);
net_buf_simple_add_u8(buf, metadata->fw_ver.minor);
net_buf_simple_add_le16(buf, metadata->fw_ver.revision);
net_buf_simple_add_le32(buf, metadata->fw_ver.build_num);
net_buf_simple_add_le24(buf, metadata->fw_size);
net_buf_simple_add_u8(buf, metadata->fw_core_type);
net_buf_simple_add_le32(buf, metadata->comp_hash);
net_buf_simple_add_le16(buf, metadata->elems);
if (metadata->user_data_len > 0) {
net_buf_simple_add_mem(buf, metadata->user_data, metadata->user_data_len);
}
return 0;
}
int bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple *buf, uint8_t *key, uint32_t *hash)
{
uint8_t mac[16];
int err;
struct bt_mesh_sg sg = {.data = buf->data, .len = buf->len};
/* The implementation of this function is the same as function `bt_mesh_aes_cmac_raw_key` in Zephyr. */
err = bt_mesh_aes_cmac(key, &sg, 1, mac);
if (err) {
return err;
}
*hash = sys_get_le32(mac);
return 0;
}
int bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t *key, uint32_t *hash)
{
NET_BUF_SIMPLE_DEFINE(buf, BLE_MESH_TX_SDU_MAX);
int err;
err = bt_mesh_get_comp_data(&buf, 0, 0, true);
if (err) {
return err;
}
err = bt_mesh_dfu_metadata_comp_hash_get(&buf, key, hash);
return err;
}
#endif /* CONFIG_BLE_MESH_DFU_METADATA */
@@ -0,0 +1,444 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "dfu_slot.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mesh/common.h"
#include "mesh/utils.h"
#include "settings_nvs.h"
#include "settings.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
#define SLOT_ENTRY_BUFLEN 25
#define DFU_SLOT_SETTINGS_PATH "mesh/dfu/s"
#define HEADER_SIZE offsetof(struct slot, slot.fwid)
#define PROP_HEADER "h"
#define PROP_FWID "id"
#define PROP_METADATA "m"
#define SETTINGS_NAME_END '='
#define SETTINGS_NAME_SEPARATOR '/'
static sys_slist_t list;
static struct slot {
uint32_t idx;
struct bt_mesh_dfu_slot slot;
sys_snode_t n;
} slots[CONFIG_BLE_MESH_DFU_SLOT_CNT];
static uint32_t slot_index;
inline int settings_name_next(const char *name, const char **next)
{
int rc = 0;
if (next) {
*next = NULL;
}
if (!name) {
return 0;
}
/* name might come from flash directly, in flash the name would end
* with '=' or '\0' depending how storage is done. Flash reading is
* limited to what can be read
*/
while ((*name != '\0') && (*name != SETTINGS_NAME_END) &&
(*name != SETTINGS_NAME_SEPARATOR)) {
rc++;
name++;
}
if (*name == SETTINGS_NAME_SEPARATOR) {
if (next) {
*next = name + 1;
}
return rc;
}
return rc;
}
#if CONFIG_BLE_MESH_SETTINGS
static char *slot_entry_encode(uint16_t idx, char buf[SLOT_ENTRY_BUFLEN],
const char *property)
{
snprintf(buf, SLOT_ENTRY_BUFLEN, DFU_SLOT_SETTINGS_PATH "/%x/%s", idx,
property);
return buf;
}
#endif
static bool slot_eq(const struct bt_mesh_dfu_slot *slot,
const uint8_t *fwid, size_t fwid_len)
{
return (slot->fwid_len == fwid_len) &&
!memcmp(fwid, slot->fwid, fwid_len);
}
static bool is_slot_committed(struct slot *slot_to_check)
{
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (s == slot_to_check) {
return true;
}
}
return false;
}
static int slot_store(const struct slot *slot_to_store)
{
int err = 0;
#if CONFIG_BLE_MESH_SETTINGS
uint16_t idx = ARRAY_INDEX(slots, slot_to_store);
char buf[SLOT_ENTRY_BUFLEN];
err = bt_mesh_save_core_settings(slot_entry_encode(idx, buf, PROP_HEADER),
(uint8_t *)slot_to_store, HEADER_SIZE);
if (err) {
return err;
}
err = bt_mesh_save_core_settings(slot_entry_encode(idx, buf, PROP_FWID),
slot_to_store->slot.fwid, slot_to_store->slot.fwid_len);
if (err) {
return err;
}
err = bt_mesh_save_core_settings(slot_entry_encode(idx, buf, PROP_METADATA),
slot_to_store->slot.metadata, slot_to_store->slot.metadata_len);
#endif
return err;
}
static void slot_erase(struct slot *slot_to_erase)
{
#if CONFIG_BLE_MESH_SETTINGS
uint16_t idx = ARRAY_INDEX(slots, slot_to_erase);
char buf[SLOT_ENTRY_BUFLEN];
bt_mesh_erase_core_settings(slot_entry_encode(idx, buf, PROP_HEADER));
bt_mesh_erase_core_settings(slot_entry_encode(idx, buf, PROP_FWID));
bt_mesh_erase_core_settings(slot_entry_encode(idx, buf, PROP_METADATA));
#endif
}
static void slot_index_defrag(void)
{
slot_index = 0;
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
s->idx = ++slot_index;
slot_store(s);
}
}
int bt_mesh_dfu_slot_count(void)
{
int cnt = 0;
sys_snode_t *n;
SYS_SLIST_FOR_EACH_NODE(&list, n) {
cnt++;
}
return cnt;
}
struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_reserve(void)
{
struct slot *slot = NULL;
for (int i = 0; i < ARRAY_SIZE(slots); ++i) {
if (slots[i].idx == 0) {
slot = &slots[i];
break;
}
}
if (!slot) {
BT_WARN("No space");
return NULL;
}
if (slot_index == UINT32_MAX) {
slot_index_defrag();
}
slot->slot.fwid_len = 0;
slot->slot.metadata_len = 0;
slot->slot.size = 0;
slot->idx = ++slot_index;
BT_DBG("Reserved slot #%u", slot - &slots[0]);
return &slot->slot;
}
int bt_mesh_dfu_slot_info_set(struct bt_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (metadata_len > CONFIG_BLE_MESH_DFU_METADATA_MAXLEN) {
return -EFBIG;
}
if (slot->idx == 0 || is_slot_committed(slot)) {
return -EINVAL;
}
slot->slot.size = size;
slot->slot.metadata_len = metadata_len;
memcpy(slot->slot.metadata, metadata, metadata_len);
return 0;
}
int bt_mesh_dfu_slot_fwid_set(struct bt_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (fwid_len > CONFIG_BLE_MESH_DFU_FWID_MAXLEN) {
return -EFBIG;
}
if (slot->idx == 0) {
return -EINVAL;
}
if (is_slot_committed(slot)) {
return -EEXIST;
}
for (int i = 0; i < ARRAY_SIZE(slots); i++) {
if (slots[i].idx != 0 &&
slot_eq(&slots[i].slot, fwid, fwid_len)) {
return -EALREADY;
}
}
slot->slot.fwid_len = fwid_len;
memcpy(slot->slot.fwid, fwid, fwid_len);
return 0;
}
int bt_mesh_dfu_slot_commit(struct bt_mesh_dfu_slot *dfu_slot)
{
int err;
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (slot->idx == 0 ||
slot->slot.fwid_len == 0 ||
slot->slot.size == 0 ||
is_slot_committed(slot)) {
return -EINVAL;
}
err = slot_store(slot);
if (err) {
BT_WARN("Store failed (err: %d)", err);
return err;
}
sys_slist_append(&list, &slot->n);
BT_DBG("Stored slot #%u: %s", ARRAY_INDEX(slots, slot),
bt_hex(slot->slot.fwid, slot->slot.fwid_len));
return 0;
}
void bt_mesh_dfu_slot_release(const struct bt_mesh_dfu_slot *dfu_slot)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (is_slot_committed(slot)) {
return;
}
slot->idx = 0;
}
int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *dfu_slot)
{
struct slot *slot = CONTAINER_OF(dfu_slot, struct slot, slot);
if (!sys_slist_find_and_remove(&list, &slot->n)) {
return -EINVAL;
}
int idx = ARRAY_INDEX(slots, slot);
BT_DBG("%u", idx);
slot_erase(slot);
slot->idx = 0;
return 0;
}
void bt_mesh_dfu_slot_del_all(void)
{
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
slot_erase(s);
s->idx = 0;
}
sys_slist_init(&list);
}
const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t img_idx)
{
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (!img_idx--) {
return &s->slot;
}
}
return NULL;
}
int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct bt_mesh_dfu_slot **slot)
{
struct slot *s;
int idx = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (slot_eq(&s->slot, fwid, fwid_len)) {
if (slot) {
*slot = &s->slot;
}
return idx;
}
idx++;
}
return -ENOENT;
}
int bt_mesh_dfu_slot_img_idx_get(const struct bt_mesh_dfu_slot *dfu_slot)
{
struct slot *s;
int idx = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (&s->slot == dfu_slot) {
return idx;
}
idx++;
}
return -ENOENT;
}
size_t bt_mesh_dfu_slot_foreach(bt_mesh_dfu_slot_cb_t cb, void *user_data)
{
enum bt_mesh_dfu_iter iter;
size_t cnt = 0;
struct slot *s;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
cnt++;
if (!cb) {
continue;
}
iter = cb(&s->slot, user_data);
if (iter != BLE_MESH_DFU_ITER_CONTINUE) {
break;
}
}
return cnt;
}
#if 0
static int slot_data_load(const char *key, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
const char *prop;
size_t len;
uint16_t idx;
idx = strtol(key, NULL, 16);
if (idx >= ARRAY_SIZE(slots)) {
return 0;
}
len = settings_name_next(key, &prop);
if (!strncmp(prop, PROP_HEADER, len)) {
if (read_cb(cb_arg, &slots[idx], HEADER_SIZE) > 0) {
struct slot *s, *prev = NULL;
SYS_SLIST_FOR_EACH_CONTAINER(&list, s, n) {
if (s->idx > slots[idx].idx) {
break;
}
prev = s;
}
if (prev == NULL) {
sys_slist_prepend(&list, &slots[idx].n);
} else {
sys_slist_insert(&list, &prev->n, &slots[idx].n);
}
if (slots[idx].idx >= slot_index) {
slot_index = slots[idx].idx + 1;
}
}
return 0;
}
if (!strncmp(prop, PROP_FWID, len)) {
if (read_cb(cb_arg, &slots[idx].slot.fwid,
sizeof(slots[idx].slot.fwid)) < 0) {
slots[idx].idx = 0;
sys_slist_find_and_remove(&list, &slots[idx].n);
return 0;
}
slots[idx].slot.fwid_len = len_rd;
return 0;
}
if (!strncmp(prop, PROP_METADATA, len)) {
if (read_cb(cb_arg, &slots[idx].slot.metadata,
sizeof(slots[idx].slot.metadata)) < 0) {
slots[idx].idx = 0;
sys_slist_find_and_remove(&list, &slots[idx].n);
return 0;
}
slots[idx].slot.metadata_len = len_rd;
return 0;
}
return 0;
}
#endif
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */
@@ -0,0 +1,137 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh_v1.1/dfu/dfu.h"
#if CONFIG_BLE_MESH_DFU_SLOTS
/** @brief Slot iteration callback.
*
* @param slot A valid DFU image slot.
* @param user_data User data passed to @ref bt_mesh_dfu_slot_foreach.
*
* @return Iteration action determining next step.
*/
typedef enum bt_mesh_dfu_iter(*bt_mesh_dfu_slot_cb_t)
(const struct bt_mesh_dfu_slot *slot, void *user_data);
/** @brief Get the number of slots committed to the firmware list.
*
* @return Number of committed slots.
*/
int bt_mesh_dfu_slot_count(void);
/** @brief Reserve a new DFU image slot for a distributable image.
*
* A DFU image slot represents a single distributable DFU image with all its
* metadata. The slot data must be set using @ref bt_mesh_dfu_slot_info_set and
* @ref bt_mesh_dfu_slot_fwid_set, and the slot committed using
* @ref bt_mesh_dfu_slot_commit for the slot to be considered part of the slot
* list.
*
* @return A pointer to the reserved slot, or NULL if allocation failed.
*/
struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_reserve(void);
/** @brief Set the size and metadata for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the
* metadata.
* @param size The size of the image.
* @param metadata Metadata or NULL.
* @param metadata_len Length of the metadata, at most @c
* CONFIG_BLE_MESH_DFU_METADATA_MAXLEN.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfu_slot_info_set(struct bt_mesh_dfu_slot *dfu_slot, size_t size,
const uint8_t *metadata, size_t metadata_len);
/** @brief Set the new fwid for the incoming image for a reserved slot.
*
* @param dfu_slot Pointer to the reserved slot for which to set the fwid.
* @param fwid Fwid to set.
* @param fwid_len Length of the fwid, at most @c
* CONFIG_BLE_MESH_DFU_FWID_MAXLEN.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfu_slot_fwid_set(struct bt_mesh_dfu_slot *dfu_slot,
const uint8_t *fwid, size_t fwid_len);
/** @brief Commit the reserved slot to the list of slots, and store it
* persistently.
*
* If the commit fails for any reason, the slot will still be in the reserved
* state after this call.
*
* @param dfu_slot Pointer to the reserved slot.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfu_slot_commit(struct bt_mesh_dfu_slot *dfu_slot);
/** @brief Release a reserved slot so that it can be reserved again.
*
* @param dfu_slot Pointer to the reserved slot.
*/
void bt_mesh_dfu_slot_release(const struct bt_mesh_dfu_slot *dfu_slot);
/** @brief Delete a committed DFU image slot.
*
* @param slot Slot to delete. Must be a valid pointer acquired from this
* module.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_dfu_slot_del(const struct bt_mesh_dfu_slot *slot);
/** @brief Delete all DFU image slots.
*
* @return 0 on success, or (negative) error code on failure.
*/
void bt_mesh_dfu_slot_del_all(void);
/** @brief Get the DFU image slot at the given firmware image list index.
*
* @param idx DFU image slot index.
*
* @return The DFU image slot at the given index, or NULL if no slot exists with the
* given index.
*/
const struct bt_mesh_dfu_slot *bt_mesh_dfu_slot_at(uint16_t img_idx);
/** @brief Get the committed DFU image slot for the image with the given
* firmware ID.
*
* @param fwid Firmware ID.
* @param fwid_len Firmware ID length.
* @param slot Slot pointer to fill.
*
* @return Slot index on success, or negative error code on failure.
*/
int bt_mesh_dfu_slot_get(const uint8_t *fwid, size_t fwid_len, struct bt_mesh_dfu_slot **slot);
/** @brief Get the index in the firmware image list for the given slot.
*
* @param slot Slot to find.
*
* @return Slot index on success, or negative error code on failure.
*/
int bt_mesh_dfu_slot_img_idx_get(const struct bt_mesh_dfu_slot *slot);
/** @brief Iterate through all DFU image slots.
*
* Calls the callback for every DFU image slot or until the callback returns
* something other than @ref BLE_MESH_DFU_ITER_CONTINUE.
*
* @param cb Callback to call for each slot, or NULL to just count the
* number of slots.
* @param user_data User data to pass to the callback.
*
* @return The number of slots iterated over.
*/
size_t bt_mesh_dfu_slot_foreach(bt_mesh_dfu_slot_cb_t cb, void *user_data);
#endif /* CONFIG_BLE_MESH_DFU_SLOTS */
@@ -0,0 +1,631 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh_v1.1/dfu/dfu.h"
#include "mesh_v1.1/dfu/dfu_srv.h"
#include "dfu.h"
#include "blob.h"
#include "access.h"
#if CONFIG_BLE_MESH_SETTINGS
#include "settings.h"
#endif
#if CONFIG_BLE_MESH_DFU_SRV
#define UPDATE_IDX_NONE 0xff
_Static_assert((DFU_UPDATE_START_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFU_OP_UPDATE_START) +
BLE_MESH_MIC_SHORT) <= BLE_MESH_RX_SDU_MAX,
"The Firmware Update Start message does not fit into the maximum incoming SDU size.");
_Static_assert((DFU_UPDATE_INFO_STATUS_MSG_MINLEN +
BLE_MESH_MODEL_OP_LEN(BLE_MESH_DFU_OP_UPDATE_INFO_STATUS) + BLE_MESH_MIC_SHORT)
<= BLE_MESH_TX_SDU_MAX,
"The Firmware Update Info Status message does not fit into the maximum outgoing SDU "
"size.");
static void store_state(struct bt_mesh_dfu_srv *srv)
{
#if CONFIG_BLE_MESH_SETTINGS
bt_mesh_model_data_store(srv->mod, false, NULL, &srv->update,
sizeof(srv->update));
#endif
}
static void erase_state(struct bt_mesh_dfu_srv *srv)
{
#if CONFIG_BLE_MESH_SETTINGS
bt_mesh_model_data_store(srv->mod, false, NULL, NULL, 0);
#endif
}
static void xfer_failed(struct bt_mesh_dfu_srv *srv)
{
if (!bt_mesh_dfu_srv_is_busy(srv) ||
srv->update.idx >= srv->img_count) {
return;
}
erase_state(srv);
if (srv->cb->end) {
srv->cb->end(srv, &srv->imgs[srv->update.idx], false);
}
}
static enum bt_mesh_dfu_status metadata_check(struct bt_mesh_dfu_srv *srv,
uint8_t idx,
struct net_buf_simple *buf,
enum bt_mesh_dfu_effect *effect)
{
*effect = BLE_MESH_DFU_EFFECT_NONE;
if (idx >= srv->img_count) {
return BLE_MESH_DFU_ERR_FW_IDX;
}
if (!srv->cb->check) {
return BLE_MESH_DFU_SUCCESS;
}
if (srv->cb->check(srv, &srv->imgs[idx], buf, effect)) {
*effect = BLE_MESH_DFU_EFFECT_NONE;
return BLE_MESH_DFU_ERR_METADATA;
}
return BLE_MESH_DFU_SUCCESS;
}
static void apply_rsp_sent(int err, void *cb_params)
{
struct bt_mesh_dfu_srv *srv = cb_params;
if (err) {
/* return phase back to give client one more chance. */
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_OK;
BT_WARN("Apply response failed, wait for retry (err %d)", err);
return;
}
BT_DBG("");
if (!srv->cb->apply || srv->update.idx == UPDATE_IDX_NONE) {
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
store_state(srv);
BT_DBG("Prerequisites for apply callback are wrong");
return;
}
store_state(srv);
err = srv->cb->apply(srv, &srv->imgs[srv->update.idx]);
if (err) {
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
store_state(srv);
BT_DBG("Application apply callback failed (err %d)", err);
}
}
static void apply_rsp_sending(uint16_t duration, int err, void *cb_params)
{
if (err) {
apply_rsp_sent(err, cb_params);
}
}
static void verify(struct bt_mesh_dfu_srv *srv)
{
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY;
if (srv->update.idx >= srv->img_count) {
bt_mesh_dfu_srv_rejected(srv);
return;
}
if (!srv->cb->end) {
bt_mesh_dfu_srv_verified(srv);
return;
}
srv->cb->end(srv, &srv->imgs[srv->update.idx], true);
if (srv->update.phase == BLE_MESH_DFU_PHASE_VERIFY) {
store_state(srv);
}
}
static int handle_info_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
uint8_t idx, limit;
if (srv->update.phase == BLE_MESH_DFU_PHASE_APPLYING) {
BT_INFO("Still applying, not responding");
return -EBUSY;
}
idx = net_buf_simple_pull_u8(buf);
limit = net_buf_simple_pull_u8(buf);
BT_DBG("from %u (limit: %u)", idx, limit);
NET_BUF_SIMPLE_DEFINE(rsp, BLE_MESH_TX_SDU_MAX);
bt_mesh_model_msg_init(&rsp, BLE_MESH_DFU_OP_UPDATE_INFO_STATUS);
net_buf_simple_add_u8(&rsp, srv->img_count);
net_buf_simple_add_u8(&rsp, idx);
for (; idx < srv->img_count && limit > 0; ++idx) {
uint32_t entry_len;
if (!srv->imgs[idx].fwid) {
continue;
}
entry_len = 2 + srv->imgs[idx].fwid_len;
if (srv->imgs[idx].uri) {
entry_len += strlen(srv->imgs[idx].uri);
}
if (net_buf_simple_tailroom(&rsp) + BLE_MESH_MIC_SHORT < entry_len) {
break;
}
net_buf_simple_add_u8(&rsp, srv->imgs[idx].fwid_len);
net_buf_simple_add_mem(&rsp, srv->imgs[idx].fwid,
srv->imgs[idx].fwid_len);
if (srv->imgs[idx].uri) {
size_t len = strlen(srv->imgs[idx].uri);
net_buf_simple_add_u8(&rsp, len);
net_buf_simple_add_mem(&rsp, srv->imgs[idx].uri, len);
} else {
net_buf_simple_add_u8(&rsp, 0);
}
limit--;
}
if (srv->update.phase != BLE_MESH_DFU_PHASE_IDLE) {
ctx->send_ttl = srv->update.ttl;
}
bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL);
return 0;
}
static int handle_metadata_check(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
enum bt_mesh_dfu_status status;
enum bt_mesh_dfu_effect effect;
uint8_t idx;
BLE_MESH_MODEL_BUF_DEFINE(rsp, BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS, 2);
bt_mesh_model_msg_init(&rsp, BLE_MESH_DFU_OP_UPDATE_METADATA_STATUS);
idx = net_buf_simple_pull_u8(buf);
status = metadata_check(srv, idx, buf, &effect);
BT_DBG("%u", idx);
net_buf_simple_add_u8(&rsp, (status & BIT_MASK(3)) | (effect << 3));
net_buf_simple_add_u8(&rsp, idx);
if (srv->update.phase != BLE_MESH_DFU_PHASE_IDLE) {
ctx->send_ttl = srv->update.ttl;
}
bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL);
return 0;
}
static void update_status_rsp(struct bt_mesh_dfu_srv *srv,
struct bt_mesh_msg_ctx *ctx,
enum bt_mesh_dfu_status status,
const struct bt_mesh_send_cb *send_cb)
{
BLE_MESH_MODEL_BUF_DEFINE(buf, BLE_MESH_DFU_OP_UPDATE_STATUS, 14);
bt_mesh_model_msg_init(&buf, BLE_MESH_DFU_OP_UPDATE_STATUS);
net_buf_simple_add_u8(&buf, ((status & BIT_MASK(3)) |
(srv->update.phase << 5)));
if (srv->update.phase != BLE_MESH_DFU_PHASE_IDLE) {
net_buf_simple_add_u8(&buf, srv->update.ttl);
net_buf_simple_add_u8(&buf, srv->update.effect);
net_buf_simple_add_le16(&buf, srv->update.timeout_base);
net_buf_simple_add_le64(&buf, srv->blob.state.xfer.id);
net_buf_simple_add_u8(&buf, srv->update.idx);
ctx->send_ttl = srv->update.ttl;
}
bt_mesh_model_send(srv->mod, ctx, &buf, send_cb, srv);
}
static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
BT_DBG("");
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, NULL);
return 0;
}
static inline bool is_active_update(struct bt_mesh_dfu_srv *srv, uint8_t idx,
uint16_t timeout_base,
const uint64_t *blob_id, uint8_t ttl,
uint16_t meta_checksum)
{
return (srv->update.idx != idx || srv->blob.state.xfer.id != *blob_id ||
srv->update.ttl != ttl ||
srv->update.timeout_base != timeout_base ||
srv->update.meta != meta_checksum);
}
static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
const struct bt_mesh_blob_io *io;
uint16_t timeout_base, meta_checksum;
enum bt_mesh_dfu_status status;
uint8_t ttl, idx;
uint64_t blob_id;
int err;
struct net_buf_simple_state buf_state;
ttl = net_buf_simple_pull_u8(buf);
timeout_base = net_buf_simple_pull_le16(buf);
blob_id = net_buf_simple_pull_le64(buf);
idx = net_buf_simple_pull_u8(buf);
meta_checksum = dfu_metadata_checksum(buf);
BT_DBG("%u ttl: %u extra time: %u", idx, ttl, timeout_base);
if ((!buf->len || meta_checksum == srv->update.meta) &&
srv->update.phase == BLE_MESH_DFU_PHASE_TRANSFER_ERR &&
srv->update.ttl == ttl &&
srv->update.timeout_base == timeout_base &&
srv->update.idx == idx &&
srv->blob.state.xfer.id == blob_id) {
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE;
status = BLE_MESH_DFU_SUCCESS;
store_state(srv);
/* blob srv will resume the transfer. */
BT_DBG("Resuming transfer");
goto rsp;
}
if (bt_mesh_dfu_srv_is_busy(srv)) {
if (is_active_update(srv, idx, timeout_base, &blob_id, ttl,
meta_checksum)) {
status = BLE_MESH_DFU_ERR_WRONG_PHASE;
} else {
status = BLE_MESH_DFU_SUCCESS;
srv->update.ttl = ttl;
srv->blob.state.xfer.id = blob_id;
}
BT_WARN("Busy. Phase: %u", srv->update.phase);
goto rsp;
}
net_buf_simple_save(buf, &buf_state);
status = metadata_check(srv, idx, buf,
(enum bt_mesh_dfu_effect *)&srv->update.effect);
net_buf_simple_restore(buf, &buf_state);
if (status != BLE_MESH_DFU_SUCCESS) {
goto rsp;
}
srv->update.ttl = ttl;
srv->update.timeout_base = timeout_base;
srv->update.meta = meta_checksum;
io = NULL;
err = srv->cb->start(srv, &srv->imgs[idx], buf, &io);
if (err == -EALREADY || (!err && bt_mesh_has_addr(ctx->addr))) {
/* This image has already been received or this is a
* self-update. Skip the transfer phase and proceed to
* verifying update.
*/
status = BLE_MESH_DFU_SUCCESS;
srv->update.idx = idx;
srv->blob.state.xfer.id = blob_id;
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY;
update_status_rsp(srv, ctx, status, NULL);
verify(srv);
return 0;
}
if (err == -ENOMEM) {
status = BLE_MESH_DFU_ERR_RESOURCES;
goto rsp;
}
if (err == -EBUSY) {
status = BLE_MESH_DFU_ERR_TEMPORARILY_UNAVAILABLE;
goto rsp;
}
if (err || !io || !io->wr) {
status = BLE_MESH_DFU_ERR_INTERNAL;
goto rsp;
}
err = bt_mesh_blob_srv_recv(&srv->blob, blob_id, io,
ttl, timeout_base);
if (err) {
status = BLE_MESH_DFU_ERR_BLOB_XFER_BUSY;
goto rsp;
}
srv->update.idx = idx;
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE;
status = BLE_MESH_DFU_SUCCESS;
store_state(srv);
rsp:
update_status_rsp(srv, ctx, status, NULL);
return 0;
}
static int handle_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
if (srv->update.idx == UPDATE_IDX_NONE) {
goto rsp;
}
BT_DBG("");
bt_mesh_blob_srv_cancel(&srv->blob);
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
xfer_failed(srv);
rsp:
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, NULL);
return 0;
}
static int handle_apply(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
static const struct bt_mesh_send_cb send_cb = {
.start = apply_rsp_sending,
.end = apply_rsp_sent,
};
BT_DBG("");
if (srv->update.phase == BLE_MESH_DFU_PHASE_APPLYING) {
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, NULL);
return 0;
}
if (srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY_OK) {
BT_WARN("Apply: Invalid phase %u", srv->update.phase);
update_status_rsp(srv, ctx, BLE_MESH_DFU_ERR_WRONG_PHASE, NULL);
return 0;
}
/* Postponing the apply callback until the response has been sent, in
* case it triggers a reboot:
*/
srv->update.phase = BLE_MESH_DFU_PHASE_APPLYING;
update_status_rsp(srv, ctx, BLE_MESH_DFU_SUCCESS, &send_cb);
return 0;
}
const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[] = {
{ BLE_MESH_DFU_OP_UPDATE_INFO_GET, 2, (void *)handle_info_get },
{ BLE_MESH_DFU_OP_UPDATE_METADATA_CHECK, 1, (void *)handle_metadata_check },
{ BLE_MESH_DFU_OP_UPDATE_GET, 0, (void *)handle_get },
{ BLE_MESH_DFU_OP_UPDATE_START, 12, (void *)handle_start },
{ BLE_MESH_DFU_OP_UPDATE_CANCEL, 0, (void *)handle_cancel },
{ BLE_MESH_DFU_OP_UPDATE_APPLY, 0, (void *)handle_apply },
BLE_MESH_MODEL_OP_END,
};
static int dfu_srv_init(struct bt_mesh_model *mod)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
srv->mod = mod;
srv->update.idx = UPDATE_IDX_NONE;
srv->blob.cb = &_bt_mesh_dfu_srv_blob_cb;
if (!srv->cb || !srv->cb->start || !srv->imgs || srv->img_count == 0 ||
srv->img_count == UPDATE_IDX_NONE) {
BT_ERR("Invalid DFU Server initialization");
return -EINVAL;
}
return 0;
}
__attribute__((unused))
static int dfu_srv_settings_set(const struct bt_mesh_model *mod, const char *name,
size_t len_rd, settings_read_cb read_cb,
void *cb_arg)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
ssize_t len;
if (len_rd < sizeof(srv->update)) {
return -EINVAL;
}
len = read_cb(cb_arg, &srv->update, sizeof(srv->update));
if (len < 0) {
return len;
}
BT_DBG("Recovered transfer (phase: %u, idx: %u)", srv->update.phase,
srv->update.idx);
if (srv->update.phase == BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
BT_DBG("Settings recovered mid-transfer, setting transfer error");
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ERR;
} else if (srv->update.phase == BLE_MESH_DFU_PHASE_VERIFY_OK) {
BT_DBG("Settings recovered before application, setting verification fail");
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_FAIL;
}
return 0;
}
static void dfu_srv_reset(struct bt_mesh_model *mod)
{
struct bt_mesh_dfu_srv *srv = mod->user_data;
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
erase_state(srv);
}
static int dfu_srv_deinit(struct bt_mesh_model *mod)
{
dfu_srv_reset(mod);
return 0;
}
const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb = {
.init = dfu_srv_init,
#if CONFIG_BLE_MESH_DEINIT
.deinit = dfu_srv_deinit,
#endif
};
static void blob_suspended(struct bt_mesh_blob_srv *b)
{
struct bt_mesh_dfu_srv *srv = CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ERR;
store_state(srv);
}
static void blob_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success)
{
struct bt_mesh_dfu_srv *srv =
CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);
BT_DBG("success: %u", success);
if (!success) {
srv->update.phase = BLE_MESH_DFU_PHASE_TRANSFER_ERR;
xfer_failed(srv);
return;
}
verify(srv);
}
static int blob_recover(struct bt_mesh_blob_srv *b,
struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_io **io)
{
struct bt_mesh_dfu_srv *srv =
CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);
if (!srv->cb->recover ||
srv->update.phase != BLE_MESH_DFU_PHASE_TRANSFER_ERR ||
srv->update.idx >= srv->img_count) {
return -ENOTSUP;
}
return srv->cb->recover(srv, &srv->imgs[srv->update.idx], io);
}
const struct bt_mesh_blob_srv_cb _bt_mesh_dfu_srv_blob_cb = {
.suspended = blob_suspended,
.end = blob_end,
.recover = blob_recover,
};
void bt_mesh_dfu_srv_verified(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY) {
BT_WARN("Wrong state");
return;
}
BT_DBG("");
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_OK;
store_state(srv);
}
void bt_mesh_dfu_srv_rejected(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY) {
BT_WARN("Wrong state");
return;
}
BT_DBG("");
srv->update.phase = BLE_MESH_DFU_PHASE_VERIFY_FAIL;
store_state(srv);
}
void bt_mesh_dfu_srv_cancel(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase == BLE_MESH_DFU_PHASE_IDLE) {
BT_WARN("Wrong state");
return;
}
(void)bt_mesh_blob_srv_cancel(&srv->blob);
}
void bt_mesh_dfu_srv_applied(struct bt_mesh_dfu_srv *srv)
{
if (srv->update.phase != BLE_MESH_DFU_PHASE_APPLYING) {
BT_WARN("Wrong state");
return;
}
BT_DBG("");
srv->update.phase = BLE_MESH_DFU_PHASE_IDLE;
store_state(srv);
}
bool bt_mesh_dfu_srv_is_busy(const struct bt_mesh_dfu_srv *srv)
{
return srv->update.phase != BLE_MESH_DFU_PHASE_IDLE &&
srv->update.phase != BLE_MESH_DFU_PHASE_TRANSFER_ERR &&
srv->update.phase != BLE_MESH_DFU_PHASE_VERIFY_FAIL;
}
uint8_t bt_mesh_dfu_srv_progress(const struct bt_mesh_dfu_srv *srv)
{
if (!bt_mesh_dfu_srv_is_busy(srv)) {
return 0U;
}
if (srv->update.phase == BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
return bt_mesh_blob_srv_progress(&srv->blob);
}
return 100U;
}
#endif /* CONFIG_BLE_MESH_DFU_SRV */
@@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_DFD_H__
#define _BLE_MESH_v11_DFD_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_dfd Firmware Distribution models
* @ingroup bt_mesh
* @{
*/
/** Firmware distribution status. */
enum bt_mesh_dfd_status {
/** The message was processed successfully. */
BT_MESH_DFD_SUCCESS,
/** Insufficient resources on the node. */
BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES,
/** The operation cannot be performed while the Server is in the current
* phase.
*/
BT_MESH_DFD_ERR_WRONG_PHASE,
/** An internal error occurred on the node. */
BT_MESH_DFD_ERR_INTERNAL,
/** The requested firmware image is not stored on the Distributor. */
BT_MESH_DFD_ERR_FW_NOT_FOUND,
/** The AppKey identified by the AppKey Index is not known to the node.
*/
BT_MESH_DFD_ERR_INVALID_APPKEY_INDEX,
/** There are no Target nodes in the Distribution Receivers List
* state.
*/
BT_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY,
/** Another firmware image distribution is in progress. */
BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION,
/** Another upload is in progress. */
BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD,
/** The URI scheme name indicated by the Update URI is not supported. */
BT_MESH_DFD_ERR_URI_NOT_SUPPORTED,
/** The format of the Update URI is invalid. */
BT_MESH_DFD_ERR_URI_MALFORMED,
/** The URI is currently unreachable. */
BT_MESH_DFD_ERR_URI_UNREACHABLE,
/** The Check Firmware OOB procedure did not find any new firmware. */
BT_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE,
/** The suspension of the Distribute Firmware procedure failed. */
BT_MESH_DFD_ERR_SUSPEND_FAILED,
};
/** Firmware distribution phases. */
enum bt_mesh_dfd_phase {
/** No firmware distribution is in progress. */
BT_MESH_DFD_PHASE_IDLE,
/** Firmware distribution is in progress. */
BT_MESH_DFD_PHASE_TRANSFER_ACTIVE,
/** The Transfer BLOB procedure has completed successfully. */
BT_MESH_DFD_PHASE_TRANSFER_SUCCESS,
/** The Apply Firmware on Target Nodes procedure is being executed. */
BT_MESH_DFD_PHASE_APPLYING_UPDATE,
/** The Distribute Firmware procedure has completed successfully. */
BT_MESH_DFD_PHASE_COMPLETED,
/** The Distribute Firmware procedure has failed. */
BT_MESH_DFD_PHASE_FAILED,
/** The Cancel Firmware Update procedure is being executed. */
BT_MESH_DFD_PHASE_CANCELING_UPDATE,
/** The Transfer BLOB procedure is suspended. */
BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED,
};
/** Firmware upload phases. */
enum bt_mesh_dfd_upload_phase {
/** No firmware upload is in progress. */
BT_MESH_DFD_UPLOAD_PHASE_IDLE,
/** The Store Firmware procedure is being executed. */
BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE,
/** The Store Firmware procedure or Store Firmware OOB procedure failed.
*/
BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR,
/** The Store Firmware procedure or the Store Firmware OOB procedure
* completed successfully.
*/
BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS,
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFD_H__ */
@@ -0,0 +1,314 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfd_srv Firmware Distribution Server model
* @ingroup bt_mesh_dfd
* @{
* @brief API for the Firmware Distribution Server model
*/
#ifndef _BLE_MESH_v11_DFD_SRV_H__
#define _BLE_MESH_v11_DFD_SRV_H__
#include "mesh/access.h"
#include "mesh_v1.1/dfu/dfd.h"
#include "mesh_v1.1/dfu/dfu_cli.h"
#include "mesh_v1.1/mbt/blob_cli.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX
#define CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX 0
#endif
#ifndef CONFIG_BLE_MESH_DFD_SRV_SLOT_MAX_SIZE
#define CONFIG_BLE_MESH_DFD_SRV_SLOT_MAX_SIZE 0
#endif
#ifndef CONFIG_BLE_MESH_DFD_SRV_SLOT_SPACE
#define CONFIG_BLE_MESH_DFD_SRV_SLOT_SPACE 0
#endif
struct bt_mesh_dfd_srv;
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
/**
*
* @brief Initialization parameters for the @ref bt_mesh_dfd_srv with OOB
* upload support.
*
* @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance.
* @param[in] _oob_schemes Array of OOB schemes supported by the server,
* each scheme being a code point from the
* Bluetooth SIG Assigned Numbers document.
* @param[in] _oob_schemes_count Number of schemes in @c _oob_schemes.
*/
#define BT_MESH_DFD_SRV_OOB_INIT(_cb, _oob_schemes, _oob_schemes_count) \
{ \
.cb = _cb, \
.dfu = BLE_MESH_DFU_CLI_INIT(&_bt_mesh_dfd_srv_dfu_cb), \
.upload = { \
.blob = { .cb = &_bt_mesh_dfd_srv_blob_cb }, \
}, \
.oob_schemes = { \
.schemes = _oob_schemes, \
.count = _oob_schemes_count, \
}, \
}
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
/**
*
* @brief Initialization parameters for the @ref bt_mesh_dfd_srv.
*
* @param[in] _cb Pointer to a @ref bt_mesh_dfd_srv_cb instance.
*/
#define BT_MESH_DFD_SRV_INIT(_cb) \
{ \
.cb = _cb, \
.dfu = BLE_MESH_DFU_CLI_INIT(&_bt_mesh_dfd_srv_dfu_cb), \
.upload = { \
.blob = { .cb = &_bt_mesh_dfd_srv_blob_cb }, \
}, \
}
/**
*
* @brief Firmware Distribution Server model Composition Data entry.
*
* @param _srv Pointer to a @ref bt_mesh_dfd_srv instance.
*/
#define BT_MESH_MODEL_DFD_SRV(_srv) \
BT_MESH_MODEL_DFU_CLI(&(_srv)->dfu), \
BT_MESH_MODEL_BLOB_SRV(&(_srv)->upload.blob), \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_DFD_SRV, _bt_mesh_dfd_srv_op, NULL, \
_srv, &_bt_mesh_dfd_srv_cb)
/** Firmware Distribution Server callbacks: */
struct bt_mesh_dfd_srv_cb {
/** @brief Slot receive callback.
*
* Called at the start of an upload procedure. The callback must fill
* @c io with a pointer to a writable BLOB stream for the Firmware Distribution
* Server to write the firmware image to.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot being received.
* @param io BLOB stream response pointer.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*recv)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const struct bt_mesh_blob_io **io);
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
/** @brief Firmware upload OOB start callback.
*
* Called at the start of an OOB firmware upload. The application must
* start a firmware check using an OOB mechanism, and then call
* @ref bt_mesh_dfd_srv_oob_check_complete. Depending on the return
* value of this function, the application must then start storing the
* firmware image using an OOB mechanism, and call
* @ref bt_mesh_dfd_srv_oob_store_complete. This callback is mandatory
* to support OOB uploads.
*
* @param srv Firmware Distribution Server model instance.
* @param slot Slot to be used for the upload.
* @param uri Pointer to buffer containing the URI used to
* check for new firmware.
* @param uri_len Length of the URI buffer.
* @param fwid Pointer to buffer containing the current
* firmware ID to be used when checking for
* availability of new firmware.
* @param fwid_len Length of the current firmware ID. Must be set
* to the length of the new firmware ID if it is
* available, or to 0 if new firmware is not
* available.
*
* @return BT_MESH_DFD_SUCCESS on success, or error code otherwise.
*/
int (*start_oob_upload)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const char *uri, uint8_t uri_len,
const uint8_t *fwid, uint16_t fwid_len);
/** @brief Cancel store OOB callback
*
* Called when an OOB store is cancelled. The application must stop
* any ongoing OOB image transfer. This callback is mandatory to
* support OOB uploads.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot to cancel
*/
void (*cancel_oob_upload)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot);
/** @brief Get the progress of an ongoing OOB store
*
* Called by the Firmware Distribution Server model when it needs to
* get the current progress of an ongoing OOB store from the
* application. This callback is mandatory to support OOB uploads.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot to get progress for.
*
* @return The current progress of the ongoing OOB store, in percent.
*/
uint8_t (*oob_progress_get)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot);
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
/** @brief Slot delete callback.
*
* Called when the Firmware Distribution Server is about to delete a DFU image slot.
* All allocated data associated with the firmware slot should be
* deleted.
*
* @param srv Firmware Update Server instance.
* @param slot DFU image slot being deleted.
*/
void (*del)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot);
/** @brief Slot send callback.
*
* Called at the start of a distribution procedure. The callback must
* fill @c io with a pointer to a readable BLOB stream for the Firmware
* Distribution Server to read the firmware image from.
*
* @param srv Firmware Distribution Server model instance.
* @param slot DFU image slot being sent.
* @param io BLOB stream response pointer.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*send)(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const struct bt_mesh_blob_io **io);
/** @brief Phase change callback (Optional).
*
* Called whenever the phase of the Firmware Distribution Server changes.
*
* @param srv Firmware Distribution Server model instance.
* @param phase New Firmware Distribution phase.
*/
void (*phase)(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_phase phase);
};
/** Firmware Distribution Server instance. */
struct bt_mesh_dfd_srv {
const struct bt_mesh_dfd_srv_cb *cb;
const struct bt_mesh_model *mod;
struct bt_mesh_dfu_cli dfu;
struct bt_mesh_dfu_target targets[CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX];
struct bt_mesh_blob_target_pull pull_ctxs[CONFIG_BLE_MESH_DFD_SRV_TARGETS_MAX];
const struct bt_mesh_blob_io *io;
uint16_t target_cnt;
uint16_t slot_idx;
bool apply;
enum bt_mesh_dfd_phase phase;
struct bt_mesh_blob_cli_inputs inputs;
struct {
enum bt_mesh_dfd_upload_phase phase;
struct bt_mesh_dfu_slot *slot;
const struct flash_area *area;
struct bt_mesh_blob_srv blob;
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
bool is_oob;
bool is_pending_oob_check;
struct {
uint8_t uri_len;
char uri[CONFIG_BLE_MESH_DFU_URI_MAXLEN];
uint16_t current_fwid_len;
uint8_t current_fwid[CONFIG_BLE_MESH_DFU_FWID_MAXLEN];
struct bt_mesh_msg_ctx ctx;
} oob;
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
} upload;
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
struct {
const uint8_t *schemes;
const uint8_t count;
} oob_schemes;
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
};
#ifdef CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD
/** @brief Call when an OOB check has completed or failed
*
* This should be called by the application after an OOB check started by the @c start_oob_upload
* callback has completed or failed. The @p status param should be set to one of the following
* values:
*
* * @c BT_MESH_DFD_SUCCESS if the check was successful and a new firmware ID was found.
* * @c BT_MESH_DFD_ERR_URI_MALFORMED if the URI is not formatted correctly.
* * @c BT_MESH_DFD_ERR_URI_NOT_SUPPORTED if the URI scheme is not supported by the node.
* * @c BT_MESH_DFD_ERR_URI_UNREACHABLE if the URI can't be reached.
* * @c BT_MESH_DFD_ERR_NEW_FW_NOT_AVAILABLE if the check completes successfully but no new
* firmware is available.
*
* If this function returns 0, the application should then download the firmware to the
* slot. If an error code is returned, the application should abort the OOB upload.
*
* @param srv Firmware Distribution Server model instance.
* @param slot The slot used in the OOB upload.
* @param status The result of the firmware check.
* @param fwid If the check was successful and new firmware found, this should point to a
* buffer containing the new firmware ID to store.
* @param fwid_len The length of the firmware ID pointed to by @p fwid.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot, int status,
uint8_t *fwid, size_t fwid_len);
/** @brief Call when an OOB store has completed or failed
*
* This should be called by the application after an OOB store started after a successful call to
* @c bt_mesh_dfd_srv_oob_check_complete has completed successfully or failed.
*
* @param srv Firmware Distribution Server model instance.
* @param slot The slot used when storing the firmware image.
* @param success @c true if the OOB store completed successfully, @c false otherwise.
* @param size The size of the stored firmware image, in bytes.
* @param metadata Pointer to the metadata received OOB, or @c NULL if no metadata was
* received.
* @param metadata_len Size of the metadata pointed to by @p metadata.
*
* @return 0 on success, (negative) error code otherwise.
*/
int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot, bool success,
size_t size, const uint8_t *metadata, size_t metadata_len);
#endif /* CONFIG_BLE_MESH_DFD_SRV_OOB_UPLOAD */
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfd_srv_cb;
extern const struct bt_mesh_dfu_cli_cb _bt_mesh_dfd_srv_dfu_cb;
extern const struct bt_mesh_blob_srv_cb _bt_mesh_dfd_srv_blob_cb;
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFD_SRV_H__ */
/** @} */
@@ -0,0 +1,173 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_DFU_H__
#define _BLE_MESH_v11_DFU_H__
#include <sys/types.h>
#include "mesh/types.h"
#include "mesh/utils.h"
#include "mesh_v1.1/mbt/blob.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_dfu Bluetooth Mesh Device Firmware Update
* @ingroup bt_mesh
* @{
*/
#ifndef CONFIG_BLE_MESH_DFU_FWID_MAXLEN
#define CONFIG_BLE_MESH_DFU_FWID_MAXLEN 0
#endif
#ifndef CONFIG_BLE_MESH_DFU_METADATA_MAXLEN
#define CONFIG_BLE_MESH_DFU_METADATA_MAXLEN 0
#endif
#ifndef CONFIG_BLE_MESH_DFU_URI_MAXLEN
#define CONFIG_BLE_MESH_DFU_URI_MAXLEN 0
#endif
#ifndef CONFIG_BLE_MESH_DFU_SLOT_CNT
#define CONFIG_BLE_MESH_DFU_SLOT_CNT 0
#endif
/** DFU transfer phase. */
enum bt_mesh_dfu_phase {
/** Ready to start a Receive Firmware procedure. */
BLE_MESH_DFU_PHASE_IDLE,
/** The Transfer BLOB procedure failed. */
BLE_MESH_DFU_PHASE_TRANSFER_ERR,
/** The Receive Firmware procedure is being executed. */
BLE_MESH_DFU_PHASE_TRANSFER_ACTIVE,
/** The Verify Firmware procedure is being executed. */
BLE_MESH_DFU_PHASE_VERIFY,
/** The Verify Firmware procedure completed successfully. */
BLE_MESH_DFU_PHASE_VERIFY_OK,
/** The Verify Firmware procedure failed. */
BLE_MESH_DFU_PHASE_VERIFY_FAIL,
/** The Apply New Firmware procedure is being executed. */
BLE_MESH_DFU_PHASE_APPLYING,
/** Firmware transfer has been canceled. */
BLE_MESH_DFU_PHASE_TRANSFER_CANCELED,
/** Firmware applying succeeded. */
BLE_MESH_DFU_PHASE_APPLY_SUCCESS,
/** Firmware applying failed. */
BLE_MESH_DFU_PHASE_APPLY_FAIL,
/** Phase of a node was not yet retrieved. */
BLE_MESH_DFU_PHASE_UNKNOWN,
};
/** DFU status. */
enum bt_mesh_dfu_status {
/** The message was processed successfully. */
BLE_MESH_DFU_SUCCESS,
/** Insufficient resources on the node */
BLE_MESH_DFU_ERR_RESOURCES,
/** The operation cannot be performed while the Server is in the current
* phase.
*/
BLE_MESH_DFU_ERR_WRONG_PHASE,
/** An internal error occurred on the node. */
BLE_MESH_DFU_ERR_INTERNAL,
/** The message contains a firmware index value that is not expected. */
BLE_MESH_DFU_ERR_FW_IDX,
/** The metadata check failed. */
BLE_MESH_DFU_ERR_METADATA,
/** The Server cannot start a firmware update. */
BLE_MESH_DFU_ERR_TEMPORARILY_UNAVAILABLE,
/** Another BLOB transfer is in progress. */
BLE_MESH_DFU_ERR_BLOB_XFER_BUSY,
};
/** Expected effect of a DFU transfer. */
enum bt_mesh_dfu_effect {
/** No changes to node Composition Data. */
BLE_MESH_DFU_EFFECT_NONE,
/** Node Composition Data changed and the node does not support remote
* provisioning.
*/
BLE_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR,
/** 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.
*/
BLE_MESH_DFU_EFFECT_COMP_CHANGE,
/** Node will be unprovisioned after the update. */
BLE_MESH_DFU_EFFECT_UNPROV,
};
/** Action for DFU iteration callbacks. */
enum bt_mesh_dfu_iter {
/** Stop iterating. */
BLE_MESH_DFU_ITER_STOP,
/** Continue iterating. */
BLE_MESH_DFU_ITER_CONTINUE,
};
/** DFU image instance.
*
* Each DFU image represents a single updatable firmware image.
*/
struct bt_mesh_dfu_img {
/** Firmware ID. */
const void *fwid;
/** Length of the firmware ID. */
size_t fwid_len;
/** Update URI, or NULL. */
const char *uri;
};
/** DFU image slot for DFU distribution. */
struct bt_mesh_dfu_slot {
/** Size of the firmware in bytes. */
size_t size;
/** Length of the firmware ID. */
size_t fwid_len;
/** Length of the metadata. */
size_t metadata_len;
/** Firmware ID. */
uint8_t fwid[CONFIG_BLE_MESH_DFU_FWID_MAXLEN];
/** Metadata. */
uint8_t metadata[CONFIG_BLE_MESH_DFU_METADATA_MAXLEN];
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_H__ */
@@ -0,0 +1,430 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfu_cli Firmware Uppdate Client model
* @ingroup bt_mesh_dfu
* @{
* @brief API for the Bluetooth Mesh Firmware Update Client model
*/
#ifndef _BLE_MESH_v11_DFU_CLI_H__
#define _BLE_MESH_v11_DFU_CLI_H__
#include "freertos/semphr.h"
#include "mesh/access.h"
#include "mesh_v1.1/mbt/blob_cli.h"
#include "mesh_v1.1/dfu/dfu.h"
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_dfu_cli;
/**
*
* @brief Initialization parameters for the @ref bt_mesh_dfu_cli.
*
* @sa bt_mesh_dfu_cli_cb.
*
* @param _handlers Handler callback structure.
*/
#define BLE_MESH_DFU_CLI_INIT(_handlers) \
{ \
.cb = _handlers, \
.blob = { .cb = &_bt_mesh_dfu_cli_blob_handlers }, \
}
/**
*
* @brief Firmware Update Client model Composition Data entry.
*
* @param _cli Pointer to a @ref bt_mesh_dfu_cli instance.
*/
#define BT_MESH_MODEL_DFU_CLI(_cli) \
BT_MESH_MODEL_BLOB_CLI(&(_cli)->blob), \
BT_MESH_MODEL_CB(BLE_MESH_MODEL_ID_DFU_CLI, _bt_mesh_dfu_cli_op, NULL, \
_cli, &_bt_mesh_dfu_cli_cb)
/** DFU Target node. */
struct bt_mesh_dfu_target {
/** BLOB Target node */
struct bt_mesh_blob_target blob;
/** Image index on the Target node */
uint8_t img_idx;
/** Expected DFU effect, see @ref bt_mesh_dfu_effect. */
uint8_t effect;
/** Current DFU status, see @ref bt_mesh_dfu_status. */
uint8_t status;
/** Current DFU phase, see @ref bt_mesh_dfu_phase. */
uint8_t phase;
};
/** Metadata status response. */
struct bt_mesh_dfu_metadata_status {
/** Image index. */
uint8_t idx;
/** Status code. */
enum bt_mesh_dfu_status status;
/** Effect of transfer. */
enum bt_mesh_dfu_effect effect;
};
/** DFU Target node status parameters.
* The structure should be same as
* @ref esp_ble_mesh_device_firmware_update_status_t
*/
struct bt_mesh_dfu_target_status {
/** Status of the previous operation. */
enum bt_mesh_dfu_status status;
/** Phase of the current DFU transfer. */
enum bt_mesh_dfu_phase phase;
/** The effect the update will have on the Target device's state. */
enum bt_mesh_dfu_effect effect;
/** BLOB ID used in the transfer. */
uint64_t blob_id;
/** Image index to transfer. */
uint8_t img_idx;
/** TTL used in the transfer. */
uint8_t ttl;
/** Additional response time for the Target nodes, in 10-second increments.
*
* The extra time can be used to give the Target nodes more time to respond
* to messages from the Client. The actual timeout will be calculated
* according to the following formula:
*
* @verbatim
* timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
* @endverbatim
*
* If a Target node fails to respond to a message from the Client within the
* configured transfer timeout, the Target node is dropped.
*/
uint16_t timeout_base;
};
/** @brief DFU image callback.
*
* The image callback is called for every DFU image on the Target node when
* calling @ref bt_mesh_dfu_cli_imgs_get.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context of the received message.
* @param idx Image index.
* @param total Total number of images on the Target node.
* @param img Image information for the given image index.
* @param cb_data Callback data.
*
* @retval BLE_MESH_DFU_ITER_STOP Stop iterating through the image list and
* return from @ref bt_mesh_dfu_cli_imgs_get.
* @retval BLE_MESH_DFU_ITER_CONTINUE Continue iterating through the image list
* if any images remain.
*/
typedef enum bt_mesh_dfu_iter(*bt_mesh_dfu_img_cb_t)(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx,
uint8_t idx, uint8_t total,
const struct bt_mesh_dfu_img *img,
void *cb_data);
/** Firmware Update Client event callbacks. */
struct bt_mesh_dfu_cli_cb {
/** @brief BLOB transfer is suspended.
*
* Called when the BLOB transfer is suspended due to response timeout from all Target nodes.
*
* @param cli Firmware Update Client model instance.
*/
void (*suspended)(struct bt_mesh_dfu_cli *cli);
/** @brief DFU ended.
*
* Called when the DFU transfer ends, either because all Target nodes were
* lost or because the transfer was completed successfully.
*
* @param cli Firmware Update Client model instance.
* @param reason Reason for ending.
*/
void (*ended)(struct bt_mesh_dfu_cli *cli,
enum bt_mesh_dfu_status reason);
/** @brief DFU transfer applied on all active Target nodes.
*
* Called at the end of the apply procedure started by @ref
* bt_mesh_dfu_cli_apply.
*
* @param cli Firmware Update Client model instance.
*/
void (*applied)(struct bt_mesh_dfu_cli *cli);
/** @brief DFU transfer confirmed on all active Target nodes.
*
* Called at the end of the apply procedure started by @ref
* bt_mesh_dfu_cli_confirm.
*
* @param cli Firmware Update Client model instance.
*/
void (*confirmed)(struct bt_mesh_dfu_cli *cli);
/** @brief DFU Target node was lost.
*
* A DFU Target node was dropped from the receivers list. The Target node's
* @c status is set to reflect the reason for the failure.
*
* @param cli Firmware Update Client model instance.
* @param target DFU Target node that was lost.
*/
void (*lost_target)(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_dfu_target *target);
};
enum {
STATE_IDLE,
STATE_TRANSFER,
STATE_REFRESH,
STATE_VERIFIED,
STATE_APPLY,
STATE_APPLIED,
STATE_CONFIRM,
STATE_CANCEL,
STATE_SUSPENDED,
};
typedef struct {
sys_snode_t node;
uint8_t ttl;
uint8_t type;
uint8_t img_cnt;
uint32_t opcode;
void *params;
bt_mesh_dfu_img_cb_t img_cb;
struct bt_mesh_dfu_cli *dfu_cli;
struct bt_mesh_msg_ctx ctx;
int32_t timeout;
struct k_delayed_work timer; /* Time used to get response. Only for internal use. */
} bt_mesh_dfu_cli_req_t;
/** Firmware Update Client model instance.
*
* Should be initialized with @ref BLE_MESH_DFU_CLI_INIT.
*/
struct bt_mesh_dfu_cli {
/** Callback structure. */
const struct bt_mesh_dfu_cli_cb *cb;
/** Underlying BLOB Transfer Client. */
struct bt_mesh_blob_cli blob;
/* runtime state */
uint32_t op;
struct bt_mesh_model *mod;
struct {
const struct bt_mesh_dfu_slot *slot;
const struct bt_mesh_blob_io *io;
struct bt_mesh_blob_xfer blob;
uint8_t state;
uint8_t flags;
} xfer;
bt_mesh_dfu_cli_req_t *req;
};
/** BLOB parameters for Firmware Update Client transfer: */
struct bt_mesh_dfu_cli_xfer_blob_params {
/* Logarithmic representation of the block size. */
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
};
/** Firmware Update Client transfer parameters: */
struct bt_mesh_dfu_cli_xfer {
/** BLOB ID to use for this transfer, or 0 to set it randomly. */
uint64_t blob_id;
/** DFU image slot to transfer. */
const struct bt_mesh_dfu_slot *slot;
/** Transfer mode (Push (Push BLOB Transfer Mode) or Pull (Pull BLOB Transfer Mode)) */
enum bt_mesh_blob_xfer_mode mode;
/** BLOB parameters to be used for the transfer, or NULL to retrieve Target nodes'
* capabilities before sending a firmware.
*/
const struct bt_mesh_dfu_cli_xfer_blob_params *blob_params;
};
/** @brief Start distributing a DFU.
*
* Starts distribution of the firmware in the given slot to the list of DFU
* Target nodes in @c ctx. The transfer runs in the background, and its end is
* signalled through the @ref bt_mesh_dfu_cli_cb::ended callback.
*
* @note The BLOB Transfer Client transfer inputs @c targets list must point to a list of @ref
* bt_mesh_dfu_target nodes.
*
* @param cli Firmware Update Client model instance.
* @param inputs BLOB Transfer Client transfer inputs.
* @param io BLOB stream to read BLOB from.
* @param xfer Firmware Update Client transfer parameters.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_send(struct bt_mesh_dfu_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs,
const struct bt_mesh_blob_io *io,
const struct bt_mesh_dfu_cli_xfer *xfer);
/** @brief Suspend a DFU transfer.
*
* @param cli Firmware Update Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_suspend(struct bt_mesh_dfu_cli *cli);
/** @brief Resume the suspended transfer.
*
* @param cli Firmware Update Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_resume(struct bt_mesh_dfu_cli *cli);
/** @brief Cancel a DFU transfer.
*
* Will cancel the ongoing DFU transfer, or the transfer on a specific Target
* node if @c ctx is valid.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context, or NULL to cancel the ongoing DFU transfer.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_cancel(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx);
/** @brief Apply the completed DFU transfer.
*
* A transfer can only be applied after it has ended successfully. The Firmware
* Update Client's @c applied callback is called at the end of the apply procedure.
*
* @param cli Firmware Update Client model instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_apply(struct bt_mesh_dfu_cli *cli);
/** @brief Confirm that the active transfer has been applied on the Target nodes.
*
* A transfer can only be confirmed after it has been applied. The Firmware Update
* Client's @c confirmed callback is called at the end of the confirm
* procedure.
*
* Target nodes that have reported the effect as @ref BLE_MESH_DFU_EFFECT_UNPROV
* are expected to not respond to the query, and will fail if they do.
*
* @param cli Firmware Update Client model instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_confirm(struct bt_mesh_dfu_cli *cli);
/** @brief Get progress as a percentage of completion.
*
* @param cli Firmware Update Client model instance.
*
* @return The progress of the current transfer in percent, or 0 if no
* transfer is active.
*/
uint8_t bt_mesh_dfu_cli_progress(struct bt_mesh_dfu_cli *cli);
/** @brief Check whether a DFU transfer is in progress.
*
* @param cli Firmware Update Client model instance.
*
* @return true if the BLOB Transfer Client is currently participating in a transfer,
* false otherwise.
*/
bool bt_mesh_dfu_cli_is_busy(struct bt_mesh_dfu_cli *cli);
/** @brief Perform a DFU image list request.
*
* Requests the full list of DFU images on a Target node, and iterates through
* them, calling the @c cb for every image.
*
* The DFU image list request can be used to determine which image index the
* Target node holds its different firmwares in.
*
* Waits for a response until the procedure timeout expires.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context.
* @param cb Callback to call for each image index.
* @param cb_data Callback data to pass to @c cb.
* @param first_idx Index of the first requested imgs entry.
* @param max_count Max number of images to return.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_imgs_get(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx,
bt_mesh_dfu_img_cb_t cb, void *cb_data,
uint8_t first_idx, uint8_t max_count);
/** @brief Perform a metadata check for the given DFU image slot.
*
* The metadata check procedure allows the Firmware Update Client to check if a Target
* node will accept a transfer of this DFU image slot, and what the effect would be.
*
* Waits for a response until the procedure timeout expires.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context.
* @param img_idx Target node's image index to check.
* @param metadata DFU image metadata to check for.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_metadata_check(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx, uint8_t img_idx,
struct net_buf_simple *metadata);
/** @brief Get the status of a Target node.
*
* @param cli Firmware Update Client model instance.
* @param ctx Message context.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_cli_status_get(struct bt_mesh_dfu_cli *cli,
struct bt_mesh_msg_ctx *ctx);
/** @brief Get the current procedure timeout value.
*
* @return The configured procedure timeout.
*/
int32_t bt_mesh_dfu_cli_timeout_get(void);
/** @brief Set the procedure timeout value.
*
* @param timeout The new procedure timeout.
*/
void bt_mesh_dfu_cli_timeout_set(int32_t timeout);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_blob_cli_cb _bt_mesh_dfu_cli_blob_handlers;
extern const struct bt_mesh_model_cb _bt_mesh_dfu_cli_cb;
extern const struct bt_mesh_model_op _bt_mesh_dfu_cli_op[];
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_CLI_H__ */
@@ -0,0 +1,113 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfu_metadata Bluetooth Mesh Device Firmware Update (DFU) metadata
* @ingroup bt_mesh_dfu
* @{
* @brief Common types and functions for the Bluetooth Mesh DFU metadata.
*/
#ifndef _BLE_MESH_v11_DFU_METADATA_H__
#define _BLE_MESH_v11_DFU_METADATA_H__
#include <stdint.h>
#include <sys/types.h>
#include "mesh/types.h"
#include "mesh/utils.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Firmware version. */
struct bt_mesh_dfu_metadata_fw_ver {
/** Firmware major version. */
uint8_t major;
/** Firmware minor version. */
uint8_t minor;
/** Firmware revision. */
uint16_t revision;
/** Firmware build number. */
uint32_t build_num;
};
/** Firmware core type. */
enum bt_mesh_dfu_metadata_fw_core_type {
/** Application core. */
BLE_MESH_DFU_FW_CORE_TYPE_APP = BIT(0),
/** Application-specific BLOB. */
BLE_MESH_DFU_FW_CORE_TYPE_APP_SPECIFIC_BLOB = BIT(2),
};
/** Firmware metadata. */
struct bt_mesh_dfu_metadata {
/** New firmware version. */
struct bt_mesh_dfu_metadata_fw_ver fw_ver;
/** New firmware size. */
uint32_t fw_size;
/** New firmware core type. */
enum bt_mesh_dfu_metadata_fw_core_type fw_core_type;
/** Hash of incoming Composition Data. */
uint32_t comp_hash;
/** New number of node elements. */
uint16_t elems;
/** Application-specific data for new firmware. This field is optional. */
uint8_t *user_data;
/** Length of the application-specific field. */
uint32_t user_data_len;
};
/** @brief Decode a firmware metadata from a network buffer.
*
* @param buf Buffer containing a raw metadata to be decoded.
* @param metadata Pointer to a metadata structure to be filled.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_decode(struct net_buf_simple *buf,
struct bt_mesh_dfu_metadata *metadata);
/** @brief Encode a firmware metadata into a network buffer.
*
* @param metadata Firmware metadata to be encoded.
* @param buf Buffer to store the encoded metadata.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata,
struct net_buf_simple *buf);
/** @brief Compute hash of the Composition Data state.
*
* The format of the Composition Data is defined in MshPRTv1.1: 4.2.2.1.
*
* @param buf Pointer to buffer holding Composition Data.
* @param key 128-bit key to be used in the hash computation.
* @param hash Pointer to a memory location to which the hash will be stored.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple *buf, uint8_t *key, uint32_t *hash);
/** @brief Compute hash of the Composition Data Page 0 of this device.
*
* @param key 128-bit key to be used in the hash computation.
* @param hash Pointer to a memory location to which the hash will be stored.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t *key, uint32_t *hash);
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_METADATA_H__ */
@@ -0,0 +1,264 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @defgroup bt_mesh_dfu_srv Firmware Update Server model
* @ingroup bt_mesh_dfu
* @{
* @brief API for the Bluetooth Mesh Firmware Update Server model
*/
#ifndef _BLE_MESH_v11_DFU_SRV_H__
#define _BLE_MESH_v11_DFU_SRV_H__
#include "mesh/access.h"
#include "mesh_v1.1/mbt/blob_srv.h"
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_dfu_srv;
/**
*
* @brief Initialization parameters for @ref bt_mesh_dfu_srv.
*
* @param _handlers DFU handler function structure.
* @param _imgs List of @ref bt_mesh_dfu_img managed by this Server.
* @param _img_count Number of DFU images managed by this Server.
*/
#define BLE_MESH_DFU_SRV_INIT(_handlers, _imgs, _img_count) \
{ \
.blob = { .cb = &_bt_mesh_dfu_srv_blob_cb }, .cb = _handlers, \
.imgs = _imgs, .img_count = _img_count, \
}
/**
*
* @brief Firmware Update Server model entry.
*
* @param _srv Pointer to a @ref bt_mesh_dfu_srv instance.
*/
#define BT_MESH_MODEL_DFU_SRV(_srv) \
BT_MESH_MODEL_BLOB_SRV(&(_srv)->blob), \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_DFU_SRV, _bt_mesh_dfu_srv_op, NULL, \
_srv, &_bt_mesh_dfu_srv_cb)
/** @brief Firmware Update Server event callbacks. */
struct bt_mesh_dfu_srv_cb {
/** @brief Transfer check callback.
*
* The transfer check can be used to validate the incoming transfer
* before it starts. The contents of the metadata is implementation
* specific, and should contain all the information the application
* needs to determine whether this image should be accepted, and what
* the effect of the transfer would be.
*
* If applying the image will have an effect on the provisioning state
* of the mesh stack, this can be communicated through the @c effect
* return parameter.
*
* The metadata check can be performed both as part of starting a new
* transfer and as a separate procedure.
*
* This handler is optional.
*
* @param srv Firmware Update Server instance.
* @param img DFU image the metadata check is performed on.
* @param metadata Image metadata.
* @param effect Return parameter for the image effect on the
* provisioning state of the mesh stack.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*check)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img,
struct net_buf_simple *metadata,
enum bt_mesh_dfu_effect *effect);
/** @brief Transfer start callback.
*
* Called when the Firmware Update Server is ready to start a new DFU transfer.
* The application must provide an initialized BLOB stream to be used
* during the DFU transfer.
*
* The following error codes are treated specially, and should be used
* to communicate these issues:
* - @c -ENOMEM: The device cannot fit this image.
* - @c -EBUSY: The application is temporarily unable to accept the
* transfer.
* - @c -EALREADY: The device has already received and verified this
* image, and there's no need to transfer it again. The Firmware Update model
* will skip the transfer phase, and mark the image as verified.
*
* This handler is mandatory.
*
* @param srv Firmware Update Server instance.
* @param img DFU image being updated.
* @param metadata Image metadata.
* @param io BLOB stream return parameter. Must be set to a
* valid BLOB stream by the callback.
*
* @return 0 on success, or (negative) error code otherwise. Return
* codes @c -ENOMEM, @c -EBUSY @c -EALREADY will be passed to
* the updater, other error codes are reported as internal
* errors.
*/
int (*start)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img,
struct net_buf_simple *metadata,
const struct bt_mesh_blob_io **io);
/** @brief Transfer end callback.
*
* This handler is optional.
*
* If the transfer is successful, the application should verify the
* firmware image, and call either @ref bt_mesh_dfu_srv_verified or
* @ref bt_mesh_dfu_srv_rejected depending on the outcome.
*
* If the transfer fails, the Firmware Update Server will be available for new
* transfers immediately after this function returns.
*
* @param srv Firmware Update Server instance.
* @param img DFU image that failed the update.
* @param success Whether the DFU transfer was successful.
*/
void (*end)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img, bool success);
/** @brief Transfer recovery callback.
*
* If the device reboots in the middle of a transfer, the Firmware Update Server
* calls this function when the Bluetooth Mesh subsystem is started.
*
* This callback is optional, but transfers will not be recovered after
* a reboot without it.
*
* @param srv Firmware Update Server instance.
* @param img DFU image being updated.
* @param io BLOB stream return parameter. Must be set to a valid BLOB
* stream by the callback.
*
* @return 0 on success, or (negative) error code to abandon the
* transfer.
*/
int (*recover)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img,
const struct bt_mesh_blob_io **io);
/** @brief Transfer apply callback.
*
* Called after a transfer has been validated, and the updater sends an
* apply message to the Target nodes.
*
* This handler is optional.
*
* @param srv Firmware Update Server instance.
* @param img DFU image that should be applied.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*apply)(struct bt_mesh_dfu_srv *srv,
const struct bt_mesh_dfu_img *img);
};
/** @brief Firmware Update Server instance.
*
* Should be initialized with @ref BLE_MESH_DFU_SRV_INIT.
*/
struct bt_mesh_dfu_srv {
/** Underlying BLOB Transfer Server. */
struct bt_mesh_blob_srv blob;
/** Callback structure. */
const struct bt_mesh_dfu_srv_cb *cb;
/** List of updatable images. */
const struct bt_mesh_dfu_img *imgs;
/** Number of updatable images. */
size_t img_count;
/* Runtime state */
const struct bt_mesh_model *mod;
struct {
/* Effect of transfer, @see bt_mesh_dfu_effect. */
uint8_t effect;
/* Current phase, @see bt_mesh_dfu_phase. */
uint8_t phase;
uint8_t ttl;
uint8_t idx;
uint16_t timeout_base;
uint16_t meta;
} update;
};
/** @brief Accept the received DFU transfer.
*
* Should be called at the end of a successful DFU transfer.
*
* If the DFU transfer completes successfully, the application should verify
* the image validity (including any image authentication or integrity checks),
* and call this function if the image is ready to be applied.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_verified(struct bt_mesh_dfu_srv *srv);
/** @brief Reject the received DFU transfer.
*
* Should be called at the end of a successful DFU transfer.
*
* If the DFU transfer completes successfully, the application should verify
* the image validity (including any image authentication or integrity checks),
* and call this function if one of the checks fail.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_rejected(struct bt_mesh_dfu_srv *srv);
/** @brief Cancel the ongoing DFU transfer.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_cancel(struct bt_mesh_dfu_srv *srv);
/** @brief Confirm that the received DFU transfer was applied.
*
* Should be called as a result of the @ref bt_mesh_dfu_srv_cb.apply callback.
*
* @param srv Firmware Update Server instance.
*/
void bt_mesh_dfu_srv_applied(struct bt_mesh_dfu_srv *srv);
/** @brief Check if the Firmware Update Server is busy processing a transfer.
*
* @param srv Firmware Update Server instance.
*
* @return true if a DFU procedure is in progress, false otherwise.
*/
bool bt_mesh_dfu_srv_is_busy(const struct bt_mesh_dfu_srv *srv);
/** @brief Get the progress of the current DFU procedure, in percent.
*
* @param srv Firmware Update Server instance.
*
* @return The current transfer progress in percent.
*/
uint8_t bt_mesh_dfu_srv_progress(const struct bt_mesh_dfu_srv *srv);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[];
extern const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb;
extern const struct bt_mesh_blob_srv_cb _bt_mesh_dfu_srv_blob_cb;
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_DFU_SRV_H__ */
@@ -0,0 +1,272 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_BLOB_H__
#define _BLE_MESH_v11_BLOB_H__
#include <sys/types.h>
#include "mesh/types.h"
#include "mesh/utils.h"
#include "mesh.h"
#include "mesh/utils.h"
#include "mesh/access.h"
#include "mesh/atomic.h"
#include "mesh/timer.h"
#include "mesh/compiler.h"
#include "mesh/trace.h"
#include "transport.h"
#include "mesh_v1.1/mbt/blob.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_blob Bluetooth Mesh BLOB model API
* @ingroup bt_mesh
* @{
*/
#ifndef CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX
#define CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX 0
#endif
/** BLOB transfer mode. */
enum bt_mesh_blob_xfer_mode {
/** No valid transfer mode. */
BT_MESH_BLOB_XFER_MODE_NONE,
/** Push mode (Push BLOB Transfer Mode). */
BT_MESH_BLOB_XFER_MODE_PUSH,
/** Pull mode (Pull BLOB Transfer Mode). */
BT_MESH_BLOB_XFER_MODE_PULL,
/** Both modes are valid. */
BT_MESH_BLOB_XFER_MODE_ALL,
};
/** Transfer phase. */
enum bt_mesh_blob_xfer_phase {
/** The BLOB Transfer Server is awaiting configuration. */
BT_MESH_BLOB_XFER_PHASE_INACTIVE,
/** The BLOB Transfer Server is ready to receive a BLOB transfer. */
BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START,
/** The BLOB Transfer Server is waiting for the next block of data. */
BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK,
/** The BLOB Transfer Server is waiting for the next chunk of data. */
BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK,
/** The BLOB was transferred successfully. */
BT_MESH_BLOB_XFER_PHASE_COMPLETE,
/** The BLOB transfer is paused. */
BT_MESH_BLOB_XFER_PHASE_SUSPENDED,
};
/** BLOB model status codes. */
enum bt_mesh_blob_status {
/** The message was processed successfully. */
BT_MESH_BLOB_SUCCESS,
/** The Block Number field value is not within the range of blocks being
* transferred.
*/
BT_MESH_BLOB_ERR_INVALID_BLOCK_NUM,
/** The block size is smaller than the size indicated by the Min Block
* Size Log state or is larger than the size indicated by the Max Block
* Size Log state.
*/
BT_MESH_BLOB_ERR_INVALID_BLOCK_SIZE,
/** The chunk size exceeds the size indicated by the Max Chunk Size
* state, or the number of chunks exceeds the number specified by the
* Max Total Chunks state.
*/
BT_MESH_BLOB_ERR_INVALID_CHUNK_SIZE,
/** The operation cannot be performed while the server is in the current
* phase.
*/
BT_MESH_BLOB_ERR_WRONG_PHASE,
/** A parameter value in the message cannot be accepted. */
BT_MESH_BLOB_ERR_INVALID_PARAM,
/** The message contains a BLOB ID value that is not expected. */
BT_MESH_BLOB_ERR_WRONG_BLOB_ID,
/** There is not enough space available in memory to receive the BLOB.
*/
BT_MESH_BLOB_ERR_BLOB_TOO_LARGE,
/** The transfer mode is not supported by the BLOB Transfer Server
* model.
*/
BT_MESH_BLOB_ERR_UNSUPPORTED_MODE,
/** An internal error occurred on the node. */
BT_MESH_BLOB_ERR_INTERNAL,
/** The requested information cannot be provided while the server is in
* the current phase.
*/
BT_MESH_BLOB_ERR_INFO_UNAVAILABLE,
};
/** BLOB transfer data block. */
struct bt_mesh_blob_block {
/** Block size in bytes */
size_t size;
/** Offset in bytes from the start of the BLOB. */
off_t offset;
/** Block number */
uint16_t number;
/** Number of chunks in block. */
uint16_t chunk_count;
/** Bitmap of missing chunks. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX,
8)];
};
/** BLOB data chunk. */
struct bt_mesh_blob_chunk {
/** Offset of the chunk data from the start of the block. */
off_t offset;
/** Chunk data size. */
size_t size;
/** Chunk data. */
uint8_t *data;
};
/** BLOB transfer. */
struct bt_mesh_blob_xfer {
/** BLOB ID. */
uint64_t id;
/** Total BLOB size in bytes. */
size_t size;
/** BLOB transfer mode. */
enum bt_mesh_blob_xfer_mode mode;
/* Logarithmic representation of the block size. */
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
};
/** BLOB stream interaction mode. */
enum bt_mesh_blob_io_mode {
/** Read data from the stream. */
BT_MESH_BLOB_READ,
/** Write data to the stream. */
BT_MESH_BLOB_WRITE,
};
/** BLOB stream. */
struct bt_mesh_blob_io {
/** @brief Open callback.
*
* Called when the reader is opened for reading.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param mode Direction of the stream (read/write).
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*open)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
enum bt_mesh_blob_io_mode mode);
/** @brief Close callback.
*
* Called when the reader is closed.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
*/
void (*close)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer);
/** @brief Block start callback.
*
* Called when a new block is opened for sending. Each block is only
* sent once, and are always sent in increasing order. The data chunks
* inside a single block may be requested out of order and multiple
* times.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that was started.
*/
int (*block_start)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block);
/** @brief Block end callback.
*
* Called when the current block has been transmitted in full.
* No data from this block will be requested again, and the application
* data associated with this block may be discarded.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block that finished sending.
*/
void (*block_end)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block);
/** @brief Chunk data write callback.
*
* Used by the BLOB Transfer Server on incoming data.
*
* Each block is divided into chunks of data. This callback is called
* when a new chunk of data is received. Chunks may be received in
* any order within their block.
*
* If the callback returns successfully, this chunk will be marked as
* received, and will not be received again unless the block is
* restarted due to a transfer suspension. If the callback returns a
* non-zero value, the chunk remains unreceived, and the BLOB Transfer
* Client will attempt to resend it later.
*
* Note that the Client will only perform a limited number of attempts
* at delivering a chunk before dropping a Target node from the transfer.
* The number of retries performed by the Client is implementation
* specific.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Received chunk.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*wr)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block,
const struct bt_mesh_blob_chunk *chunk);
/** @brief Chunk data read callback.
*
* Used by the BLOB Transfer Client to fetch outgoing data.
*
* The Client calls the chunk data request callback to populate a chunk
* message going out to the Target nodes. The data request callback
* may be called out of order and multiple times for each offset, and
* cannot be used as an indication of progress.
*
* Returning a non-zero status code on the chunk data request callback
* results in termination of the transfer.
*
* @param io BLOB stream.
* @param xfer BLOB transfer.
* @param block Block the chunk is part of.
* @param chunk Chunk to get the data of. The buffer pointer to by the
* @c data member should be filled by the callback.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int (*rd)(const struct bt_mesh_blob_io *io,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_block *block,
const struct bt_mesh_blob_chunk *chunk);
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_BLOB_H__ */
@@ -0,0 +1,467 @@
/*
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_v11_BLOB_CLI_H_
#define _BLE_MESH_v11_BLOB_CLI_H_
#include <sys/types.h>
#include "mesh/access.h"
#include "mesh/utils.h"
#include "mesh.h"
#include "mesh/utils.h"
#include "mesh/access.h"
#include "mesh/atomic.h"
#include "mesh/timer.h"
#include "mesh/compiler.h"
#include "mesh/trace.h"
#include "transport.h"
#include "mesh_v1.1/mbt/blob.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_mesh_blob_cli Bluetooth Mesh BLOB Transfer Client model API
* @ingroup bt_mesh
* @{
*/
struct bt_mesh_blob_cli;
/**
*
* @brief BLOB Transfer Client model Composition Data entry.
*
* @param _cli Pointer to a @ref bt_mesh_blob_cli instance.
*/
#define BT_MESH_MODEL_BLOB_CLI(_cli) \
BLE_MESH_MODEL_CB(BLE_MESH_MODEL_ID_BLOB_CLI, _bt_mesh_blob_cli_op, \
NULL, _cli, &_bt_mesh_blob_cli_cb)
/** Target node's Pull mode (Pull BLOB Transfer Mode) context used
* while sending chunks to the Target node.
*/
struct bt_mesh_blob_target_pull {
/** Timestamp when the Block Report Timeout Timer expires for this Target node. */
int64_t block_report_timestamp;
/** Missing chunks reported by this Target node. */
uint8_t missing[DIV_ROUND_UP(CONFIG_BLE_MESH_BLOB_CHUNK_COUNT_MAX, 8)];
};
/** BLOB Transfer Client Target node. */
struct bt_mesh_blob_target {
/** Linked list node */
sys_snode_t n;
/** Target node address. */
uint16_t addr;
/** Target node's Pull mode context.
* Needs to be initialized when sending a BLOB in Pull mode.
*/
struct bt_mesh_blob_target_pull *pull;
/** BLOB transfer status, see @ref bt_mesh_blob_status. */
uint8_t status;
uint8_t procedure_complete: 1, /* Procedure has been completed. */
acked: 1, /* Message has been acknowledged. Not used when sending. */
timedout: 1, /* Target node didn't respond after specified timeout. */
skip: 1; /* Skip Target node from broadcast. */
};
/** BLOB transfer information.
*
* If @c phase is @ref BT_MESH_BLOB_XFER_PHASE_INACTIVE,
* the fields below @c phase are not initialized.
* If @c phase is @ref BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START,
* the fields below @c id are not initialized.
*/
struct bt_mesh_blob_xfer_info {
/** BLOB transfer status. */
enum bt_mesh_blob_status status;
/** BLOB transfer mode. */
enum bt_mesh_blob_xfer_mode mode;
/** BLOB transfer phase. */
enum bt_mesh_blob_xfer_phase phase;
/** BLOB ID. */
uint64_t id;
/** BLOB size in octets. */
uint32_t size;
/** Logarithmic representation of the block size. */
uint8_t block_size_log;
/** MTU size in octets. */
uint16_t mtu_size;
/** Bit field indicating blocks that were not received. */
const uint8_t *missing_blocks;
};
/** BLOB Transfer Client transfer inputs. */
struct bt_mesh_blob_cli_inputs {
/** Linked list of Target nodes. Each node should point to @ref
* bt_mesh_blob_target::n.
*/
sys_slist_t targets;
/** AppKey index to send with. */
uint16_t app_idx;
/** Group address destination for the BLOB transfer, or @ref
* BLE_MESH_ADDR_UNASSIGNED to send every message to each Target
* node individually.
*/
uint16_t group;
/** Time to live value of BLOB transfer messages. */
uint8_t ttl;
/** Additional response time for the Target nodes, in 10-second increments.
*
* The extra time can be used to give the Target nodes more time to respond
* to messages from the Client. The actual timeout will be calculated
* according to the following formula:
*
* @verbatim
* timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)
* @endverbatim
*
* If a Target node fails to respond to a message from the Client within the
* configured transfer timeout, the Target node is dropped.
*/
uint16_t timeout_base;
};
/** Transfer capabilities of a Target node. */
struct bt_mesh_blob_cli_caps {
/** Max BLOB size. */
size_t max_size;
/** Logarithmic representation of the minimum block size. */
uint8_t min_block_size_log;
/** Logarithmic representation of the maximum block size. */
uint8_t max_block_size_log;
/** Max number of chunks per block. */
uint16_t max_chunks;
/** Max chunk size. */
uint16_t max_chunk_size;
/** Max MTU size. */
uint16_t mtu_size;
/** Supported transfer modes. */
enum bt_mesh_blob_xfer_mode modes;
};
/** BLOB Transfer Client state. */
enum bt_mesh_blob_cli_state {
/** No transfer is active. */
BT_MESH_BLOB_CLI_STATE_NONE,
/** Retrieving transfer capabilities. */
BT_MESH_BLOB_CLI_STATE_CAPS_GET,
/** Sending transfer start. */
BT_MESH_BLOB_CLI_STATE_START,
/** Sending block start. */
BT_MESH_BLOB_CLI_STATE_BLOCK_START,
/** Sending block chunks. */
BT_MESH_BLOB_CLI_STATE_BLOCK_SEND,
/** Checking block status. */
BT_MESH_BLOB_CLI_STATE_BLOCK_CHECK,
/** Checking transfer status. */
BT_MESH_BLOB_CLI_STATE_XFER_CHECK,
/** Cancelling transfer. */
BT_MESH_BLOB_CLI_STATE_CANCEL,
/** Transfer is suspended. */
BT_MESH_BLOB_CLI_STATE_SUSPENDED,
/** Checking transfer progress. */
BT_MESH_BLOB_CLI_STATE_XFER_PROGRESS_GET,
};
/** Event handler callbacks for the BLOB Transfer Client model.
*
* All handlers are optional.
*/
struct bt_mesh_blob_cli_cb {
/** @brief Capabilities retrieval completion callback.
*
* Called when the capabilities retrieval procedure completes, indicating that
* a common set of acceptable transfer parameters have been established
* for the given list of Target nodes. All compatible Target nodes have
* status code @ref BT_MESH_BLOB_SUCCESS.
*
* @param cli BLOB Transfer Client instance.
* @param caps Safe transfer capabilities if the transfer capabilities
* of at least one Target node has satisfied the Client, or NULL otherwise.
*/
void (*caps)(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_caps *caps);
/** @brief Target node loss callback.
*
* Called whenever a Target node has been lost due to some error in the
* transfer. Losing a Target node is not considered a fatal error for
* the Client until all Target nodes have been lost.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that was lost.
* @param reason Reason for the Target node loss.
*/
void (*lost_target)(struct bt_mesh_blob_cli *cli,
struct bt_mesh_blob_target *target,
enum bt_mesh_blob_status reason);
/** @brief Transfer is suspended.
*
* Called when the transfer is suspended due to response timeout from all Target nodes.
*
* @param cli BLOB Transfer Client instance.
*/
void (*suspended)(struct bt_mesh_blob_cli *cli);
/** @brief Transfer end callback.
*
* Called when the transfer ends.
*
* @param cli BLOB Transfer Client instance.
* @param xfer Completed transfer.
* @param success Status of the transfer.
* Is @c true if at least one Target
* node received the whole transfer.
*/
void (*end)(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_xfer *xfer, bool success);
/** @brief Transfer progress callback
*
* The content of @c info is invalidated upon exit from the callback.
* Therefore it needs to be copied if it is planned to be used later.
*
* @param cli BLOB Transfer Client instance.
* @param target Target node that responded to the request.
* @param info BLOB transfer information.
*/
void (*xfer_progress)(struct bt_mesh_blob_cli *cli,
struct bt_mesh_blob_target *target,
const struct bt_mesh_blob_xfer_info *info);
/** @brief End of Get Transfer Progress procedure.
*
* Called when all Target nodes have responded or the procedure timed-out.
*
* @param cli BLOB Transfer Client instance.
*/
void (*xfer_progress_complete)(struct bt_mesh_blob_cli *cli);
};
/** @cond INTERNAL_HIDDEN */
struct blob_cli_broadcast_ctx {
/** Called for every Target node in unicast mode, or once in case of multicast mode. */
void (*send)(struct bt_mesh_blob_cli *cli, uint16_t dst);
/** Called after every @ref blob_cli_broadcast_ctx::send callback. */
void (*send_complete)(struct bt_mesh_blob_cli *cli, uint16_t dst);
/** If @ref blob_cli_broadcast_ctx::acked is true, called after all Target nodes
* have confirmed reception by @ref blob_cli_broadcast_rsp. Otherwise, called
* after transmission has been completed.
*/
void (*next)(struct bt_mesh_blob_cli *cli);
/** If true, every transmission needs to be confirmed by @ref blob_cli_broadcast_rsp before
* @ref blob_cli_broadcast_ctx::next is called.
*/
bool acked;
/** If true, the message is always sent in a unicast way. */
bool force_unicast;
/** If true, non-responsive Target nodes won't be dropped after transfer has timed out. */
bool optional;
/** Set to true by the BLOB Transfer Client between blob_cli_broadcast
* and broadcast_complete calls.
*/
bool is_inited;
/* Defines a time in ms by which the broadcast API postpones sending the message to a next
* target or completing the broadcast.
*/
uint32_t post_send_delay_ms;
};
/** INTERNAL_HIDDEN @endcond */
/** BLOB Transfer Client model instance. */
struct bt_mesh_blob_cli {
/** Event handler callbacks */
const struct bt_mesh_blob_cli_cb *cb;
/* Runtime state */
const struct bt_mesh_model *mod;
struct {
struct bt_mesh_blob_target *target;
struct blob_cli_broadcast_ctx ctx;
struct k_work_delayable retry;
/* Represents Client Timeout timer in a timestamp. Used in Pull mode only. */
int64_t cli_timestamp;
struct k_work_delayable complete;
uint16_t pending;
uint8_t retries;
uint8_t sending : 1,
cancelled : 1;
} tx;
const struct bt_mesh_blob_io *io;
const struct bt_mesh_blob_cli_inputs *inputs;
const struct bt_mesh_blob_xfer *xfer;
uint32_t chunk_interval_ms;
uint16_t block_count;
uint16_t chunk_idx;
uint16_t mtu_size;
enum bt_mesh_blob_cli_state state;
struct bt_mesh_blob_block block;
struct bt_mesh_blob_cli_caps caps;
};
/** @brief Retrieve transfer capabilities for a list of Target nodes.
*
* Queries the availability and capabilities of all Target nodes, producing a
* cumulative set of transfer capabilities for the Target nodes, and returning
* it through the @ref bt_mesh_blob_cli_cb::caps callback.
*
* Retrieving the capabilities may take several seconds, depending on the
* number of Target nodes and mesh network performance. The end of the procedure
* is indicated through the @ref bt_mesh_blob_cli_cb::caps callback.
*
* This procedure is not required, but strongly recommended as a
* preparation for a transfer to maximize performance and the chances of
* success.
*
* @param cli BLOB Transfer Client instance.
* @param inputs Statically allocated BLOB Transfer Client transfer inputs.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_caps_get(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs);
/** @brief Perform a BLOB transfer.
*
* Starts sending the transfer to the Target nodes. Only Target nodes with a
* @c status of @ref BT_MESH_BLOB_SUCCESS will be considered.
*
* The transfer will keep going either until all Target nodes have been dropped, or
* the full BLOB has been sent.
*
* The BLOB transfer may take several minutes, depending on the number of
* Target nodes, size of the BLOB and mesh network performance. The end of the
* transfer is indicated through the @ref bt_mesh_blob_cli_cb::end callback.
*
* A Client only supports one transfer at the time.
*
* @param cli BLOB Transfer Client instance.
* @param inputs Statically allocated BLOB Transfer Client transfer inputs.
* @param xfer Statically allocated transfer parameters.
* @param io BLOB stream to read the transfer from.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_send(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs,
const struct bt_mesh_blob_xfer *xfer,
const struct bt_mesh_blob_io *io);
/** @brief Suspend the active transfer.
*
* @param cli BLOB Transfer Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_suspend(struct bt_mesh_blob_cli *cli);
/** @brief Resume the suspended transfer.
*
* @param cli BLOB Transfer Client instance.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_resume(struct bt_mesh_blob_cli *cli);
/** @brief Cancel an ongoing transfer.
*
* @param cli BLOB Transfer Client instance.
*/
void bt_mesh_blob_cli_cancel(struct bt_mesh_blob_cli *cli);
void bt_mesh_blob_cli_send_cancel(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_xfer *xfer);
/** @brief Get the progress of BLOB transfer.
*
* This function can only be used if the BLOB Transfer Client is currently
* not performing a BLOB transfer.
* To get progress of the active BLOB transfer, use the
* @ref bt_mesh_blob_cli_xfer_progress_active_get function.
*
* @param cli BLOB Transfer Client instance.
* @param inputs Statically allocated BLOB Transfer Client transfer inputs.
*
* @return 0 on success, or (negative) error code otherwise.
*/
int bt_mesh_blob_cli_xfer_progress_get(struct bt_mesh_blob_cli *cli,
const struct bt_mesh_blob_cli_inputs *inputs);
/** @brief Get the current progress of the active transfer in percent.
*
* @param cli BLOB Transfer Client instance.
*
* @return The current transfer progress, or 0 if no transfer is active.
*/
uint8_t bt_mesh_blob_cli_xfer_progress_active_get(struct bt_mesh_blob_cli *cli);
/** @brief Get the current state of the BLOB Transfer Client.
*
* @param cli BLOB Transfer Client instance.
*
* @return true if the BLOB Transfer Client is currently participating in a transfer or
* retrieving the capabilities and false otherwise.
*/
bool bt_mesh_blob_cli_is_busy(struct bt_mesh_blob_cli *cli);
/** @brief Set chunk sending interval in ms
*
* This function is optional, and can be used to define how fast chunks are sent in the BLOB Client
* Model.
* Without an added delay, for example a Bluetooth Mesh DFU can cause network blockage by
* constantly sending the next chunks, especially if the chunks are sent to group addresses or
* multiple unicast addresses.
*
* @note: Big intervals may cause timeouts. Increasing the @c timeout_base accordingly can
* circumvent this.
*
* @param cli BLOB Transfer Client instance.
* @param interval_ms the delay before each chunk is sent out in ms.
*/
void bt_mesh_blob_cli_set_chunk_interval_ms(struct bt_mesh_blob_cli *cli, uint32_t interval_ms);
/** @cond INTERNAL_HIDDEN */
extern const struct bt_mesh_model_op _bt_mesh_blob_cli_op[];
extern const struct bt_mesh_model_cb _bt_mesh_blob_cli_cb;
/** @endcond */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_v11_BLOB_CLI_H_ */

Some files were not shown because too many files have changed in this diff Show More