diff --git a/Documentation/ideas.md b/Documentation/ideas.md index 9aafe7368..c12417b63 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -13,7 +13,6 @@ ## Higher Priority -- Bluetooth app: when toggling BT on, it doesn't update the UI with discovered devices. It only works after re-opening the app. - display.h API: get_backlight does not change ref counting, but it should - bluetooth: various getters for child devices do not change ref counting, but they should - Improve kernel_init.cpp (and other modules): create driver_ensure_added() and driver_ensure_destructed() diff --git a/Tactility/Private/Tactility/app/btmanage/BtManagePrivate.h b/Tactility/Private/Tactility/app/btmanage/BtManagePrivate.h index c22fe7d0e..e271a8800 100644 --- a/Tactility/Private/Tactility/app/btmanage/BtManagePrivate.h +++ b/Tactility/Private/Tactility/app/btmanage/BtManagePrivate.h @@ -35,6 +35,12 @@ public: State& getState() { return state; } void requestViewUpdate(); + + // 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(). + void registerDeviceCallback(Device* dev); }; } // namespace tt::app::btmanage diff --git a/Tactility/Source/app/btmanage/BtManage.cpp b/Tactility/Source/app/btmanage/BtManage.cpp index 33fc08452..72172a3d9 100644 --- a/Tactility/Source/app/btmanage/BtManage.cpp +++ b/Tactility/Source/app/btmanage/BtManage.cpp @@ -23,7 +23,13 @@ static void onBtToggled(bool requestOn) { bool radio_on = bluetooth::isRadioOnOrPending(dev); if (requestOn && !radio_on) { LOG_I(TAG, "Turning on"); - bluetooth::start(dev); + if (bluetooth::start(dev)) { + // The driver only allocates its callback list once the device is started, + // so the registration attempted in onShow() (while radio was off) was a + // no-op. Register again now that the device is actually up. + auto bt = std::static_pointer_cast(getCurrentApp()); + bt->registerDeviceCallback(dev); + } } else if (!requestOn && radio_on) { LOG_I(TAG, "Turning off"); bluetooth::stop(dev); @@ -153,12 +159,20 @@ static void onKernelBtEvent(Device* /*device*/, void* context, BtEvent event) { }); } +void BtManage::registerDeviceCallback(Device* dev) { + lock(); + if (btDevice == dev) { + bluetooth_add_event_callback(dev, this, onKernelBtEvent); + } + unlock(); +} + void BtManage::onShow(AppContext& app, lv_obj_t* parent) { // Initialise state and view before subscribing to avoid incoming events // racing with state initialisation. state.setRadioState(bluetooth::getRadioState()); Device* dev = nullptr; - device_get_first_active_by_type(&BLUETOOTH_TYPE, &dev); + device_get_first_by_type(&BLUETOOTH_TYPE, &dev); state.setScanning(dev ? bluetooth_is_scanning(dev) : false); state.updateScanResults();