Skip to content

Add Trouble BLE Support over ESP-IDF VHCI - #677

Open
dickermoshe wants to merge 4 commits into
esp-rs:masterfrom
dickermoshe:feat/trouble-vhci
Open

Add Trouble BLE Support over ESP-IDF VHCI#677
dickermoshe wants to merge 4 commits into
esp-rs:masterfrom
dickermoshe:feat/trouble-vhci

Conversation

@dickermoshe

Copy link
Copy Markdown

Thank you for your contribution!

We appreciate the time and effort you've put into this pull request.
To help us review it efficiently, please ensure you've gone through the following checklist:

Submission Checklist 📝

  • I have updated existing examples or added new ones (if applicable).
  • I have used cargo fmt command to ensure that all changed code is formatted correctly.
  • I have used cargo clippy command to ensure that all changed code passes latest Clippy nightly lints.
  • My changes were added to the CHANGELOG.md in the proper section.

Pull Request Details 📖

Description

This crate already includes support for ESP-IDF’s Bluedroid and NimBLE BLE stacks. However, the Trouble crate makes it much easier to create Bluetooth Low Energy applications.

This PR introduces Trouble support by implementing the bt-hci traits. This is also how the esp-radio crate enables Bluetooth for devices not using esp-idf

In addition to the changes included here, there was also an issue with nightly Rust not working with some upstream changes in the Rust compiler. To be honest, I'm not sure what it is. To have CI pass, I've capped the nightly release to nightly-2026-07-29, but I'm sure this is not how you want to fix it. If you could let me know how you want to fix it, I'll do whatever you want.

Testing

I added a small Trouble beacon example to exercise the controller and VHCI transport together.

@ivmarkov ivmarkov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking the time and effort!

I think exposing the controller might have some small benefits indeed (like running trouble on top of esp-idf-svc) so I'm not opposed to it in general.

We just have to be careful how to do it so that we don't reintroduce a ton of dependencies that might be a bit of a headache to support in future, as the benefit exists but is not that big.

For one, the host in trouble is not certified, and it is unclear when or if Espressif would certify trouble as the BLE host to be used for their esp-hal baremetal portfolio.

... and Espressif would almost never, ever certify trouble on top of the community-maintained esp-idf-* crates.

In fact, one major reason I'm keeping the esp-idf-* crates alive - in the presence of esp-hal - is that they run on top of ESP-IDF and as such inherit the certified status of the Wifi, Thread and BT stacks (both NimBLE host for which APIs were just introduced and Bluedroid host) of ESP-IDF. None of these three are certified in esp-hal yet, which is a bit of a roadblock for production (as opposed to hobby) use-cases. Running trouble-host on top of ESP-IDF would of course not be a certified setup.

CONFIG_BT_LE_ACL_BUF_SIZE=251

# The Trouble runner and host resources exceed ESP-IDF's default main-task stack.
CONFIG_ESP_MAIN_TASK_STACK_SIZE=32768

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HostResources should not be allocated on-stack, but staticlaly in bss or on heap. It is another topic that they regressed it recently, where such an allocation was not possible anymore due to the Controller re-generification. Fortunately, fixed in main: embassy-rs/trouble#645


env:
rust_toolchain: nightly
# Temporary workaround for rust-lang/rust#158168. Remove after the fix reaches nightly:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert, this script does not run every day.

rust_toolchain: nightly
# Temporary workaround for rust-lang/rust#158168. Remove after the fix reaches nightly:
# https://github.com/rust-lang/rust/pull/160170
rust_toolchain: nightly-2026-07-29

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

type Controller = ExternalController<EspVhciTransport<'static>, 10>;

pub fn main() -> Result<()> {
esp_idf_svc::sys::link_patches();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer necessary, as it is called automatically by the startup code in esp-idf-sys. The other two explicit link calls should also not be necessary, unless you hit an actual linking issue.

@@ -0,0 +1,335 @@
#[cfg(not(esp_idf_bt_controller_only))]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the primary driver for implementing the bt-hci traits on top of esp-idf-svc is to run trouble on top of it:

  • Naming the bti-hci controller module trouble is incorrect. In theory there could be other BLE hosts that could use it
  • Hiding this code behind a feature named trouble is also not ideal for the same reasons. Furthermore, hiding this code behind a feature in the first place seems unnecessary?

I suggest:

  • Remove the trouble feature altogether. Whether the bt-hci support is compiled-in or compiled-out should only depend on the esp_idf_* flags
  • Merge bt_controller/trouble.rs into bt_controller.rs. What is this separation supposed to model anyway?

Comment thread src/lib.rs
feature = "alloc",
))]
pub mod bt;
#[cfg(all(not(any(esp32s2, esp32p4)), esp_idf_bt_enabled, feature = "trouble",))]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add feature alloc, remove feature trouble, etc.

Comment thread Cargo.toml
alloc = ["esp-idf-hal/alloc", "embedded-svc/alloc", "uncased/alloc"]
nightly = ["embedded-svc/nightly", "esp-idf-hal/nightly"]
experimental = ["embedded-svc/experimental", "esp-idf-hal/experimental"]
trouble = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Comment thread Cargo.toml
embassy-futures = "0.1.2"
embedded-storage = { version = "0.3", optional = true }
futures-io = { version = "0.3", optional = true }
bt-hci = { version = "0.9", optional = true, default-features = false }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the trouble feature would mean bt-hci becomes non-optional. Oh well. See also my previous comment on bt-hci-drvier (= bt-hci-transport) as a (much better) alternative.

Comment thread Cargo.toml
futures-io = { version = "0.3", optional = true }
bt-hci = { version = "0.9", optional = true, default-features = false }
embassy-sync = { version = "0.7", optional = true }
embedded-io = { version = "0.7", optional = true }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessary to list explicitly. comes via embedded-svc anyway

Comment thread Cargo.toml
embedded-storage = { version = "0.3", optional = true }
futures-io = { version = "0.3", optional = true }
bt-hci = { version = "0.9", optional = true, default-features = false }
embassy-sync = { version = "0.7", optional = true }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my earlier comment, let's try not to introduce this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants