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
@@ -302,10 +302,12 @@ error_t apiEventSubscribe(Device* device, WifiEventSubscription* sub, TaskEventG
mutex_lock(&ctx->subscriptionsMutex);
// Avoid cyclic subscription list that would loop forever
if (ctx->subscriptions == sub) {
mutex_unlock(&ctx->subscriptionsMutex);
task_event_group_release_bit(event_group, bit);
return ERROR_INVALID_STATE;
for (WifiEventSubscription* existing = ctx->subscriptions; existing != nullptr; existing = existing->internal.next) {
if (existing == sub) {
mutex_unlock(&ctx->subscriptionsMutex);
task_event_group_release_bit(event_group, bit);
return ERROR_INVALID_STATE;
}
}
sub->internal.event_group = event_group;
@@ -382,12 +384,16 @@ error_t stopDevice(Device* device) {
// Release any subscribers that never unsubscribed: device_stop() doesn't wait for apps still
// using this device, so a later wifi_event_unsubscribe() would find no ctx and skip releasing
// the bit and destructing sub->internal.ring_mutex.
// the bit.
mutex_lock(&ctx->subscriptionsMutex);
for (WifiEventSubscription* sub = ctx->subscriptions; sub != nullptr;) {
WifiEventSubscription* next = sub->internal.next;
// Force-close, don't destruct: a concurrent wifi_event_poll() may hold/await this same
// lock (see WifiEventSubscription::internal::closed).
mutex_lock(&sub->internal.ring_mutex);
sub->internal.closed = true;
mutex_unlock(&sub->internal.ring_mutex);
task_event_group_release_bit(sub->internal.event_group, sub->bit);
mutex_destruct(&sub->internal.ring_mutex);
sub = next;
}
ctx->subscriptions = nullptr;