Bluetooth and Wi-Fi improvements (#622)

- Enable BT by default in DTS, and create separate radio on/of functionality (like recent Wi-Fi changes)
- Bluetooth event handling now uses queued subscriptions, improving event delivery and application responsiveness.
- Improved synchronization of Bluetooth advertising, connections, HID, MIDI, and SPP operations.
- Enhanced cleanup during Bluetooth shutdown and subscription removal.
- Clarified Bluetooth start and stop behavior.
- Improved wifi driver subscription stability to prevent endless loops
This commit is contained in:
Ken Van Hoeylandt
2026-08-26 00:30:03 +02:00
committed by GitHub
parent ab75d2022d
commit 0ee2415f3b
50 changed files with 458 additions and 270 deletions
@@ -7,9 +7,6 @@
#include <Tactility/bluetooth/Bluetooth.h>
#include <tactility/drivers/bluetooth.h>
#include <atomic>
#include <memory>
namespace tt::app::btmanage {
struct Context {
@@ -19,13 +16,7 @@ struct Context {
State state;
View view = View(&bindings, &state);
Device* btDevice = nullptr;
bool callbackRegistered = false;
// Bumped right before the BT event callback is unregistered at the end of appMain(), to
// invalidate any BT event already dispatched to the main task for this instance. Kept in
// its own heap allocation, independent of Context's (stack-local) lifetime, so a dispatched
// callback can check it without touching a possibly already-destroyed Context.
std::shared_ptr<std::atomic<int>> generation = std::make_shared<std::atomic<int>>(0);
BtEventSubscription btEventSub {};
void lock() { mutex.lock(); }
void unlock() { mutex.unlock(); }
@@ -34,15 +25,4 @@ struct Context {
void onBtEvent(Context* ctx, const struct BtEvent& event);
void requestViewUpdate(Context* ctx);
// Re-attempts registering the device event callback. Needed because the BLE driver only
// allocates its callback list while the device is started/on: a registration attempted while
// the radio is off silently no-ops, so this must be called again right after a successful
// bluetooth::start(). Idempotent: no-ops if already registered for this device.
void registerDeviceCallback(Context* ctx, Device* dev);
// Call after bluetooth::stop(): the driver frees its callback list on stop, so the
// registration state must be cleared here too, without touching the (now-dangling) driver-side
// list.
void forgetCallbackRegistration(Context* ctx);
} // namespace tt::app::btmanage